Subversion Repositories HelenOS-historic

Compare Revisions

Ignore whitespace Rev 1083 → Rev 1084

/kernel/trunk/generic/src/ipc/ipc.c
49,6 → 49,14
 
static slab_cache_t *ipc_call_slab;
 
/* Initialize new call */
static void _ipc_call_init(call_t *call)
{
memsetb((__address)call, sizeof(*call), 0);
call->callerbox = &TASK->answerbox;
call->sender = TASK;
}
 
/** Allocate & initialize call structure
*
* The call is initialized, so that the reply will be directed
59,19 → 67,16
call_t *call;
 
call = slab_alloc(ipc_call_slab, 0);
memsetb((__address)call, sizeof(*call), 0);
call->callerbox = &TASK->answerbox;
call->sender = TASK;
_ipc_call_init(call);
 
return call;
}
 
/** Initialize allocated call */
void ipc_call_init(call_t *call)
void ipc_call_static_init(call_t *call)
{
call->callerbox = &TASK->answerbox;
call->flags = IPC_CALL_STATIC_ALLOC;
call->sender = TASK;
_ipc_call_init(call);
call->flags |= IPC_CALL_STATIC_ALLOC;
}
 
/** Deallocate call stracuture */
96,6 → 101,8
/** Connect phone to answerbox */
void ipc_phone_connect(phone_t *phone, answerbox_t *box)
{
spinlock_lock(&phone->lock);
 
ASSERT(!phone->callee);
phone->busy = 1;
phone->callee = box;
103,6 → 110,8
spinlock_lock(&box->lock);
list_append(&phone->list, &box->connected_phones);
spinlock_unlock(&box->lock);
 
spinlock_unlock(&phone->lock);
}
 
/** Initialize phone structure and connect phone to naswerbox
114,7 → 123,10
phone->busy = 0;
}
 
/** Disconnect phone from answerbox */
/** Disconnect phone from answerbox
*
* It is allowed to call disconnect on already disconnected phone\
*/
void ipc_phone_destroy(phone_t *phone)
{
answerbox_t *box = phone->callee;
121,9 → 133,16
ASSERT(box);
 
spinlock_lock(&phone->lock);
spinlock_lock(&box->lock);
list_remove(&phone->list);
 
if (phone->callee) {
list_remove(&phone->list);
phone->callee = NULL;
}
 
spinlock_unlock(&box->lock);
spinlock_unlock(&phone->lock);
}
 
/** Helper function to facilitate synchronous calls */
140,6 → 159,37
ipc_wait_for_call(&sync_box, 0);
}
 
/** Answer message that was not dispatched and is not entered in
* any queue
*/
static void _ipc_answer_free_call(call_t *call)
{
answerbox_t *callerbox = call->callerbox;
 
call->flags &= ~IPC_CALL_DISPATCHED;
call->flags |= IPC_CALL_ANSWERED;
 
spinlock_lock(&callerbox->lock);
list_append(&call->list, &callerbox->answers);
spinlock_unlock(&callerbox->lock);
waitq_wakeup(&callerbox->wq, 0);
}
 
/** Answer message, that is in callee queue
*
* @param box Answerbox that is answering the message
* @param call Modified request that is being sent back
*/
void ipc_answer(answerbox_t *box, call_t *call)
{
/* Remove from active box */
spinlock_lock(&box->lock);
list_remove(&call->list);
spinlock_unlock(&box->lock);
/* Send back answer */
_ipc_answer_free_call(call);
}
 
/** Send a asynchronous request using phone to answerbox
*
* @param phone Phone connected to answerbox
147,14 → 197,23
*/
void ipc_call(phone_t *phone, call_t *call)
{
answerbox_t *box = phone->callee;
answerbox_t *box;
 
ASSERT(box);
spinlock_lock(&phone->lock);
box = phone->callee;
if (!box) {
/* Trying to send over disconnected phone */
IPC_SET_RETVAL(call->data, ENOENT);
_ipc_answer_free_call(call);
return;
}
 
spinlock_lock(&box->lock);
list_append(&call->list, &box->calls);
spinlock_unlock(&box->lock);
waitq_wakeup(&box->wq, 0);
spinlock_unlock(&phone->lock);
}
 
/** Forwards call from one answerbox to a new one
163,40 → 222,16
* @param newbox Target answerbox
* @param oldbox Old answerbox
*/
void ipc_forward(call_t *call, answerbox_t *newbox, answerbox_t *oldbox)
void ipc_forward(call_t *call, phone_t *newphone, answerbox_t *oldbox)
{
spinlock_lock(&oldbox->lock);
list_remove(&call->list);
spinlock_unlock(&oldbox->lock);
 
spinlock_lock(&newbox->lock);
list_append(&call->list, &newbox->calls);
spinlock_lock(&newbox->lock);
waitq_wakeup(&newbox->wq, 0);
ipc_call(newphone, call);
}
 
/** Answer message back to phone
*
* @param box Answerbox that is answering the message
* @param request Modified request that is being sent back
*/
void ipc_answer(answerbox_t *box, call_t *request)
{
answerbox_t *callerbox = request->callerbox;
 
request->flags &= ~IPC_CALL_DISPATCHED;
request->flags |= IPC_CALL_ANSWERED;
 
spinlock_lock(&box->lock);
list_remove(&request->list);
spinlock_unlock(&box->lock);
 
spinlock_lock(&callerbox->lock);
list_append(&request->list, &callerbox->answers);
spinlock_unlock(&callerbox->lock);
waitq_wakeup(&callerbox->wq, 0);
}
 
/** Wait for phone call
*
* @return Recived message address