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.
This commit is contained in:
Sebastian Huber
2016-05-13 10:28:14 +02:00
parent 33829ce155
commit da82656065
16 changed files with 98 additions and 275 deletions

View File

@@ -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

View File

@@ -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 <rtems/posix/threadsup.h>
/**
* @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 */

View File

@@ -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

View File

@@ -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

View File

@@ -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 <rtems/score/isr.h>
#include <rtems/score/threadimpl.h>
#include <rtems/posix/cancel.h>
#include <rtems/posix/threadsup.h>
/*
* 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 ) {
case OBJECTS_LOCAL:
thread_support = the_thread->API_Extensions[ THREAD_API_POSIX ];
thread_support->cancelation_requested = 1;
/* This enables dispatch implicitly */
_POSIX_Thread_Evaluate_cancellation_and_enable_dispatch( the_thread );
return 0;
#if defined(RTEMS_MULTIPROCESSING)
case OBJECTS_REMOTE:
#endif
case OBJECTS_ERROR:
break;
}
return ESRCH;
the_thread = _Thread_Get_interrupt_disable( thread, &lock_context );
if ( the_thread == NULL ) {
return ESRCH;
}
cpu_self = _Thread_Dispatch_disable_critical( &lock_context );
_ISR_lock_ISR_enable( &lock_context );
executing = _Per_CPU_Get_executing( cpu_self );
if ( the_thread == executing ) {
_Thread_Exit( executing, THREAD_LIFE_TERMINATING, PTHREAD_CANCELED );
} else {
_Thread_Cancel( the_thread, executing, PTHREAD_CANCELED );
}
_Thread_Dispatch_enable( cpu_self );
return 0;
}

View File

@@ -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 <pthread.h>
#include <rtems/system.h>
#include <rtems/score/thread.h>
#include <rtems/posix/cancel.h>
#include <rtems/posix/pthreadimpl.h>
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 );
}

View File

@@ -33,7 +33,6 @@
#include <rtems/score/userextimpl.h>
#include <rtems/score/watchdogimpl.h>
#include <rtems/score/wkspace.h>
#include <rtems/posix/cancel.h>
#include <rtems/posix/pthreadimpl.h>
#include <rtems/posix/priorityimpl.h>
#include <rtems/posix/psignalimpl.h>
@@ -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.

View File

@@ -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(

View File

@@ -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 <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>
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();
}

View File

@@ -27,7 +27,6 @@
#include <rtems/score/stack.h>
#include <rtems/score/thread.h>
#include <rtems/score/wkspace.h>
#include <rtems/posix/cancel.h>
#include <rtems/posix/posixapi.h>
#include <rtems/posix/pthreadimpl.h>
#include <rtems/posix/priorityimpl.h>

View File

@@ -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 <pthread.h>
#include <errno.h>
#include <rtems/system.h>
#include <rtems/score/chain.h>
#include <rtems/score/isr.h>
#include <rtems/score/thread.h>
#include <rtems/posix/cancel.h>
#include <rtems/posix/pthreadimpl.h>
#include <rtems/posix/threadsup.h>
#include <rtems/score/threadimpl.h>
/*
* 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;
Thread_Life_state new_life_protection;
Thread_Life_state previous_life_state;
/*
* 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 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();
previous_life_state = _Thread_Set_life_protection( new_life_protection );
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 );
/*
* _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;
}

View File

@@ -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 <pthread.h>
#include <errno.h>
#include <rtems/system.h>
#include <rtems/score/chain.h>
#include <rtems/score/isr.h>
#include <rtems/score/thread.h>
#include <rtems/posix/cancel.h>
#include <rtems/posix/pthreadimpl.h>
#include <rtems/posix/threadsup.h>
#include <rtems/score/threadimpl.h>
/*
* 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;
Thread_Life_state set_life_state;
Thread_Life_state previous_life_state;
/*
* 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 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();
previous_life_state = _Thread_Change_life(
THREAD_LIFE_CHANGE_DEFERRED,
set_life_state,
0
);
executing = _Thread_Executing;
thread_support = executing ->API_Extensions[ THREAD_API_POSIX ];
if ( oldtype != NULL ) {
if ( ( previous_life_state & THREAD_LIFE_CHANGE_DEFERRED ) != 0 ) {
*oldtype = PTHREAD_CANCEL_DEFERRED;
} else {
*oldtype = PTHREAD_CANCEL_ASYNCHRONOUS;
}
}
if ( oldtype != NULL )
*oldtype = thread_support->cancelability_type;
thread_support->cancelability_type = type;
_POSIX_Thread_Evaluate_cancellation_and_enable_dispatch( executing );
/*
* _Thread_Enable_dispatch is invoked by above call.
*/
return 0;
}

View File

@@ -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 <pthread.h>
#include <errno.h>
#include <rtems/system.h>
#include <rtems/score/chain.h>
#include <rtems/score/isr.h>
#include <rtems/score/thread.h>
#include <rtems/score/wkspace.h>
#include <rtems/posix/cancel.h>
#include <rtems/posix/pthreadimpl.h>
#include <rtems/posix/threadsup.h>
#include <rtems/score/threadimpl.h>
/*
* 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 );
}

View File

@@ -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;

View File

@@ -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(

View File

@@ -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