[rtems commit] posix: Use cleanup contexts on the stack
Sebastian Huber
sebh at rtems.org
Mon Dec 2 08:35:31 UTC 2013
Module: rtems
Branch: master
Commit: 927a0a1f990c19a3e7295bb001896b3f3c75a77e
Changeset: http://git.rtems.org/rtems/commit/?id=927a0a1f990c19a3e7295bb001896b3f3c75a77e
Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
Date: Mon Dec 2 08:33:35 2013 +0100
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.
---
cpukit/configure.ac | 1 +
cpukit/posix/include/rtems/posix/cancel.h | 2 +
cpukit/posix/include/rtems/posix/threadsup.h | 7 ++++
cpukit/posix/src/cancelrun.c | 40 ++++++++++++++++++++++---
cpukit/posix/src/cleanuppop.c | 33 ++++++++++++++++++--
cpukit/posix/src/cleanuppush.c | 37 +++++++++++++++++++++--
cpukit/posix/src/pthread.c | 4 ++
testsuites/psxtests/psxcleanup/psxcleanup.c | 7 ----
8 files changed, 111 insertions(+), 20 deletions(-)
diff --git a/cpukit/configure.ac b/cpukit/configure.ac
index e111fdd..38d2dd9 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 c1fff9c..7b2ab5c 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 7bd1f93..6bb3b84 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 9d15862..4fe4d73 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 4ec7084..7afe9e6 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 84dbc00..9d11c05 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 408bb07..4d8f95f 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 568e897..123e766 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);
More information about the vc
mailing list