summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-12-02 08:33:35 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-12-02 09:24:51 +0100
commit927a0a1f990c19a3e7295bb001896b3f3c75a77e (patch)
treeb4c1cdb1a406b700a17b80e235613c9ced8c0cd9
parentpstmtests_plan.csv: Update to reflect psxtmcond 09 and 10 exit (diff)
downloadrtems-927a0a1f990c19a3e7295bb001896b3f3c75a77e.tar.bz2
posix: Use cleanup contexts on the stack
Provide support for latest Newlib <pthread.h> change. The cleanup contexts are stored on the thread stack. This is conformant with the POSIX requirements for the pthread_cleanup_push() and pthread_cleanup_pop() statement pair. Passing an invalid pointer as the routine to pthread_cleanup_push() is now a usage error and the behaviour is undefined.
-rw-r--r--cpukit/configure.ac1
-rw-r--r--cpukit/posix/include/rtems/posix/cancel.h2
-rw-r--r--cpukit/posix/include/rtems/posix/threadsup.h7
-rw-r--r--cpukit/posix/src/cancelrun.c40
-rw-r--r--cpukit/posix/src/cleanuppop.c33
-rw-r--r--cpukit/posix/src/cleanuppush.c37
-rw-r--r--cpukit/posix/src/pthread.c4
-rw-r--r--testsuites/psxtests/psxcleanup/psxcleanup.c7
8 files changed, 111 insertions, 20 deletions
diff --git a/cpukit/configure.ac b/cpukit/configure.ac
index e111fdd0fc..38d2dd9eba 100644
--- a/cpukit/configure.ac
+++ b/cpukit/configure.ac
@@ -140,6 +140,7 @@ AC_CHECK_HEADER([pthread.h],[
AC_CHECK_TYPES([pthread_rwlock_t])
AC_CHECK_TYPES([pthread_barrier_t])
AC_CHECK_TYPES([pthread_spinlock_t])
+ AC_CHECK_TYPES([struct _pthread_cleanup_context],[],[],[#include <pthread.h>])
])
AC_CHECK_HEADER([signal.h],[
diff --git a/cpukit/posix/include/rtems/posix/cancel.h b/cpukit/posix/include/rtems/posix/cancel.h
index c1fff9c04d..7b2ab5ca42 100644
--- a/cpukit/posix/include/rtems/posix/cancel.h
+++ b/cpukit/posix/include/rtems/posix/cancel.h
@@ -21,6 +21,7 @@
#include <rtems/posix/threadsup.h>
+#ifndef HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT
/**
* This structure is used to manage the cancelation handlers.
*/
@@ -32,6 +33,7 @@ typedef struct {
/** This field is the argument to the cancelation routine. */
void *arg;
} POSIX_Cancel_Handler_control;
+#endif /* HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT */
/**
* @brief POSIX run thread cancelation.
diff --git a/cpukit/posix/include/rtems/posix/threadsup.h b/cpukit/posix/include/rtems/posix/threadsup.h
index 7bd1f934ad..6bb3b844cc 100644
--- a/cpukit/posix/include/rtems/posix/threadsup.h
+++ b/cpukit/posix/include/rtems/posix/threadsup.h
@@ -80,8 +80,15 @@ typedef struct {
int cancelability_type;
/** This indicates if a cancelation has been requested. */
int cancelation_requested;
+#ifndef HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT
/** This is the set of cancelation handlers. */
Chain_Control Cancellation_Handlers;
+#else /* HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT */
+ /**
+ * @brief LIFO list of cleanup contexts.
+ */
+ struct _pthread_cleanup_context *last_cleanup_context;
+#endif /* HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT */
/**
* This is the thread key value chain's control, which is used
diff --git a/cpukit/posix/src/cancelrun.c b/cpukit/posix/src/cancelrun.c
index 9d158627de..4fe4d732ae 100644
--- a/cpukit/posix/src/cancelrun.c
+++ b/cpukit/posix/src/cancelrun.c
@@ -19,16 +19,18 @@
#endif
#include <pthread.h>
-#include <errno.h>
-#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threaddispatch.h>
+#include <rtems/posix/cancel.h>
+#include <rtems/posix/threadsup.h>
+
+#ifndef HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT
+
#include <rtems/score/chainimpl.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>
void _POSIX_Threads_cancel_run(
Thread_Control *the_thread
@@ -57,3 +59,31 @@ void _POSIX_Threads_cancel_run(
_Workspace_Free( handler );
}
}
+
+#else /* HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT */
+
+void _POSIX_Threads_cancel_run(
+ Thread_Control *the_thread
+)
+{
+ struct _pthread_cleanup_context *context;
+ POSIX_API_Control *thread_support;
+
+ _Thread_Disable_dispatch();
+
+ thread_support = the_thread->API_Extensions[ THREAD_API_POSIX ];
+ thread_support->cancelability_state = PTHREAD_CANCEL_DISABLE;
+
+ context = thread_support->last_cleanup_context;
+ thread_support->last_cleanup_context = NULL;
+
+ _Thread_Enable_dispatch();
+
+ while ( context != NULL ) {
+ ( *context->_routine )( context->_arg );
+
+ context = context->_previous;
+ }
+}
+
+#endif /* HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT */
diff --git a/cpukit/posix/src/cleanuppop.c b/cpukit/posix/src/cleanuppop.c
index 4ec7084fdd..7afe9e6cd0 100644
--- a/cpukit/posix/src/cleanuppop.c
+++ b/cpukit/posix/src/cleanuppop.c
@@ -19,16 +19,18 @@
#endif
#include <pthread.h>
-#include <errno.h>
-#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threaddispatch.h>
+#include <rtems/posix/threadsup.h>
+
+#ifndef HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT
+
#include <rtems/score/chainimpl.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>
/*
* 18.2.3.1 Establishing Cancellation Handlers, P1003.1c/Draft 10, p. 184
@@ -79,3 +81,26 @@ void pthread_cleanup_pop(
if ( execute )
(*tmp_handler.routine)( tmp_handler.arg );
}
+
+#else /* HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT */
+
+void _pthread_cleanup_pop(
+ struct _pthread_cleanup_context *context,
+ int execute
+)
+{
+ POSIX_API_Control *thread_support;
+
+ if ( execute != 0 ) {
+ ( *context->_routine )( context->_arg );
+ }
+
+ _Thread_Disable_dispatch();
+
+ thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+ thread_support->last_cleanup_context = context->_previous;
+
+ _Thread_Enable_dispatch();
+}
+
+#endif /* HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT */
diff --git a/cpukit/posix/src/cleanuppush.c b/cpukit/posix/src/cleanuppush.c
index 84dbc0043d..9d11c0553f 100644
--- a/cpukit/posix/src/cleanuppush.c
+++ b/cpukit/posix/src/cleanuppush.c
@@ -19,16 +19,18 @@
#endif
#include <pthread.h>
-#include <errno.h>
-#include <rtems/system.h>
+#include <rtems/score/thread.h>
+#include <rtems/score/threaddispatch.h>
+#include <rtems/posix/threadsup.h>
+
+#ifndef HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT
+
#include <rtems/score/chainimpl.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>
/*
* 18.2.3.1 Establishing Cancellation Handlers, P1003.1c/Draft 10, p. 184
@@ -66,3 +68,30 @@ void pthread_cleanup_push(
}
_Thread_Enable_dispatch();
}
+
+#else /* HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT */
+
+void _pthread_cleanup_push(
+ struct _pthread_cleanup_context *context,
+ void ( *routine )( void * ),
+ void *arg
+)
+{
+ POSIX_API_Control *thread_support;
+
+ context->_routine = routine;
+ context->_arg = arg;
+
+ /* This value is unused, just provide a deterministic value */
+ context->_canceltype = -1;
+
+ _Thread_Disable_dispatch();
+
+ thread_support = _Thread_Executing->API_Extensions[ THREAD_API_POSIX ];
+ context->_previous = thread_support->last_cleanup_context;
+ thread_support->last_cleanup_context = context;
+
+ _Thread_Enable_dispatch();
+}
+
+#endif /* HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT */
diff --git a/cpukit/posix/src/pthread.c b/cpukit/posix/src/pthread.c
index 408bb07dc4..4d8f95f150 100644
--- a/cpukit/posix/src/pthread.c
+++ b/cpukit/posix/src/pthread.c
@@ -200,7 +200,11 @@ static bool _POSIX_Threads_Create_extension(
api->cancelation_requested = 0;
api->cancelability_state = PTHREAD_CANCEL_ENABLE;
api->cancelability_type = PTHREAD_CANCEL_DEFERRED;
+#ifndef HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT
_Chain_Initialize_empty (&api->Cancellation_Handlers);
+#else /* HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT */
+ api->last_cleanup_context = NULL;
+#endif /* HAVE_STRUCT__PTHREAD_CLEANUP_CONTEXT */
/*
* If the thread is not a posix thread, then all posix signals are blocked
diff --git a/testsuites/psxtests/psxcleanup/psxcleanup.c b/testsuites/psxtests/psxcleanup/psxcleanup.c
index 568e897a76..123e76692c 100644
--- a/testsuites/psxtests/psxcleanup/psxcleanup.c
+++ b/testsuites/psxtests/psxcleanup/psxcleanup.c
@@ -250,13 +250,6 @@ void *POSIX_Init(
sleep(1);
- /*************** ERROR CASES ***************/
- puts("Call pthread_cleanup_push with NULL handler");
- pthread_cleanup_push(NULL, NULL);
-
- puts("Call pthread_cleanup_pop with no push");
- pthread_cleanup_pop(1);
-
/*************** END OF TEST *****************/
puts( "*** END OF POSIX CLEANUP TEST ***\n" );
rtems_test_exit(0);