From da82656065d09f7b6aa411ba361287afdd787204 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 13 May 2016 10:28:14 +0200 Subject: posix: Rework thread cancellation Add Thread_Life_state::THREAD_LIFE_CHANGE_DEFERRED and rework the POSIX thread cancellation to use the thread life states. Update #2555. Update #2626. --- cpukit/posix/Makefile.am | 3 +- cpukit/posix/include/rtems/posix/cancel.h | 37 ------------------ cpukit/posix/include/rtems/posix/threadsup.h | 33 ---------------- cpukit/posix/preinstall.am | 4 -- cpukit/posix/src/cancel.c | 45 +++++++++++----------- cpukit/posix/src/canceleval.c | 45 ---------------------- cpukit/posix/src/pthread.c | 7 ---- cpukit/posix/src/pthreadcreate.c | 2 + cpukit/posix/src/pthreadexit.c | 29 ++------------ cpukit/posix/src/pthreadinitthreads.c | 1 - cpukit/posix/src/setcancelstate.c | 51 +++++++++++-------------- cpukit/posix/src/setcanceltype.c | 54 +++++++++++++-------------- cpukit/posix/src/testcancel.c | 36 +++--------------- cpukit/score/include/rtems/score/thread.h | 1 + cpukit/score/include/rtems/score/threadimpl.h | 9 ++++- cpukit/score/src/threadrestart.c | 6 +-- 16 files changed, 93 insertions(+), 270 deletions(-) delete mode 100644 cpukit/posix/include/rtems/posix/cancel.h delete mode 100644 cpukit/posix/src/canceleval.c diff --git a/cpukit/posix/Makefile.am b/cpukit/posix/Makefile.am index d354f7ec52..a7632a04cc 100644 --- a/cpukit/posix/Makefile.am +++ b/cpukit/posix/Makefile.am @@ -31,7 +31,6 @@ endif # include/rtems/posix include_rtems_posix_HEADERS += include/rtems/posix/aio_misc.h -include_rtems_posix_HEADERS += include/rtems/posix/cancel.h include_rtems_posix_HEADERS += include/rtems/posix/cond.h include_rtems_posix_HEADERS += include/rtems/posix/condimpl.h include_rtems_posix_HEADERS += include/rtems/posix/mqueue.h @@ -78,7 +77,7 @@ libposix_a_SOURCES += src/barrierattrdestroy.c src/barrierattrgetpshared.c \ src/pbarriertranslatereturncode.c src/pbarrierwait.c ## CANCEL_C_FILES -libposix_a_SOURCES += src/cancel.c src/canceleval.c \ +libposix_a_SOURCES += src/cancel.c \ src/cleanuppush.c src/setcancelstate.c \ src/setcanceltype.c src/testcancel.c diff --git a/cpukit/posix/include/rtems/posix/cancel.h b/cpukit/posix/include/rtems/posix/cancel.h deleted file mode 100644 index 52bbcbccec..0000000000 --- a/cpukit/posix/include/rtems/posix/cancel.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @file - * - * @brief POSIX Thread Cancelation Support - * - * This file contains the prototypes and data types used to implement - * POSIX thread cancelation. - */ - -/* - * COPYRIGHT (c) 1989-2009. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#ifndef _RTEMS_POSIX_CANCEL_H -#define _RTEMS_POSIX_CANCEL_H - -#include - -/** - * @brief POSIX evaluate thread cancelation and enable dispatch. - * - * This routine separates a piece of code that existed as part of - * another routine, but had to be separated to improve coverage. - * - * @param[in] the_thread is a pointer to the thread to evaluate canceling - */ -void _POSIX_Thread_Evaluate_cancellation_and_enable_dispatch ( - Thread_Control *the_thread -); - -#endif -/* end of include file */ diff --git a/cpukit/posix/include/rtems/posix/threadsup.h b/cpukit/posix/include/rtems/posix/threadsup.h index 3a7cfbc6dc..51c9564c64 100644 --- a/cpukit/posix/include/rtems/posix/threadsup.h +++ b/cpukit/posix/include/rtems/posix/threadsup.h @@ -71,41 +71,8 @@ typedef struct { * @brief Signal post-switch action in case signals are pending. */ Thread_Action Signal_action; - - /*******************************************************************/ - /*******************************************************************/ - /*************** POSIX Cancelability ***************/ - /*******************************************************************/ - /*******************************************************************/ - - /** This is the cancelability state. */ - int cancelability_state; - /** This is the cancelability type. */ - int cancelability_type; - /** This indicates if a cancelation has been requested. */ - int cancelation_requested; } POSIX_API_Control; -/** - * @brief POSIX thread exit shared helper. - * - * 16.1.5.1 Thread Termination, p1003.1c/Draft 10, p. 150 - * - * This method is a helper routine which ensures that all - * POSIX thread calls which result in a thread exiting will - * do so in the same manner. - * - * @param[in] the_thread is a pointer to the thread exiting or being canceled - * @param[in] value_ptr is a pointer the value to be returned by the thread - * - * NOTE: Key destructors are executed in the POSIX api delete extension. - * - */ -void _POSIX_Thread_Exit( - Thread_Control *the_thread, - void *value_ptr -); - /** @} */ #ifdef __cplusplus diff --git a/cpukit/posix/preinstall.am b/cpukit/posix/preinstall.am index cf1303c954..6fc6b4cc47 100644 --- a/cpukit/posix/preinstall.am +++ b/cpukit/posix/preinstall.am @@ -61,10 +61,6 @@ $(PROJECT_INCLUDE)/rtems/posix/aio_misc.h: include/rtems/posix/aio_misc.h $(PROJ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/aio_misc.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/aio_misc.h -$(PROJECT_INCLUDE)/rtems/posix/cancel.h: include/rtems/posix/cancel.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp) - $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/cancel.h -PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/cancel.h - $(PROJECT_INCLUDE)/rtems/posix/cond.h: include/rtems/posix/cond.h $(PROJECT_INCLUDE)/rtems/posix/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/posix/cond.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/posix/cond.h diff --git a/cpukit/posix/src/cancel.c b/cpukit/posix/src/cancel.c index f103d6574b..9519c45e52 100644 --- a/cpukit/posix/src/cancel.c +++ b/cpukit/posix/src/cancel.c @@ -9,6 +9,8 @@ * COPYRIGHT (c) 1989-2008. * On-Line Applications Research Corporation (OAR). * + * Copyright (c) 2016 embedded brains GmbH. + * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. @@ -23,46 +25,43 @@ #include #include -#include -#include /* * 18.2.1 Canceling Execution of a Thread, P1003.1c/Draft 10, p. 181 */ -int pthread_cancel( - pthread_t thread -) +int pthread_cancel( pthread_t thread ) { - Thread_Control *the_thread; - POSIX_API_Control *thread_support; - Objects_Locations location; + Thread_Control *the_thread; + ISR_lock_Context lock_context; + Thread_Control *executing; + Per_CPU_Control *cpu_self; /* * Don't even think about deleting a resource from an ISR. */ - if ( _ISR_Is_in_progress() ) + if ( _ISR_Is_in_progress() ) { return EPROTO; + } - the_thread = _Thread_Get( thread, &location ); - switch ( location ) { + the_thread = _Thread_Get_interrupt_disable( thread, &lock_context ); - case OBJECTS_LOCAL: - thread_support = the_thread->API_Extensions[ THREAD_API_POSIX ]; + if ( the_thread == NULL ) { + return ESRCH; + } - thread_support->cancelation_requested = 1; + cpu_self = _Thread_Dispatch_disable_critical( &lock_context ); + _ISR_lock_ISR_enable( &lock_context ); - /* This enables dispatch implicitly */ - _POSIX_Thread_Evaluate_cancellation_and_enable_dispatch( the_thread ); - return 0; + executing = _Per_CPU_Get_executing( cpu_self ); -#if defined(RTEMS_MULTIPROCESSING) - case OBJECTS_REMOTE: -#endif - case OBJECTS_ERROR: - break; + if ( the_thread == executing ) { + _Thread_Exit( executing, THREAD_LIFE_TERMINATING, PTHREAD_CANCELED ); + } else { + _Thread_Cancel( the_thread, executing, PTHREAD_CANCELED ); } - return ESRCH; + _Thread_Dispatch_enable( cpu_self ); + return 0; } diff --git a/cpukit/posix/src/canceleval.c b/cpukit/posix/src/canceleval.c deleted file mode 100644 index 9e02c92375..0000000000 --- a/cpukit/posix/src/canceleval.c +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @file - * - * @brief POSIX Function Evaluates Thread Cancellation and Enables Dispatch - * @ingroup POSIXAPI - */ - -/* - * COPYRIGHT (c) 1989-2009. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#if HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include - -void _POSIX_Thread_Evaluate_cancellation_and_enable_dispatch( - Thread_Control *the_thread -) -{ - POSIX_API_Control *thread_support; - - thread_support = the_thread->API_Extensions[ THREAD_API_POSIX ]; - - if ( thread_support->cancelability_state == PTHREAD_CANCEL_ENABLE && - thread_support->cancelability_type == PTHREAD_CANCEL_ASYNCHRONOUS && - thread_support->cancelation_requested ) { - /* FIXME: This path is broken on SMP */ - _Thread_Unnest_dispatch(); - /* FIXME: Cancelability state may change here */ - _POSIX_Thread_Exit( the_thread, PTHREAD_CANCELED ); - } else - _Objects_Put( &the_thread->Object ); - -} diff --git a/cpukit/posix/src/pthread.c b/cpukit/posix/src/pthread.c index 12c5ace537..766ac01e5f 100644 --- a/cpukit/posix/src/pthread.c +++ b/cpukit/posix/src/pthread.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -208,12 +207,6 @@ static bool _POSIX_Threads_Create_extension( api->schedparam.sched_priority = _POSIX_Priority_From_core( created->current_priority ); - /* - * POSIX 1003.1 1996, 18.2.2.2 - */ - RTEMS_STATIC_ASSERT( PTHREAD_CANCEL_ENABLE == 0, cancelability_state ); - RTEMS_STATIC_ASSERT( PTHREAD_CANCEL_DEFERRED == 0, cancelability_type ); - /* * If the thread is not a posix thread, then all posix signals are blocked * by default. diff --git a/cpukit/posix/src/pthreadcreate.c b/cpukit/posix/src/pthreadcreate.c index 33fae37776..7f95898b62 100644 --- a/cpukit/posix/src/pthreadcreate.c +++ b/cpukit/posix/src/pthreadcreate.c @@ -205,6 +205,8 @@ int pthread_create( the_thread->Life.state |= THREAD_LIFE_DETACHED; } + the_thread->Life.state |= THREAD_LIFE_CHANGE_DEFERRED; + #if defined(RTEMS_SMP) && __RTEMS_HAVE_SYS_CPUSET_H__ _ISR_lock_ISR_disable( &lock_context ); status = _Scheduler_Set_affinity( diff --git a/cpukit/posix/src/pthreadexit.c b/cpukit/posix/src/pthreadexit.c index 3c4d3ebaaf..53c42ff3d0 100644 --- a/cpukit/posix/src/pthreadexit.c +++ b/cpukit/posix/src/pthreadexit.c @@ -9,6 +9,8 @@ * COPYRIGHT (c) 1989-2011. * On-Line Applications Research Corporation (OAR). * + * Copyright (c) 2016 embedded brains GmbH. + * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. @@ -20,41 +22,18 @@ #include -#include -#include -#include #include -#include -void _POSIX_Thread_Exit( - Thread_Control *the_thread, - void *value_ptr -) +void pthread_exit( void *value_ptr ) { Thread_Control *executing; Per_CPU_Control *cpu_self; - _Assert( _Debug_Is_thread_dispatching_allowed() ); - cpu_self = _Thread_Dispatch_disable(); executing = _Per_CPU_Get_executing( cpu_self ); - /* - * Now shut down the thread - */ - if ( the_thread == executing ) { - _Thread_Exit( executing, THREAD_LIFE_TERMINATING, value_ptr ); - } else { - _Thread_Cancel( the_thread, executing, value_ptr ); - } + _Thread_Exit( executing, THREAD_LIFE_TERMINATING, value_ptr ); _Thread_Dispatch_enable( cpu_self ); -} - -void pthread_exit( - void *value_ptr -) -{ - _POSIX_Thread_Exit( _Thread_Get_executing(), value_ptr ); RTEMS_UNREACHABLE(); } diff --git a/cpukit/posix/src/pthreadinitthreads.c b/cpukit/posix/src/pthreadinitthreads.c index 05ceda2120..ff11e8a6b0 100644 --- a/cpukit/posix/src/pthreadinitthreads.c +++ b/cpukit/posix/src/pthreadinitthreads.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/cpukit/posix/src/setcancelstate.c b/cpukit/posix/src/setcancelstate.c index a451c2c4b4..b0a42e86b8 100644 --- a/cpukit/posix/src/setcancelstate.c +++ b/cpukit/posix/src/setcancelstate.c @@ -9,6 +9,8 @@ * COPYRIGHT (c) 1989-2009. * On-Line Applications Research Corporation (OAR). * + * Copyright (c) 2016 embedded brains GmbH. + * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. @@ -21,13 +23,8 @@ #include #include -#include -#include #include -#include -#include -#include -#include +#include /* * 18.2.2 Setting Cancelability State, P1003.1c/Draft 10, p. 183 @@ -38,36 +35,30 @@ int pthread_setcancelstate( int *oldstate ) { - POSIX_API_Control *thread_support; - Thread_Control *executing; - - /* - * Don't even think about deleting a resource from an ISR. - * Besides this request is supposed to be for _Thread_Executing - * and the ISR context is not a thread. - */ + Thread_Life_state new_life_protection; + Thread_Life_state previous_life_state; - if ( _ISR_Is_in_progress() ) + if ( _ISR_Is_in_progress() ) { return EPROTO; + } - if ( state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE ) + if ( state == PTHREAD_CANCEL_DISABLE ) { + new_life_protection = THREAD_LIFE_PROTECTED; + } else if ( state == PTHREAD_CANCEL_ENABLE ) { + new_life_protection = 0; + } else { return EINVAL; + } - _Thread_Disable_dispatch(); - - executing = _Thread_Executing; - thread_support = executing ->API_Extensions[ THREAD_API_POSIX ]; - - if (oldstate != NULL) - *oldstate = thread_support->cancelability_state; - - thread_support->cancelability_state = state; - - _POSIX_Thread_Evaluate_cancellation_and_enable_dispatch( executing ); + previous_life_state = _Thread_Set_life_protection( new_life_protection ); - /* - * _Thread_Enable_dispatch is invoked by above call. - */ + if ( oldstate != NULL ) { + if ( ( previous_life_state & THREAD_LIFE_PROTECTED ) != 0 ) { + *oldstate = PTHREAD_CANCEL_DISABLE; + } else { + *oldstate = PTHREAD_CANCEL_ENABLE; + } + } return 0; } diff --git a/cpukit/posix/src/setcanceltype.c b/cpukit/posix/src/setcanceltype.c index 8c4687a981..701317f1d6 100644 --- a/cpukit/posix/src/setcanceltype.c +++ b/cpukit/posix/src/setcanceltype.c @@ -9,6 +9,8 @@ * COPYRIGHT (c) 1989-2009. * On-Line Applications Research Corporation (OAR). * + * Copyright (c) 2016 embedded brains GmbH. + * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. @@ -21,13 +23,8 @@ #include #include -#include -#include #include -#include -#include -#include -#include +#include /* * 18.2.2 Setting Cancelability State, P1003.1c/Draft 10, p. 183 @@ -38,35 +35,34 @@ int pthread_setcanceltype( int *oldtype ) { - POSIX_API_Control *thread_support; - Thread_Control *executing; - - /* - * Don't even think about deleting a resource from an ISR. - * Besides this request is supposed to be for _Thread_Executing - * and the ISR context is not a thread. - */ + Thread_Life_state set_life_state; + Thread_Life_state previous_life_state; - if ( _ISR_Is_in_progress() ) + if ( _ISR_Is_in_progress() ) { return EPROTO; + } - if ( type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS ) + if ( type == PTHREAD_CANCEL_DEFERRED ) { + set_life_state = THREAD_LIFE_CHANGE_DEFERRED; + } else if ( type == PTHREAD_CANCEL_ASYNCHRONOUS ) { + set_life_state = 0; + } else { return EINVAL; + } - _Thread_Disable_dispatch(); - - executing = _Thread_Executing; - thread_support = executing ->API_Extensions[ THREAD_API_POSIX ]; - - if ( oldtype != NULL ) - *oldtype = thread_support->cancelability_type; - - thread_support->cancelability_type = type; + previous_life_state = _Thread_Change_life( + THREAD_LIFE_CHANGE_DEFERRED, + set_life_state, + 0 + ); - _POSIX_Thread_Evaluate_cancellation_and_enable_dispatch( executing ); + if ( oldtype != NULL ) { + if ( ( previous_life_state & THREAD_LIFE_CHANGE_DEFERRED ) != 0 ) { + *oldtype = PTHREAD_CANCEL_DEFERRED; + } else { + *oldtype = PTHREAD_CANCEL_ASYNCHRONOUS; + } + } - /* - * _Thread_Enable_dispatch is invoked by above call. - */ return 0; } diff --git a/cpukit/posix/src/testcancel.c b/cpukit/posix/src/testcancel.c index c78f26a62b..f50c7782ed 100644 --- a/cpukit/posix/src/testcancel.c +++ b/cpukit/posix/src/testcancel.c @@ -9,6 +9,8 @@ * COPYRIGHT (c) 1989-2008. * On-Line Applications Research Corporation (OAR). * + * Copyright (c) 2016 embedded brains GmbH. + * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. @@ -19,16 +21,9 @@ #endif #include -#include -#include -#include #include -#include -#include -#include -#include -#include +#include /* * 18.2.2 Setting Cancelability State, P1003.1c/Draft 10, p. 183 @@ -36,28 +31,9 @@ void pthread_testcancel( void ) { - POSIX_API_Control *thread_support; - Thread_Control *executing; - bool cancel = false; - - /* - * Don't even think about deleting a resource from an ISR. - * Besides this request is supposed to be for _Thread_Executing - * and the ISR context is not a thread. - */ - - if ( _ISR_Is_in_progress() ) + if ( _ISR_Is_in_progress() ) { return; + } - _Thread_Disable_dispatch(); - executing = _Thread_Executing; - thread_support = executing->API_Extensions[ THREAD_API_POSIX ]; - - if ( thread_support->cancelability_state == PTHREAD_CANCEL_ENABLE && - thread_support->cancelation_requested ) - cancel = true; - _Thread_Enable_dispatch(); - - if ( cancel ) - _POSIX_Thread_Exit( executing, PTHREAD_CANCELED ); + _Thread_Change_life( 0, 0, THREAD_LIFE_CHANGE_DEFERRED ); } diff --git a/cpukit/score/include/rtems/score/thread.h b/cpukit/score/include/rtems/score/thread.h index 352fb2e434..8672fddfd2 100644 --- a/cpukit/score/include/rtems/score/thread.h +++ b/cpukit/score/include/rtems/score/thread.h @@ -526,6 +526,7 @@ typedef enum { THREAD_LIFE_PROTECTED = 0x1, THREAD_LIFE_RESTARTING = 0x2, THREAD_LIFE_TERMINATING = 0x4, + THREAD_LIFE_CHANGE_DEFERRED = 0x8, THREAD_LIFE_DETACHED = 0x10 } Thread_Life_state; diff --git a/cpukit/score/include/rtems/score/threadimpl.h b/cpukit/score/include/rtems/score/threadimpl.h index 6f97ca9866..549ca7ac35 100644 --- a/cpukit/score/include/rtems/score/threadimpl.h +++ b/cpukit/score/include/rtems/score/threadimpl.h @@ -205,6 +205,12 @@ bool _Thread_Restart_other( void _Thread_Yield( Thread_Control *executing ); +Thread_Life_state _Thread_Change_life( + Thread_Life_state clear, + Thread_Life_state set, + Thread_Life_state ignore +); + Thread_Life_state _Thread_Set_life_protection( Thread_Life_state state ); /** @@ -933,7 +939,8 @@ RTEMS_INLINE_ROUTINE bool _Thread_Is_life_change_allowed( Thread_Life_state life_state ) { - return ( life_state & THREAD_LIFE_PROTECTED ) == 0; + return ( life_state + & ( THREAD_LIFE_PROTECTED | THREAD_LIFE_CHANGE_DEFERRED ) ) == 0; } RTEMS_INLINE_ROUTINE bool _Thread_Is_life_changing( diff --git a/cpukit/score/src/threadrestart.c b/cpukit/score/src/threadrestart.c index fbda7adbb8..33c56e023c 100644 --- a/cpukit/score/src/threadrestart.c +++ b/cpukit/score/src/threadrestart.c @@ -558,7 +558,7 @@ void _Thread_Exit( executing, 0, set, - THREAD_LIFE_PROTECTED + THREAD_LIFE_PROTECTED | THREAD_LIFE_CHANGE_DEFERRED ); _Thread_State_release( executing, &lock_context ); } @@ -630,7 +630,7 @@ void _Thread_Restart_self( executing, 0, THREAD_LIFE_RESTARTING, - THREAD_LIFE_PROTECTED + THREAD_LIFE_PROTECTED | THREAD_LIFE_CHANGE_DEFERRED ); cpu_self = _Thread_Dispatch_disable_critical( lock_context ); @@ -647,7 +647,7 @@ void _Thread_Restart_self( RTEMS_UNREACHABLE(); } -static Thread_Life_state _Thread_Change_life( +Thread_Life_state _Thread_Change_life( Thread_Life_state clear, Thread_Life_state set, Thread_Life_state ignore -- cgit v1.2.3