コード例 #1
0
/** \internal
  * \brief  The system call that implements the htread_exit functionality.
  *
  * \author     Wesley Peck <*****@*****.**>
  *
  * This function is the system call routine which implements the 
  * hthread_exit functionality for hthreads. The user space function
  * hthread_exit invokes this function to terminate a thread.
  *
  * \param  retval  The return value of the thread. If the currently
  *                 running thread is in the joinable state then this
  *                 value is returned to the thread which joins with
  *                 the currently running thread, otherwise this
  *                 value is discarded.
  * \return         This function never returns to the calling thread.
  */ 
void _syscall_exit( void *retval )
{
	Huint status;
	Huint current;
    Hbool destroy_flag = Hfalse;

    // Print out a trace message about this system call
    TRACE_PRINTF( TRACE_FINE, TRACE_SYSCALL, "SYSCALL: (OP=EXIT) (RET=0x%8.8x)\n", (Huint)retval );

    // Grab the current thread
	current = _current_thread();
    
    // Print out a trace message about this system call
    TRACE_PRINTF( TRACE_FINE, TRACE_SYSCALL, "SYSCALL: (OP=EXIT) (TID=0x%8.8x) (RET=0x%8.8x)\n", (Huint)current, (Huint)retval );
     
    if( _detached_thread(current) ) destroy_flag = Htrue;

	// The return value needs to be saved before we
	// try to exit the thread (to avoid race conditions when a parent joins
	// a thread and trys to get the return value). Note that we don't
	// need to save the return value for a detached thread.
    threads[current].retval = retval;
    
	// FIXME: We should check the error condition during the while loop
	// to ensure that the error was because the ready-to-run queue is
	// full. Any other error is fatal and since this function never returns
	// to the caller we must handle this error.
	status = _exit_thread( current );

	while( has_error(status) )
	{
        DEBUG_PRINTF( "Exit returned an error: (STA=0x%8.8x)\n", status );

		// Yield the processor to another thread.
		_syscall_yield();

		// Try to exit again after some other thread has run.
		status = _exit_thread( current );
	}
 
    // If the thread is a detached thread then it can be destroyed right
    // away. Joinable threads cannot be destroyed until they have been joined
    // by some other thread (see _syscall_join).
    if( destroy_flag ) 
    {
        _destroy_thread( current );

        TRACE_PRINTF( TRACE_FINE, TRACE_SYSCALL, "** DETACHED = 0x%8.8x **\n",destroy_flag);
    }

    // Print out a trace message about this system call
    TRACE_PRINTF( TRACE_FINE, TRACE_SYSCALL, "SYSCALL DONE: (OP=EXIT) (RET=0x%8.8x)\n", (Huint)retval );

	// We have now exited. Run the scheduler and never come back.
	_run_sched( Hfalse );
}
コード例 #2
0
ファイル: pthread.c プロジェクト: jld/platform_bionic
void pthread_exit(void * retval)
{
    pthread_internal_t*  thread     = __get_thread();
    void*                stack_base = thread->attr.stack_base;
    int                  stack_size = thread->attr.stack_size;
    int                  user_stack = (thread->attr.flags & PTHREAD_ATTR_FLAG_USER_STACK) != 0;
    sigset_t mask;

    // call the cleanup handlers first
    while (thread->cleanup_stack) {
        __pthread_cleanup_t*  c = thread->cleanup_stack;
        thread->cleanup_stack   = c->__cleanup_prev;
        c->__cleanup_routine(c->__cleanup_arg);
    }

    // call the TLS destructors, it is important to do that before removing this
    // thread from the global list. this will ensure that if someone else deletes
    // a TLS key, the corresponding value will be set to NULL in this thread's TLS
    // space (see pthread_key_delete)
    pthread_key_clean_all();

    // if the thread is detached, destroy the pthread_internal_t
    // otherwise, keep it in memory and signal any joiners.
    pthread_mutex_lock(&gThreadListLock);
    if (thread->attr.flags & PTHREAD_ATTR_FLAG_DETACHED) {
        _pthread_internal_remove_locked(thread);
    } else {
        /* make sure that the thread struct doesn't have stale pointers to a stack that
         * will be unmapped after the exit call below.
         */
        if (!user_stack) {
            thread->attr.stack_base = NULL;
            thread->attr.stack_size = 0;
            thread->tls = NULL;
        }

        /* Indicate that the thread has exited for joining threads. */
        thread->attr.flags |= PTHREAD_ATTR_FLAG_ZOMBIE;
        thread->return_value = retval;

        /* Signal the joining thread if present. */
        if (thread->attr.flags & PTHREAD_ATTR_FLAG_JOINED) {
            pthread_cond_signal(&thread->join_cond);
        }
    }
    pthread_mutex_unlock(&gThreadListLock);

    sigfillset(&mask);
    sigdelset(&mask, SIGSEGV);
    (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL);

    // destroy the thread stack
    if (user_stack)
        _exit_thread((int)retval);
    else
        _exit_with_stack_teardown(stack_base, stack_size, (int)retval);
}