[rtems commit] libcsupport: Use POSIX keys for GXX key functions

Sebastian Huber sebh at rtems.org
Mon Mar 24 07:25:02 UTC 2014


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

Author:    Christian Mauderer <Christian.Mauderer at embedded-brains.de>
Date:      Fri Mar 21 14:29:55 2014 +0100

libcsupport: Use POSIX keys for GXX key functions

With this patch C++ applications now eventually need additional POSIX-keys and
POSIX-key-value-pairs configured.

---

 cpukit/libcsupport/include/rtems/gxx_wrappers.h |    8 +--
 cpukit/libcsupport/src/gxx_wrappers.c           |  112 +++++++++++------------
 testsuites/libtests/gxx01/gxx01.scn             |    8 +-
 testsuites/libtests/gxx01/init.c                |   29 +++++-
 testsuites/sptests/spfatal24/spfatal24.doc      |    2 +-
 testsuites/sptests/spfatal24/testcase.h         |    6 +-
 testsuites/sptests/sptls02/init.cc              |    3 +
 7 files changed, 90 insertions(+), 78 deletions(-)

diff --git a/cpukit/libcsupport/include/rtems/gxx_wrappers.h b/cpukit/libcsupport/include/rtems/gxx_wrappers.h
index 801223e..94502b9 100644
--- a/cpukit/libcsupport/include/rtems/gxx_wrappers.h
+++ b/cpukit/libcsupport/include/rtems/gxx_wrappers.h
@@ -36,14 +36,8 @@ extern "C" {
 /*
  * These typedefs should match with the ones defined in the file
  * gcc/gthr-rtems.h in the gcc distribution.
- * FIXME: T.S, 2007/01/31: -> gcc/gthr-rtems.h still declares
- *                            void * __gthread_key_t;
  */
-typedef struct __gthread_key_ {
-	void *val; 	           /* this is switched with the task      */
-	void (*dtor)(void*);   /* this remains in place for all tasks */
-} __gthread_key, *__gthread_key_t;
-
+typedef void *__gthread_key_t;
 typedef int   __gthread_once_t;
 typedef void *__gthread_mutex_t;
 typedef void *__gthread_recursive_mutex_t;
diff --git a/cpukit/libcsupport/src/gxx_wrappers.c b/cpukit/libcsupport/src/gxx_wrappers.c
index 0b9cad6..82f4bdb 100644
--- a/cpukit/libcsupport/src/gxx_wrappers.c
+++ b/cpukit/libcsupport/src/gxx_wrappers.c
@@ -31,7 +31,9 @@
 #include <rtems/gxx_wrappers.h>
 #include <rtems/score/onceimpl.h>
 
+#include <errno.h>
 #include <stdlib.h>
+#include <pthread.h>
 
 #include <rtems.h>
 
@@ -49,82 +51,64 @@ int rtems_gxx_once(__gthread_once_t *once, void (*func) (void))
 
 int rtems_gxx_key_create (__gthread_key_t *key, void (*dtor) (void *))
 {
-  rtems_status_code status;
-
-  /* Ok, this can be a bit tricky. We are going to return a "key" as a
-   * pointer to the buffer that will hold the value of the key itself.
-   * We have to to this, because the others functions on this interface
-   * deal with the value of the key, as used with the POSIX API.
-   */
-   /* Do not pull your hair, trust me this works. :-) */
-  __gthread_key_t new_key = (__gthread_key_t) malloc( sizeof( *new_key ) );
-  *key = new_key;
-  new_key->val  = NULL;
-  new_key->dtor = dtor;
+  int eno;
+  pthread_key_t *pkey;
+
+  pkey = malloc( sizeof( *pkey ) );
+  *key = pkey;
+  if ( pkey == NULL )
+  {
+    return ENOMEM;
+  }
 
   #ifdef DEBUG_GXX_WRAPPERS
     printk(
-      "gxx_wrappers: create key=%x, dtor=%x, new_key=%x\n", key, dtor, new_key
+      "gxx_wrappers: create key=%x, dtor=%x, pkey=%x\n", key, dtor, pkey
     );
   #endif
 
-  /* register with RTEMS the buffer that will hold the key values */
-  status = rtems_task_variable_add( RTEMS_SELF, (void **)new_key, dtor );
-  if ( status == RTEMS_SUCCESSFUL )
-    return 0;
+  eno = pthread_key_create(pkey, dtor);
+  if ( eno != 0 ) {
+    free( pkey );
+    *key = NULL;
+  }
 
-  free( new_key );
-  return -1;
+  return eno;
 }
 
 int rtems_gxx_key_delete (__gthread_key_t key)
 {
-  rtems_status_code status;
+  int eno = 0;
+  pthread_key_t *pkey = key;
 
   #ifdef DEBUG_GXX_WRAPPERS
-    printk( "gxx_wrappers: delete key=%x\n", key );
+    printk( "gxx_wrappers: delete key=%x\n", pkey );
   #endif
 
-  /* register with RTEMS the buffer that will hold the key values */
-  status = rtems_task_variable_delete( RTEMS_SELF, (void **)key );
-  if ( status == RTEMS_SUCCESSFUL ) {
-    /* Hmm - hopefully all tasks using this key have gone away... */
-    if ( key ) free( *(void **)key );
-    return 0;
+  if ( pkey == NULL ) {
+    return EINVAL;
   }
-  key = NULL;
-  return 0;
+
+  eno = pthread_key_delete(*pkey);
+  if ( eno == 0 ) {
+    free( pkey );
+  }
+  return eno;
 }
 
 void *rtems_gxx_getspecific(__gthread_key_t key)
 {
-  rtems_status_code  status;
-  void              *p= 0;
-
-  /* register with RTEMS the buffer that will hold the key values */
-  status = rtems_task_variable_get( RTEMS_SELF, (void **)key, &p );
-  if ( status == RTEMS_SUCCESSFUL ) {
-    /* We do not have to do this, but what the heck ! */
-     p= key->val;
-  } else {
-    /* fisrt time, always set to zero, it is unknown the value that the others
-     * threads are using at the moment of this call
-     */
-    status = rtems_task_variable_add( RTEMS_SELF, (void **)key, key->dtor );
-    if ( status != RTEMS_SUCCESSFUL ) {
-      _Terminate(
-        INTERNAL_ERROR_CORE,
-        true,
-        INTERNAL_ERROR_GXX_KEY_ADD_FAILED
-      );
-    }
-    key->val = (void *)0;
+  pthread_key_t *pkey = key;
+  void *p = NULL;
+
+  if ( pkey != NULL ) {
+    p = pthread_getspecific( *pkey );
   }
 
   #ifdef DEBUG_GXX_WRAPPERS
     printk(
       "gxx_wrappers: getspecific key=%x, ptr=%x, id=%x\n",
-       key,
+       pkey,
        p,
        rtems_task_self()
     );
@@ -134,25 +118,33 @@ void *rtems_gxx_getspecific(__gthread_key_t key)
 
 int rtems_gxx_setspecific(__gthread_key_t key, const void *ptr)
 {
-  rtems_status_code status;
+  pthread_key_t *pkey = key;
+  int eno;
+
+  if ( pkey == NULL ) {
+    return EINVAL;
+  }
+
+  eno = pthread_setspecific( *pkey, ptr );
 
   #ifdef DEBUG_GXX_WRAPPERS
     printk(
       "gxx_wrappers: setspecific key=%x, ptr=%x, id=%x\n",
-      key,
+      pkey,
       ptr,
       rtems_task_self()
       );
   #endif
 
-  /* register with RTEMS the buffer that will hold the key values */
-  status = rtems_task_variable_add( RTEMS_SELF, (void **)key, key->dtor );
-  if ( status == RTEMS_SUCCESSFUL ) {
-    /* now let's set the proper value */
-    key->val =  (void *)ptr;
-    return 0;
+  if ( eno != 0 ) {
+    _Terminate(
+      INTERNAL_ERROR_CORE,
+      true,
+      INTERNAL_ERROR_GXX_KEY_ADD_FAILED
+    );
   }
-  return -1;
+
+  return 0;
 }
 
 
diff --git a/testsuites/libtests/gxx01/gxx01.scn b/testsuites/libtests/gxx01/gxx01.scn
index cb9f6b5..f831881 100644
--- a/testsuites/libtests/gxx01/gxx01.scn
+++ b/testsuites/libtests/gxx01/gxx01.scn
@@ -22,10 +22,14 @@ Call once method the second time
 rtems_gxx_key_create(&key, NULL) - OK
 rtems_gxx_key_delete(key) - OK
 rtems_gxx_key_create(&key, key_dtor) - OK
-rtems_gxx_setspecific() - OK
+rtems_gxx_getspecific(key) not set - OK
+rtems_gxx_setspecific(key, 0x1234) - OK
 rtems_gxx_getspecific(key) already existing - OK
 rtems_gxx_key_delete(key) - OK
 rtems_gxx_getspecific(key) non-existent - OK
-rtems_gxx_key_delete(key) - OK
+rtems_gxx_key_delete(key) - NOT OK
+rtems_gxx_setspecific(NULL, 0x1234) - NOT OK
+rtems_gxx_getspecific(NULL) - OK
+rtems_gxx_key_delete(NULL) - NOT OK
 
 *** END OF TEST GXX 01 ***
diff --git a/testsuites/libtests/gxx01/init.c b/testsuites/libtests/gxx01/init.c
index f925284..a0debcd 100644
--- a/testsuites/libtests/gxx01/init.c
+++ b/testsuites/libtests/gxx01/init.c
@@ -11,6 +11,7 @@
 #include "config.h"
 #endif
 
+#include <errno.h>
 #include <tmacros.h>
 #include "test_support.h"
 #include <rtems/gxx_wrappers.h>
@@ -142,7 +143,11 @@ void test_key(void)
   sc = rtems_gxx_key_create(&key, key_dtor);
   rtems_test_assert( sc == 0 );
 
-  puts( "rtems_gxx_setspecific() - OK" );
+  puts( "rtems_gxx_getspecific(key) not set - OK" );
+  p = rtems_gxx_getspecific(key);
+  rtems_test_assert( p == NULL );
+
+  puts( "rtems_gxx_setspecific(key, 0x1234) - OK" );
   sc = rtems_gxx_setspecific(key, (void *)0x1234);
   rtems_test_assert( sc == 0 );
 
@@ -153,7 +158,8 @@ void test_key(void)
   puts( "rtems_gxx_key_delete(key) - OK" );
   sc = rtems_gxx_key_delete(key);
   rtems_test_assert( sc == 0 );
-  rtems_test_assert( key_dtor_ran == true );
+  /* pthread_key man-page: the dtor should _not_ be called */
+  rtems_test_assert( key_dtor_ran != true );
 
   key = calloc( 1, sizeof( *key ) );
   rtems_test_assert( key != NULL );
@@ -162,9 +168,21 @@ void test_key(void)
   p = rtems_gxx_getspecific( key );
   rtems_test_assert( p == NULL );
 
-  puts( "rtems_gxx_key_delete(key) - OK" );
+  puts( "rtems_gxx_key_delete(key) - NOT OK" );
   sc = rtems_gxx_key_delete( key );
-  rtems_test_assert( sc == 0 );
+  rtems_test_assert( sc != 0 );
+
+  puts( "rtems_gxx_setspecific(NULL, 0x1234) - NOT OK" );
+  sc = rtems_gxx_setspecific( NULL, (void *)0x1234 );
+  rtems_test_assert( sc == EINVAL );
+
+  puts( "rtems_gxx_getspecific(NULL) - OK" );
+  p = rtems_gxx_getspecific( NULL );
+  rtems_test_assert( p == NULL );
+
+  puts( "rtems_gxx_key_delete(NULL) - NOT OK" );
+  sc = rtems_gxx_key_delete( NULL );
+  rtems_test_assert( sc == EINVAL );
 }
 
 rtems_task Init(
@@ -195,6 +213,9 @@ rtems_task Init(
 #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
 
+#define CONFIGURE_MAXIMUM_POSIX_KEYS            1
+#define CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS 1
+
 #define CONFIGURE_MAXIMUM_TASKS        1
 #define CONFIGURE_MAXIMUM_SEMAPHORES   2
 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
diff --git a/testsuites/sptests/spfatal24/spfatal24.doc b/testsuites/sptests/spfatal24/spfatal24.doc
index e30241b..b697770 100644
--- a/testsuites/sptests/spfatal24/spfatal24.doc
+++ b/testsuites/sptests/spfatal24/spfatal24.doc
@@ -12,7 +12,7 @@ test set name:  spfatal24
 
 directives:
 
-  rtems_gxx_getspecific();
+  rtems_gxx_setspecific();
 
 concepts:
 
diff --git a/testsuites/sptests/spfatal24/testcase.h b/testsuites/sptests/spfatal24/testcase.h
index 73ecf85..87cbe53 100644
--- a/testsuites/sptests/spfatal24/testcase.h
+++ b/testsuites/sptests/spfatal24/testcase.h
@@ -18,9 +18,7 @@
 
 void force_error()
 {
-  __gthread_key key;
+  pthread_key_t key = -1;
 
-  rtems_workspace_greedy_allocate( NULL, 0 );
-
-  rtems_gxx_getspecific( &key );
+  rtems_gxx_setspecific( &key, NULL );
 }
diff --git a/testsuites/sptests/sptls02/init.cc b/testsuites/sptests/sptls02/init.cc
index 603e228..5902a77 100644
--- a/testsuites/sptests/sptls02/init.cc
+++ b/testsuites/sptests/sptls02/init.cc
@@ -251,6 +251,9 @@ extern "C" void Init(rtems_task_argument arg)
 
 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
 
+#define CONFIGURE_MAXIMUM_POSIX_KEYS 2
+#define CONFIGURE_MAXIMUM_POSIX_KEY_VALUE_PAIRS 2
+
 #define CONFIGURE_INIT
 
 #include <rtems/confdefs.h>




More information about the vc mailing list