static int cond_release ( void *p, int release_all ) { pthread_cond_t *cond; kpthread_cond_t *kcond; kpthread_mutex_t *kmutex; kobject_t *kobj_cond, *kobj_mutex; kthread_t *kthread; int retval = 0; cond = *( (pthread_cond_t **) p ); ASSERT_ERRNO_AND_EXIT ( cond, EINVAL ); kobj_cond = cond->ptr; ASSERT_ERRNO_AND_EXIT ( kobj_cond, EINVAL ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj_cond->list ), EINVAL ); kcond = kobj_cond->kobject; ASSERT_ERRNO_AND_EXIT ( kcond && kcond->id == cond->id, EINVAL ); kthread_set_errno ( kthread_get_active (), EXIT_SUCCESS ); if ( (kthread = kthreadq_remove ( &kcond->queue, NULL )) ) { kobj_mutex = kthread_get_private_param ( kthread ); kmutex = kobj_mutex->kobject; retval = mutex_lock ( kmutex, kthread ); if ( retval == 0 ) kthread_move_to_ready ( kthread, LAST ); /* process other threads in queue */ while ( release_all && (kthread = kthreadq_remove ( &kcond->queue, NULL )) ) { kthread_set_errno ( kthread, EXIT_SUCCESS ); kobj_mutex = kthread_get_private_param ( kthread ); kmutex = kobj_mutex->kobject; kthread_enqueue(kthread, &kmutex->queue, 0, NULL, NULL); } } if ( retval > -1 ) kthreads_schedule (); return EXIT_SUCCESS; }
/*! * Resume suspended thread (called on timer activation) * \param sigval Thread that should be released */ static void kclock_wake_thread ( sigval_t sigval ) { kthread_t *kthread; ktimer_t *ktimer; int retval = 0; kthread = sigval.sival_ptr; ASSERT ( kthread ); ASSERT ( kthread_check_kthread ( kthread ) ); /* is this valid thread */ ASSERT ( kthread_is_suspended ( kthread, NULL, NULL ) ); ktimer = kthread_get_private_param ( kthread ); timespec_t *remain = ktimer->param; if ( remain ) TIME_RESET ( remain ); /* timer expired */ kthread_move_to_ready ( kthread, LAST ); retval += ktimer_delete ( ktimer ); ASSERT ( retval == EXIT_SUCCESS ); kthreads_schedule (); }
/*! * 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; }
/*! * 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; }