kthread_t *kthreadq_remove ( kthread_q *q, kthread_t *kthread ) { ASSERT ( q ); if ( kthread ) return list_find_and_remove ( &q->q, &kthread->list ); else return list_remove ( &q->q, FIRST, NULL ); }
/*! * Close a message queue * \param mqdes Queue descriptor address (user level descriptor) * \return 0 if successful, -1 otherwise and appropriate error number is set */ int sys__mq_close ( void *p ) { mqd_t *mqdes; kmq_queue_t *kq_queue; kobject_t *kobj; kmq_msg_t *kmq_msg; kthread_t *kthread; mqdes = *( (mqd_t **) p ); ASSERT_ERRNO_AND_EXIT ( mqdes, EBADF ); kobj = mqdes->ptr; ASSERT_ERRNO_AND_EXIT ( kobj, EBADF ); ASSERT_ERRNO_AND_EXIT ( list_find ( &kobjects, &kobj->list ), EBADF ); kq_queue = kobj->kobject; kq_queue = list_find_and_remove ( &kmq_queue, &kq_queue->list ); if ( !kq_queue || kq_queue->id != mqdes->id ) EXIT2 ( EBADF, EXIT_FAILURE ); kq_queue->ref_cnt--; if ( !kq_queue->ref_cnt ) { /* remove messages */ while( (kmq_msg = list_remove(&kq_queue->msg_list,FIRST,NULL)) ) kfree (kmq_msg); /* remove blocked threads */ while ( (kthread = kthreadq_remove (&kq_queue->send_q, NULL)) ) { kthread_move_to_ready ( kthread, LAST ); kthread_set_errno ( kthread, EBADF ); kthread_set_syscall_retval ( kthread, EXIT_FAILURE ); } while ( (kthread = kthreadq_remove (&kq_queue->recv_q, NULL)) ) { kthread_move_to_ready ( kthread, LAST ); kthread_set_errno ( kthread, EBADF ); kthread_set_syscall_retval ( kthread, EXIT_FAILURE ); } list_remove ( &kmq_queue, 0, &kq_queue->list ); k_free_id ( kq_queue->id ); kfree ( kq_queue->name ); kfree ( kq_queue ); } /* remove kernel object descriptor */ kfree_kobject ( kobj ); EXIT2 ( EXIT_SUCCESS, EXIT_SUCCESS ); }
/*! Free space reserved by kernel object */ void *kfree_kobject ( kobject_t *kobj ) { ASSERT ( kobj ); #ifndef DEBUG list_remove ( &kobjects, 0, &kobj->list ); #else /* DEBUG */ ASSERT ( list_find_and_remove ( &kobjects, &kobj->list ) ); #endif kfree ( kobj ); return EXIT_SUCCESS; }
/*! Internal function for removing (freeing) thread descriptor */ static void kthread_remove_descriptor ( kthread_t *kthread ) { ASSERT ( kthread ); k_free_id ( kthread->id ); kthread->id = 0; #ifdef DEBUG ASSERT( kthread == list_find_and_remove (&all_threads, &kthread->all) ); #else (void) list_remove ( &all_threads, 0, &kthread->all ); #endif kfree ( kthread ); }
/*! * 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--; /* remove it from its scheduler */ ksched2_thread_remove ( kthread ); arch_destroy_thread_context ( &kthread->state.context ); kthread_restore_state ( kthread ); if ( kthread->proc->thread_count == 0 && kthread->proc->pi ) { /* last (non-kernel) thread - remove process */ kfree_process_kobjects ( kthread->proc ); kthread->proc->prog->started = FALSE; #ifdef DEBUG ASSERT ( kthread->proc == list_find_and_remove ( &procs, &kthread->proc->list ) ); #else (void) list_remove ( &procs, 0, &kthread->proc->list ); #endif kfree ( kthread->proc ); } 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; }