[PATCH 3/3] posix: Allow pthread_cancel() from within ISRs
Sebastian Huber
sebastian.huber at embedded-brains.de
Mon May 17 13:06:55 UTC 2021
Close #4413.
---
cpukit/posix/src/cancel.c | 13 ++---
testsuites/psxtests/psxcancel01/init.c | 72 +++++++++++++++-----------
2 files changed, 45 insertions(+), 40 deletions(-)
diff --git a/cpukit/posix/src/cancel.c b/cpukit/posix/src/cancel.c
index f2636e6a97..aa4a434037 100644
--- a/cpukit/posix/src/cancel.c
+++ b/cpukit/posix/src/cancel.c
@@ -38,14 +38,6 @@ int pthread_cancel( pthread_t thread )
Thread_Control *executing;
Per_CPU_Control *cpu_self;
- /*
- * Don't even think about deleting a resource from an ISR.
- */
-
- if ( _ISR_Is_in_progress() ) {
- return EPROTO;
- }
-
the_thread = _Thread_Get( thread, &lock_context );
if ( the_thread == NULL ) {
@@ -55,7 +47,10 @@ int pthread_cancel( pthread_t thread )
cpu_self = _Per_CPU_Get();
executing = _Per_CPU_Get_executing( cpu_self );
- if ( the_thread == executing ) {
+ if (
+ the_thread == executing &&
+ !_Per_CPU_Is_ISR_in_progress( cpu_self )
+ ) {
_ISR_lock_ISR_enable( &lock_context );
_Thread_Exit( PTHREAD_CANCELED, THREAD_LIFE_TERMINATING );
} else {
diff --git a/testsuites/psxtests/psxcancel01/init.c b/testsuites/psxtests/psxcancel01/init.c
index d87295ccd1..b0da991bad 100644
--- a/testsuites/psxtests/psxcancel01/init.c
+++ b/testsuites/psxtests/psxcancel01/init.c
@@ -18,38 +18,37 @@ const char rtems_test_name[] = "PSXCANCEL 1";
/* forward declarations to avoid warnings */
void *POSIX_Init(void *argument);
-rtems_timer_service_routine Cancel_duringISR_TSR(
- rtems_id ignored_id,
- void *ignored_address
-);
-rtems_timer_service_routine SetState_duringISR_TSR(
- rtems_id ignored_id,
- void *ignored_address
-);
-rtems_timer_service_routine SetType_duringISR_TSR(
- rtems_id ignored_id,
- void *ignored_address
-);
-void doit(
- rtems_timer_service_routine (*TSR)(rtems_id, void *),
- const char *method
-);
-volatile int TSR_occurred;
-volatile int TSR_status;
+static volatile int TSR_occurred;
+
+static volatile int TSR_status;
+
+static rtems_id timer_id;
-rtems_id timer_id;
+static pthread_t thread;
-rtems_timer_service_routine Cancel_duringISR_TSR(
+static void *suspend_self( void *arg )
+{
+ rtems_status_code status;
+
+ (void) arg;
+
+ status = rtems_task_suspend( RTEMS_SELF);
+ rtems_test_assert( status == RTEMS_SUCCESSFUL );
+
+ return NULL;
+}
+
+static rtems_timer_service_routine Cancel_duringISR_TSR(
rtems_id ignored_id,
void *ignored_address
)
{
- TSR_status = pthread_cancel( pthread_self() );
+ TSR_status = pthread_cancel( thread );
TSR_occurred = 1;
}
-rtems_timer_service_routine SetState_duringISR_TSR(
+static rtems_timer_service_routine SetState_duringISR_TSR(
rtems_id ignored_id,
void *ignored_address
)
@@ -60,7 +59,7 @@ rtems_timer_service_routine SetState_duringISR_TSR(
TSR_occurred = 1;
}
-rtems_timer_service_routine SetType_duringISR_TSR(
+static rtems_timer_service_routine SetType_duringISR_TSR(
rtems_id ignored_id,
void *ignored_address
)
@@ -71,9 +70,10 @@ rtems_timer_service_routine SetType_duringISR_TSR(
TSR_occurred = 1;
}
-void doit(
+static void doit(
rtems_timer_service_routine (*TSR)(rtems_id, void *),
- const char *method
+ const char *method,
+ int expected_status
)
{
rtems_interval start;
@@ -97,11 +97,11 @@ void doit(
printf( "%s did not occur\n", method );
rtems_test_exit(0);
}
- if ( TSR_status != EPROTO ) {
+ if ( TSR_status != expected_status ) {
printf( "%s returned %s\n", method, strerror(TSR_status) );
rtems_test_exit(0);
}
- printf( "%s - from ISR returns EPROTO - OK\n", method );
+ printf( "%s - from ISR returns expected status - OK\n", method );
}
@@ -110,6 +110,8 @@ void *POSIX_Init(
)
{
rtems_status_code status;
+ int eno;
+ void *value;
TEST_BEGIN();
@@ -119,9 +121,17 @@ void *POSIX_Init(
);
rtems_test_assert( !status );
- doit( Cancel_duringISR_TSR, "pthread_cancel" );
- doit( SetState_duringISR_TSR, "pthread_setcancelstate" );
- doit( SetType_duringISR_TSR, "pthread_setcanceltype" );
+ eno = pthread_create( &thread, NULL, suspend_self, NULL );
+ rtems_test_assert( eno == 0 );
+
+ doit( Cancel_duringISR_TSR, "pthread_cancel", 0 );
+ doit( SetState_duringISR_TSR, "pthread_setcancelstate", EPROTO );
+ doit( SetType_duringISR_TSR, "pthread_setcanceltype", EPROTO );
+
+ value = NULL;
+ eno = pthread_join( thread, &value );
+ rtems_test_assert( eno == 0 );
+ rtems_test_assert( value == PTHREAD_CANCELED );
TEST_END();
rtems_test_exit(0);
@@ -137,7 +147,7 @@ void *POSIX_Init(
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
-#define CONFIGURE_MAXIMUM_POSIX_THREADS 1
+#define CONFIGURE_MAXIMUM_POSIX_THREADS 2
#define CONFIGURE_POSIX_INIT_THREAD_TABLE
#define CONFIGURE_INIT
--
2.26.2
More information about the devel
mailing list