[rtems commit] posix: Run key destructors during thread restart

Sebastian Huber sebh at rtems.org
Thu Apr 14 07:01:05 UTC 2016


Module:    rtems
Branch:    master
Commit:    6efa3498504bffde166b4663319bd7d94ea42a08
Changeset: http://git.rtems.org/rtems/commit/?id=6efa3498504bffde166b4663319bd7d94ea42a08

Author:    Sebastian Huber <sebastian.huber at embedded-brains.de>
Date:      Thu Apr 14 08:56:53 2016 +0200

posix: Run key destructors during thread restart

POSIX key destructors must be called during thread restart.  Just like
the POSIX cleanup handlers.  This ensures that the TLS object
destructors are called during thread restart for example.  It is
important for the global construction, which uses a thread restart to
run the Init task in a clean environment.

Close #2689.

---

 cpukit/posix/src/key.c                    | 10 ++++
 testsuites/psxtests/psxkey06/init.c       | 96 ++++++++++++++++++++++++++++---
 testsuites/psxtests/psxkey06/psxkey06.scn | 17 ++++--
 testsuites/sptests/sptls02/init.cc        | 51 ++++++++++++----
 testsuites/sptests/sptls02/sptls02.scn    |  2 +-
 5 files changed, 150 insertions(+), 26 deletions(-)

diff --git a/cpukit/posix/src/key.c b/cpukit/posix/src/key.c
index 389a28b..0bc88ae 100644
--- a/cpukit/posix/src/key.c
+++ b/cpukit/posix/src/key.c
@@ -111,8 +111,18 @@ static void _POSIX_Keys_Run_destructors( Thread_Control *the_thread )
   }
 }
 
+static void _POSIX_Keys_Restart_run_destructors(
+  Thread_Control *executing,
+  Thread_Control *the_thread
+)
+{
+  (void) executing;
+  _POSIX_Keys_Run_destructors( the_thread );
+}
+
 static User_extensions_Control _POSIX_Keys_Extensions = {
   .Callouts = {
+    .thread_restart = _POSIX_Keys_Restart_run_destructors,
     .thread_terminate = _POSIX_Keys_Run_destructors
   }
 };
diff --git a/testsuites/psxtests/psxkey06/init.c b/testsuites/psxtests/psxkey06/init.c
index 2e4804d..28236c2 100644
--- a/testsuites/psxtests/psxkey06/init.c
+++ b/testsuites/psxtests/psxkey06/init.c
@@ -19,16 +19,34 @@
 
 const char rtems_test_name[] = "PSXKEY 6";
 
-/* forward declarations to avoid warnings */
-rtems_task Init(rtems_task_argument argument);
-rtems_task Test_Thread1(rtems_task_argument argument);
-rtems_task Test_Thread2(rtems_task_argument argument);
+static int Data_array[4] = {1, 2, 3, 4};
 
-int Data_array[4] = {1, 2, 3, 4};
+static pthread_key_t key1, key2, key3;
 
-pthread_key_t key1, key2;
+static rtems_id Thread_Master;
 
-rtems_task Test_Thread1( rtems_task_argument argument )
+static int Key3_Destructor_Counter;
+
+static void Wake_Up_Master(void)
+{
+  rtems_status_code rc;
+
+  rc = rtems_event_transient_send( Thread_Master );
+  rtems_test_assert( rc == RTEMS_SUCCESSFUL );
+}
+
+static void Wait_For_Worker(void)
+{
+  rtems_status_code rc;
+
+  rc = rtems_event_transient_receive(
+    RTEMS_WAIT,
+    RTEMS_NO_TIMEOUT
+  );
+  rtems_test_assert( rc == RTEMS_SUCCESSFUL );
+}
+
+static rtems_task Test_Thread1( rtems_task_argument argument )
 {
   int sc;
   int *value;
@@ -59,7 +77,7 @@ rtems_task Test_Thread1( rtems_task_argument argument )
   rtems_task_delete( RTEMS_SELF );
 }
 
-rtems_task Test_Thread2( rtems_task_argument argument )
+static rtems_task Test_Thread2( rtems_task_argument argument )
 {
   int sc;
   int *value;
@@ -83,16 +101,49 @@ rtems_task Test_Thread2( rtems_task_argument argument )
   rtems_task_delete( RTEMS_SELF );
 }
 
-rtems_task Init( rtems_task_argument ignored )
+static void Key3_Destructor( void *value )
+{
+  rtems_test_assert( value == &Thread_Master );
+  ++Key3_Destructor_Counter;
+}
+
+static rtems_task Test_Thread3( rtems_task_argument argument )
+{
+  int   sc;
+  void *value;
+
+  puts( "Test_Thread 3 - key3 pthread_getspecific - OK" );
+  value = pthread_getspecific( key3 );
+  rtems_test_assert( value == NULL );
+
+  puts( "Test_Thread 3 - key3 pthread_setspecific - OK" );
+  sc = pthread_setspecific( key3, &Thread_Master );
+  rtems_test_assert( sc == 0 );
+
+  if ( argument == 0 ) {
+    puts( "Test_Thread 3 - restart self - OK" );
+    rtems_task_restart( RTEMS_SELF, 1 );
+  } else if ( argument == 1 ) {
+    Wake_Up_Master();
+    rtems_task_delete( RTEMS_SELF );
+  }
+
+  rtems_test_assert( false );
+}
+
+static rtems_task Init( rtems_task_argument ignored )
 {
   rtems_id          thread1;
   rtems_id          thread2;
+  rtems_id          thread3;
   rtems_status_code rc;
   int               sc;
   struct timespec   delay_request;
 
   TEST_BEGIN();
 
+  Thread_Master = rtems_task_self();
+
   puts( "Init - pthread key1 create - OK" );
   sc = pthread_key_create( &key1, NULL );
   rtems_test_assert( !sc );
@@ -143,6 +194,33 @@ rtems_task Init( rtems_task_argument ignored )
   sc = pthread_key_delete( key2 );
   rtems_test_assert( sc == 0 );
 
+  puts( "Init - pthread key3 create - OK" );
+  sc = pthread_key_create( &key3, Key3_Destructor );
+  rtems_test_assert( sc == 0 );
+
+  puts( "Init - thread3 create - OK" );
+  rc = rtems_task_create(
+    rtems_build_name( 'R', 'E', 'S', 'T' ),
+    1,
+    RTEMS_MINIMUM_STACK_SIZE,
+    RTEMS_DEFAULT_MODES,
+    RTEMS_DEFAULT_ATTRIBUTES,
+    &thread3
+  );
+  rtems_test_assert( rc == RTEMS_SUCCESSFUL );
+
+  puts( "Init - thread3 start - OK" );
+  rc = rtems_task_start( thread3, Test_Thread3, 0 );
+  rtems_test_assert( rc == RTEMS_SUCCESSFUL );
+
+  Wait_For_Worker();
+
+  rtems_test_assert( Key3_Destructor_Counter == 2 );
+
+  puts( "Init - pthread key3 delete - OK" );
+  sc = pthread_key_delete( key3 );
+  rtems_test_assert( sc == 0 );
+
   TEST_END();
   rtems_test_exit(0);
 }
diff --git a/testsuites/psxtests/psxkey06/psxkey06.scn b/testsuites/psxtests/psxkey06/psxkey06.scn
index a105b6f..47ab42f 100644
--- a/testsuites/psxtests/psxkey06/psxkey06.scn
+++ b/testsuites/psxtests/psxkey06/psxkey06.scn
@@ -1,8 +1,8 @@
-*** TEST KEY 06 ***
+*** BEGIN OF TEST PSXKEY 6 ***
 Init - pthread key1 create - OK
 Init - pthread key2 create - OK
-Init - pthread1 create - OK
-Init - pthread2 create - OK
+Init - thread1 create - OK
+Init - thread2 create - OK
 Init - sleep - let thread run - OK
 Test_Thread 1 - key1 pthread_setspecific - OK
 Test_Thread 1 - key2 pthread_setspecific - OK
@@ -15,4 +15,13 @@ Test_Thread 1 - key1 pthread_getspecific - OK
 Test_Thread 1 - key2 pthread_getspecific - OK
 Init - pthread key1 delete - OK
 Init - pthread key2 delete - OK
-*** END OF TEST KEY 06 ***
+Init - pthread key3 create - OK
+Init - thread3 create - OK
+Init - thread3 start - OK
+Test_Thread 3 - key3 pthread_getspecific - OK
+Test_Thread 3 - key3 pthread_setspecific - OK
+Test_Thread 3 - restart self - OK
+Test_Thread 3 - key3 pthread_getspecific - OK
+Test_Thread 3 - key3 pthread_setspecific - OK
+Init - pthread key3 delete - OK
+*** END OF TEST PSXKEY 6 ***
diff --git a/testsuites/sptests/sptls02/init.cc b/testsuites/sptests/sptls02/init.cc
index b15e358..dc2e123 100644
--- a/testsuites/sptests/sptls02/init.cc
+++ b/testsuites/sptests/sptls02/init.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014 embedded brains GmbH.  All rights reserved.
+ * Copyright (c) 2014, 2016 embedded brains GmbH.  All rights reserved.
  *
  *  embedded brains GmbH
  *  Dornierstr. 4
@@ -162,8 +162,24 @@ static void checkTLSValues()
 
 static rtems_id masterTask;
 
-static void task(rtems_task_argument arg)
+static void wakeUpMaster()
 {
+	rtems_status_code sc = rtems_event_transient_send(masterTask);
+	rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void waitForWorker()
+{
+	rtems_status_code sc = rtems_event_transient_receive(
+		RTEMS_WAIT,
+		RTEMS_NO_TIMEOUT
+	);
+	rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void worker(rtems_task_argument arg)
+{
+	wakeUpMaster();
 	checkTLSValues();
 
 	const long gc = static_cast<long>(arg);
@@ -182,21 +198,20 @@ static void task(rtems_task_argument arg)
 	a2.clobber();
 	a3.clobber();
 
-	rtems_status_code sc = rtems_event_transient_send(masterTask);
-	rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+	wakeUpMaster();
 
-	sc = rtems_task_suspend(RTEMS_SELF);
-	rtems_test_assert(sc == RTEMS_SUCCESSFUL);
+	(void) rtems_task_suspend(RTEMS_SELF);
+	rtems_test_assert(false);
 }
 
-static void testTask()
+static void testWorkerTask()
 {
 	checkTLSValues();
 
 	rtems_id id;
 	rtems_status_code sc = rtems_task_create(
 		rtems_build_name('T', 'A', 'S', 'K'),
-		RTEMS_MINIMUM_PRIORITY,
+		2,
 		RTEMS_MINIMUM_STACK_SIZE,
 		RTEMS_DEFAULT_MODES,
 		RTEMS_DEFAULT_ATTRIBUTES,
@@ -206,12 +221,24 @@ static void testTask()
 
 	const long gc = A::globalCounter();
 
-	sc = rtems_task_start(id, task, gc);
+	sc = rtems_task_start(id, worker, gc);
 	rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 
-	sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+	waitForWorker();
+	rtems_test_assert(A::globalCounter() == gc);
+
+	waitForWorker();
+	rtems_test_assert(A::globalCounter() == gc + 3);
+
+	sc = rtems_task_restart(id, gc);
 	rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 
+	waitForWorker();
+	rtems_test_assert(A::globalCounter() == gc);
+
+	waitForWorker();
+	rtems_test_assert(A::globalCounter() == gc + 3);
+
 	sc = rtems_task_delete(id);
 	rtems_test_assert(sc == RTEMS_SUCCESSFUL);
 
@@ -232,12 +259,12 @@ extern "C" void Init(rtems_task_argument arg)
 
 	masterTask = rtems_task_self();
 
-	testTask();
+	testWorkerTask();
 
 	rtems_resource_snapshot snapshot;
 	rtems_resource_snapshot_take(&snapshot);
 
-	testTask();
+	testWorkerTask();
 
 	rtems_test_assert(rtems_resource_snapshot_check(&snapshot));
 
diff --git a/testsuites/sptests/sptls02/sptls02.scn b/testsuites/sptests/sptls02/sptls02.scn
index e4c92f5..01593d9 100644
--- a/testsuites/sptests/sptls02/sptls02.scn
+++ b/testsuites/sptests/sptls02/sptls02.scn
@@ -1,4 +1,4 @@
-*** TEST SPTLS 2 ***
+*** BEGIN OF TEST SPTLS 2 ***
 A::globalCounter() = 0
 A::globalCounter() = 3
 *** END OF TEST SPTLS 2 ***



More information about the vc mailing list