void uthread_exit () { size_t space_for_mem_alloc_hdr[16]; /* just in case ... */ uthread_t *cur_thread, *new_thread, tmp; /* active thread is exiting */ cur_thread = list_remove ( &active, FIRST, NULL ); space_for_mem_alloc_hdr[0] = (size_t) cur_thread; /*remove compiler 'not-used' warning */ free ( cur_thread->stack ); /* freeing it, but using it still - till the end of this function (parameters are on stack!) */ tmp = *cur_thread; free ( cur_thread ); /* pick next ready thread */ new_thread = list_remove ( &ready, FIRST, NULL ); /* make it active */ list_append ( &active, new_thread, &new_thread->list ); /* switch to it */ arch_switch_to_thread ( &tmp.context, &new_thread->context ); }
void uthread_yield () { uthread_t *cur_thread, *new_thread; /* remove current thread from 'active' and put it as last in 'ready' */ cur_thread = list_remove ( &active, FIRST, NULL ); list_append ( &ready, cur_thread, &cur_thread->list ); /* remove first thread from 'ready' and put it in 'active' */ new_thread = list_remove ( &ready, FIRST, NULL ); list_append ( &active, new_thread, &new_thread->list ); /* switch to new active thread */ arch_switch_to_thread ( &cur_thread->context, &new_thread->context ); }
/*! Switch to other thread */ void kthread_switch_to_thread ( kthread_t *from, kthread_t *to ) { ASSERT ( to == active_thread ); if ( from && ( from->state.flags & THR_FLAG_DELETE ) ) { /* delete thread resources with switch */ from->state.flags &= ~THR_FLAG_DELETE; arch_switch_to_thread_with_cleanup ( from, kthread_get_context ( to ) ); } else { arch_switch_to_thread ( /* from */ ( from ? kthread_get_context ( from ) : NULL ), /* to */ kthread_get_context ( to ) ); } }
void uthread_exit () { uthread_t *cur_thread, *new_thread; /* active thread is exiting */ cur_thread = list_remove ( &active, FIRST, NULL ); free ( cur_thread->stack ); /* freeing it, but using it still - till the end of this function (parameters are on stack!) */ free ( cur_thread ); /* pick next ready thread */ new_thread = list_remove ( &ready, FIRST, NULL ); /* make it active */ list_append ( &active, new_thread, &new_thread->list ); /* switch to it */ arch_switch_to_thread ( NULL, &new_thread->context ); }
/*! * 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; arch_switch_to_thread ( NULL, &kthread->state.context ); } else { ASSERT (FALSE); /* hum, rethink this */ /* move to ready? */ } 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->state.exit_status = exit_status; /* remove it from its scheduler */ ksched2_thread_remove ( kthread ); /* any thread waiting on this? */ 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--; } /* defer removing thread resources until last moment */ kthread->state.flags |= THR_FLAG_DELETE; if ( kthread == active_thread ) { //active_thread = NULL; kthreads_schedule (); } return EXIT_SUCCESS; }