void kthread_cleanup ( kthread_t *kthread ) { kthread_restore_state ( kthread ); kthread->ref_cnt--; if ( !kthread->ref_cnt ) kthread_remove_descriptor ( kthread ); }
/*! Get exit status of finished thread (and free descriptor) */ void kthread_collect_status ( kthread_t *waited, void **retval ) { ASSERT ( waited ); if ( retval ) *retval = waited->state.exit_status; if ( !waited->ref_cnt ) kthread_remove_descriptor ( waited ); }
/*! * Cancel thread (or restore it to previous state) * \param kthread Thread descriptor */ int kthread_exit ( kthread_t *kthread, void *exit_status, int force ) { kthread_state_t *prev; int restored = FALSE; kthread_t *released; kthread_q *q; void **p; ASSERT ( kthread ); do { prev = list_get ( &kthread->states, FIRST ); if ( prev ) restored = kthread_restore_state ( kthread ); } while ( prev && force ); /* if cancel is called, destroy all states */ if ( restored && !force ) /* restored to previous state */ { if ( kthread == active_thread ) kthread->state.state = THR_STATE_ACTIVE; kthreads_schedule (); return EXIT_SUCCESS; } if ( kthread->state.state == THR_STATE_PASSIVE ) return EXIT_SUCCESS; /* thread is already finished */ if ( kthread->state.state == THR_STATE_READY ) { /* remove target 'thread' from its queue */ if ( !kthread_remove_from_ready ( kthread ) ) ASSERT ( FALSE ); } else if ( kthread->state.state == THR_STATE_WAIT ) { /* remove target 'thread' from its queue */ if ( !kthreadq_remove ( kthread->queue, kthread ) ) ASSERT ( FALSE ); } else if ( kthread->state.state == THR_STATE_SUSPENDED ) { /* cancellation routine */ if ( kthread->state.cancel_suspend_handler ) kthread->state.cancel_suspend_handler ( kthread, kthread->state.cancel_suspend_param ); } else if ( kthread->state.state == THR_STATE_ACTIVE ) { if ( kthread != active_thread ) return ESRCH; /* thread descriptor corrupted ! */ } else { return ESRCH; /* thread descriptor corrupted ! */ } kthread->state.state = THR_STATE_PASSIVE; kthread->ref_cnt--; kthread->state.exit_status = exit_status; kthread->proc->thread_count--; arch_destroy_thread_context ( &kthread->state.context ); kthread_restore_state ( kthread ); q = &kthread->join_queue; while ( (released = kthreadq_remove ( q, NULL )) != NULL ) { /* save exit status to all waiting threads */ p = kthread_get_private_param ( released ); if ( p ) *p = exit_status; kthread_move_to_ready ( released, LAST ); kthread->ref_cnt--; } if ( !kthread->ref_cnt ) kthread_remove_descriptor ( kthread ); if ( kthread == active_thread ) { active_thread = NULL; kthreads_schedule (); } return EXIT_SUCCESS; }