From 1b1be254e7a3e3d6fe6d55d62010a81a7ef35411 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 25 Mar 2014 10:54:49 +0100 Subject: 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. --- cpukit/posix/src/pthreadexit.c | 82 +++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 50 deletions(-) (limited to 'cpukit/posix/src/pthreadexit.c') 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 #include +#include #include #include #include @@ -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( -- cgit v1.2.3