Subversion Repositories HelenOS-historic

Compare Revisions

Ignore whitespace Rev 1140 → Rev 1141

/kernel/trunk/generic/src/ipc/ipcrsc.c
129,13 → 129,25
 
/** Find call_t * in call table according to callid
*
* TODO: Some speedup (hash table?)
* @return NULL on not found, otherwise pointer to call structure
*/
call_t * get_call(__native callid)
{
/* TODO: Traverse list of dispatched calls and find one */
/* TODO: locking of call, ripping it from dispatched calls etc. */
return (call_t *) callid;
link_t *lst;
call_t *call, *result = NULL;
 
spinlock_lock(&TASK->answerbox.lock);
for (lst = TASK->answerbox.dispatched_calls.next;
lst != &TASK->answerbox.dispatched_calls; lst = lst->next) {
call = list_get_instance(lst, call_t, list);
if ((__native)call == callid) {
result = call;
break;
}
}
spinlock_unlock(&TASK->answerbox.lock);
return result;
}
 
/** Allocate new phone slot in current TASK structure */
/kernel/trunk/generic/src/ipc/sysipc.c
92,8 → 92,17
int phoneid;
 
if (IPC_GET_RETVAL(answer->data) == EHANGUP) {
/* Atomic operation */
answer->data.phone->callee = NULL;
/* In case of forward, hangup the forwared phone,
* not the originator
*/
spinlock_lock(&answer->data.phone->lock);
spinlock_lock(&TASK->answerbox.lock);
if (answer->data.phone->callee) {
list_remove(&answer->data.phone->list);
answer->data.phone->callee = 0;
}
spinlock_unlock(&TASK->answerbox.lock);
spinlock_unlock(&answer->data.phone->lock);
}
 
if (!olddata)
/kernel/trunk/generic/src/ipc/ipc.c
322,6 → 322,9
/* Append request to dispatch queue */
list_append(&request->list, &box->dispatched_calls);
} else {
/* This can happen regularly after ipc_cleanup, remove
* the warning in the future when the IPC is
* more debugged */
printf("WARNING: Spurious IPC wakeup.\n");
spinlock_unlock(&box->lock);
goto restart;
339,6 → 342,20
NULL, NULL, 0);
}
 
/** Answer all calls from list with EHANGUP msg */
static void ipc_cleanup_call_list(link_t *lst)
{
call_t *call;
 
while (!list_empty(lst)) {
call = list_get_instance(lst->next, call_t, list);
list_remove(&call->list);
 
IPC_SET_RETVAL(call->data, EHANGUP);
_ipc_answer_free_call(call);
}
}
 
/** Cleans up all IPC communication of the given task
*
*
346,14 → 363,45
void ipc_cleanup(task_t *task)
{
int i;
 
call_t *call;
phone_t *phone;
/* Disconnect all our phones ('ipc_phone_hangup') */
for (i=0;i < IPC_MAX_PHONES; i++)
ipc_phone_hangup(&task->phones[i]);
 
/* Disconnect all phones connected to answerbox */
/* Disconnect all phones connected to our answerbox */
restart_phones:
spinlock_lock(&task->answerbox.lock);
while (!list_empty(&task->answerbox.connected_phones)) {
phone = list_get_instance(task->answerbox.connected_phones.next,
phone_t,
list);
if (! spinlock_trylock(&phone->lock)) {
spinlock_unlock(&task->answerbox.lock);
goto restart_phones;
}
/* Disconnect phone */
phone->callee = NULL;
list_remove(&phone->list);
 
spinlock_unlock(&phone->lock);
}
 
/* Answer all messages in 'calls' and 'dispatched_calls' queues */
spinlock_lock(&task->answerbox.lock);
ipc_cleanup_call_list(&task->answerbox.dispatched_calls);
ipc_cleanup_call_list(&task->answerbox.calls);
spinlock_unlock(&task->answerbox.lock);
/* Wait for all async answers to arrive */
while (atomic_get(&task->active_calls)) {
call = ipc_wait_for_call(&task->answerbox, 0);
ASSERT(call->flags & IPC_CALL_ANSWERED);
ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC));
atomic_dec(&task->active_calls);
ipc_call_free(call);
}
}