diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2014-03-25 10:54:49 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2014-03-31 08:29:43 +0200 |
commit | 1b1be254e7a3e3d6fe6d55d62010a81a7ef35411 (patch) | |
tree | c8bacf15b0f092728fd69debcb2387b65db33ed0 /cpukit/posix/src/pthreadexit.c | |
parent | score: Replace _Thread_Reset() (diff) | |
download | rtems-1b1be254e7a3e3d6fe6d55d62010a81a7ef35411.tar.bz2 |
score: Thread life cycle re-implementation
The thread deletion is now supported on SMP.
This change fixes the following PRs:
PR1814: SMP race condition between stack free and dispatch
PR2035: psxcancel reveals NULL pointer access in _Thread_queue_Extract()
The POSIX cleanup handler are now called in the right context (should be
called in the context of the terminating thread).
http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_09.html
Add a user extension the reflects a thread termination event. This is
used to reclaim the Newlib reentrancy structure (may use file
operations), the POSIX cleanup handlers and the POSIX key destructors.
Diffstat (limited to 'cpukit/posix/src/pthreadexit.c')
-rw-r--r-- | cpukit/posix/src/pthreadexit.c | 82 |
1 files changed, 32 insertions, 50 deletions
diff --git a/cpukit/posix/src/pthreadexit.c b/cpukit/posix/src/pthreadexit.c index 8ffb54eb5a..40cd16023a 100644 --- a/cpukit/posix/src/pthreadexit.c +++ b/cpukit/posix/src/pthreadexit.c @@ -21,6 +21,7 @@ #include <pthread.h> #include <rtems/posix/pthreadimpl.h> +#include <rtems/score/assert.h> #include <rtems/score/apimutex.h> #include <rtems/score/threadimpl.h> #include <rtems/score/threadqimpl.h> @@ -30,65 +31,46 @@ void _POSIX_Thread_Exit( void *value_ptr ) { - Objects_Information *the_information; - Thread_Control *unblocked; - POSIX_API_Control *api; - - the_information = _Objects_Get_information_id( the_thread->Object.id ); + Thread_Control *unblocked; + POSIX_API_Control *api; + bool previous_life_protection; api = the_thread->API_Extensions[ THREAD_API_POSIX ]; + _Assert( _Debug_Is_thread_dispatching_allowed() ); - /* - * The_information has to be non-NULL. Otherwise, we couldn't be - * running in a thread of this API and class. - * - * NOTE: Lock and unlock in different order so we do not throw a - * fatal error when locking the allocator mutex. And after - * we unlock, we want to defer the context switch until we - * are ready to be switched out. Otherwise, an ISR could - * occur and preempt us out while we still hold the - * allocator mutex. - */ - - _RTEMS_Lock_allocator(); - _Thread_Disable_dispatch(); - - the_thread->Wait.return_argument = value_ptr; + previous_life_protection = _Thread_Set_life_protection( true ); + _Thread_Disable_dispatch(); - /* - * Process join - */ - if ( api->detachstate == PTHREAD_CREATE_JOINABLE ) { - unblocked = _Thread_queue_Dequeue( &api->Join_List ); - if ( unblocked ) { - do { - *(void **)unblocked->Wait.return_argument = value_ptr; - } while ( (unblocked = _Thread_queue_Dequeue( &api->Join_List )) ); - } else { - _Thread_Set_state( - the_thread, - STATES_WAITING_FOR_JOIN_AT_EXIT | STATES_TRANSIENT - ); - /* FIXME: Lock order reversal */ - _RTEMS_Unlock_allocator(); - _Thread_Enable_dispatch(); - /* now waiting for thread to arrive */ - _RTEMS_Lock_allocator(); - _Thread_Disable_dispatch(); - } - } + the_thread->Wait.return_argument = value_ptr; - /* - * Now shut down the thread - */ - _Thread_Close( the_information, the_thread ); + /* + * Process join + */ + if ( api->detachstate == PTHREAD_CREATE_JOINABLE ) { + unblocked = _Thread_queue_Dequeue( &api->Join_List ); + if ( unblocked ) { + do { + *(void **)unblocked->Wait.return_argument = value_ptr; + } while ( (unblocked = _Thread_queue_Dequeue( &api->Join_List )) ); + } else { + _Thread_Set_state( + the_thread, + STATES_WAITING_FOR_JOIN_AT_EXIT | STATES_TRANSIENT + ); + _Thread_Enable_dispatch(); + /* now waiting for thread to arrive */ + _Thread_Disable_dispatch(); + } + } - _POSIX_Threads_Free( the_thread ); + /* + * Now shut down the thread + */ + _Thread_Close( the_thread, _Thread_Executing ); - /* FIXME: Lock order reversal */ - _RTEMS_Unlock_allocator(); _Thread_Enable_dispatch(); + _Thread_Set_life_protection( previous_life_protection ); } void pthread_exit( |