Terminate thread. * * End current thread execution and switch it to the exiting state. * All pending timeouts are executed. * */
| 499 | * |
| 500 | */ |
| 501 | void thread_exit(void) |
| 502 | { |
| 503 | if (THREAD->uspace) { |
| 504 | #ifdef CONFIG_UDEBUG |
| 505 | /* Generate udebug THREAD_E event */ |
| 506 | udebug_thread_e_event(); |
| 507 | |
| 508 | /* |
| 509 | * This thread will not execute any code or system calls from |
| 510 | * now on. |
| 511 | */ |
| 512 | udebug_stoppable_begin(); |
| 513 | #endif |
| 514 | if (atomic_predec(&TASK->lifecount) == 0) { |
| 515 | /* |
| 516 | * We are the last userspace thread in the task that |
| 517 | * still has not exited. With the exception of the |
| 518 | * moment the task was created, new userspace threads |
| 519 | * can only be created by threads of the same task. |
| 520 | * We are safe to perform cleanup. |
| 521 | * |
| 522 | */ |
| 523 | ipc_cleanup(); |
| 524 | sys_waitq_task_cleanup(); |
| 525 | LOG("Cleanup of task %" PRIu64 " completed.", TASK->taskid); |
| 526 | } |
| 527 | } |
| 528 | |
| 529 | restart: |
| 530 | irq_spinlock_lock(&THREAD->lock, true); |
| 531 | if (THREAD->timeout_pending) { |
| 532 | /* Busy waiting for timeouts in progress */ |
| 533 | irq_spinlock_unlock(&THREAD->lock, true); |
| 534 | goto restart; |
| 535 | } |
| 536 | |
| 537 | THREAD->state = Exiting; |
| 538 | irq_spinlock_unlock(&THREAD->lock, true); |
| 539 | |
| 540 | scheduler(); |
| 541 | |
| 542 | /* Not reached */ |
| 543 | while (true) |
| 544 | ; |
| 545 | } |
| 546 | |
| 547 | /** Interrupts an existing thread so that it may exit as soon as possible. |
| 548 | * |
no test coverage detected