[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