forked from Imagelibrary/rtems
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.
This commit is contained in:
committed by
Sebastian Huber
parent
9d9df8b44e
commit
5ef9f23fb4
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
int eno;
|
||||
pthread_key_t *pkey;
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
pthread_key_t *pkey = key;
|
||||
void *p = NULL;
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 ***
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -12,7 +12,7 @@ test set name: spfatal24
|
||||
|
||||
directives:
|
||||
|
||||
rtems_gxx_getspecific();
|
||||
rtems_gxx_setspecific();
|
||||
|
||||
concepts:
|
||||
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user