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 | ||