Rev 1573 | Rev 1591 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1573 | Rev 1582 | ||
---|---|---|---|
Line 367... | Line 367... | ||
367 | IPC_SET_RETVAL(call->data, EHANGUP); |
367 | IPC_SET_RETVAL(call->data, EHANGUP); |
368 | _ipc_answer_free_call(call); |
368 | _ipc_answer_free_call(call); |
369 | } |
369 | } |
370 | } |
370 | } |
371 | 371 | ||
372 | /** Cleans up all IPC communication of the given task |
372 | /** Cleans up all IPC communication of the current task |
373 | * |
- | |
374 | * |
373 | * |
- | 374 | * Note: ipc_hangup sets returning answerbox to TASK->answerbox, you |
|
- | 375 | * have to change it as well if you want to cleanup other current then current. |
|
375 | */ |
376 | */ |
376 | void ipc_cleanup(task_t *task) |
377 | void ipc_cleanup(void) |
377 | { |
378 | { |
378 | int i; |
379 | int i; |
379 | call_t *call; |
380 | call_t *call; |
380 | phone_t *phone; |
381 | phone_t *phone; |
381 | 382 | ||
382 | /* Disconnect all our phones ('ipc_phone_hangup') */ |
383 | /* Disconnect all our phones ('ipc_phone_hangup') */ |
383 | for (i=0;i < IPC_MAX_PHONES; i++) |
384 | for (i=0;i < IPC_MAX_PHONES; i++) |
384 | ipc_phone_hangup(&task->phones[i], 1); |
385 | ipc_phone_hangup(&TASK->phones[i], 1); |
385 | 386 | ||
386 | /* Disconnect all connected irqs */ |
387 | /* Disconnect all connected irqs */ |
387 | ipc_irq_cleanup(&task->answerbox); |
388 | ipc_irq_cleanup(&TASK->answerbox); |
388 | 389 | ||
389 | /* Disconnect all phones connected to our answerbox */ |
390 | /* Disconnect all phones connected to our answerbox */ |
390 | restart_phones: |
391 | restart_phones: |
391 | spinlock_lock(&task->answerbox.lock); |
392 | spinlock_lock(&TASK->answerbox.lock); |
392 | while (!list_empty(&task->answerbox.connected_phones)) { |
393 | while (!list_empty(&TASK->answerbox.connected_phones)) { |
393 | phone = list_get_instance(task->answerbox.connected_phones.next, |
394 | phone = list_get_instance(TASK->answerbox.connected_phones.next, |
394 | phone_t, link); |
395 | phone_t, link); |
395 | if (! spinlock_trylock(&phone->lock)) { |
396 | if (! spinlock_trylock(&phone->lock)) { |
396 | spinlock_unlock(&task->answerbox.lock); |
397 | spinlock_unlock(&TASK->answerbox.lock); |
397 | goto restart_phones; |
398 | goto restart_phones; |
398 | } |
399 | } |
399 | 400 | ||
400 | /* Disconnect phone */ |
401 | /* Disconnect phone */ |
401 | ASSERT(phone->state == IPC_PHONE_CONNECTED); |
402 | ASSERT(phone->state == IPC_PHONE_CONNECTED); |
Line 404... | Line 405... | ||
404 | 405 | ||
405 | spinlock_unlock(&phone->lock); |
406 | spinlock_unlock(&phone->lock); |
406 | } |
407 | } |
407 | 408 | ||
408 | /* Answer all messages in 'calls' and 'dispatched_calls' queues */ |
409 | /* Answer all messages in 'calls' and 'dispatched_calls' queues */ |
409 | spinlock_lock(&task->answerbox.lock); |
- | |
410 | ipc_cleanup_call_list(&task->answerbox.dispatched_calls); |
410 | ipc_cleanup_call_list(&TASK->answerbox.dispatched_calls); |
411 | ipc_cleanup_call_list(&task->answerbox.calls); |
411 | ipc_cleanup_call_list(&TASK->answerbox.calls); |
412 | spinlock_unlock(&task->answerbox.lock); |
412 | spinlock_unlock(&TASK->answerbox.lock); |
413 | 413 | ||
414 | /* Wait for all async answers to arrive */ |
414 | /* Wait for all async answers to arrive */ |
415 | while (1) { |
415 | while (1) { |
416 | /* Go through all phones, until all are FREE... */ |
416 | /* Go through all phones, until all are FREE... */ |
417 | /* Locking not needed, no one else should modify |
417 | /* Locking not needed, no one else should modify |
418 | * it, when we are in cleanup */ |
418 | * it, when we are in cleanup */ |
419 | for (i=0;i < IPC_MAX_PHONES; i++) { |
419 | for (i=0;i < IPC_MAX_PHONES; i++) { |
420 | if (task->phones[i].state == IPC_PHONE_HUNGUP && \ |
420 | if (TASK->phones[i].state == IPC_PHONE_HUNGUP && \ |
421 | atomic_get(&task->phones[i].active_calls) == 0) |
421 | atomic_get(&TASK->phones[i].active_calls) == 0) |
422 | task->phones[i].state = IPC_PHONE_FREE; |
422 | TASK->phones[i].state = IPC_PHONE_FREE; |
- | 423 | ||
- | 424 | if (TASK->phones[i].state == IPC_PHONE_CONNECTED) |
|
- | 425 | ipc_phone_hangup(&TASK->phones[i], 1); |
|
- | 426 | ||
423 | if (task->phones[i].state != IPC_PHONE_FREE) |
427 | if (TASK->phones[i].state != IPC_PHONE_FREE) |
424 | break; |
428 | break; |
425 | } |
429 | } |
426 | /* Voila, got into cleanup */ |
430 | /* Voila, got into cleanup */ |
427 | if (i == IPC_MAX_PHONES) |
431 | if (i == IPC_MAX_PHONES) |
428 | break; |
432 | break; |
429 | 433 | ||
430 | call = ipc_wait_for_call(&task->answerbox, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE); |
434 | call = ipc_wait_for_call(&TASK->answerbox, SYNCH_NO_TIMEOUT, SYNCH_FLAGS_NONE); |
431 | ASSERT((call->flags & IPC_CALL_ANSWERED) || (call->flags & IPC_CALL_NOTIF)); |
435 | ASSERT((call->flags & IPC_CALL_ANSWERED) || (call->flags & IPC_CALL_NOTIF)); |
432 | ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC)); |
436 | ASSERT(! (call->flags & IPC_CALL_STATIC_ALLOC)); |
433 | 437 | ||
434 | atomic_dec(&task->active_calls); |
438 | atomic_dec(&TASK->active_calls); |
435 | ipc_call_free(call); |
439 | ipc_call_free(call); |
436 | } |
440 | } |
437 | } |
441 | } |
438 | 442 | ||
439 | 443 |