*** gxx_wrappers.c.orig	2003-01-29 14:57:18.000000000 -0800
--- gxx_wrappers.c	2004-10-14 14:10:12.000000000 -0700
***************
*** 36,45 ****
   * These typedefs should match with the ones defined in the file
   * gcc/gthr-rtems.h in the gcc distribution.
   */
- typedef void *__gthread_key_t;
  typedef int   __gthread_once_t;
  typedef void *__gthread_mutex_t;
  
  
  /* uncomment this if you need to debug this interface */
  
--- 36,49 ----
   * These typedefs should match with the ones defined in the file
   * gcc/gthr-rtems.h in the gcc distribution.
   */
  typedef int   __gthread_once_t;
  typedef void *__gthread_mutex_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;
+ 
  
  /* uncomment this if you need to debug this interface */
  
***************
*** 66,78 ****
     if( *(volatile __gthread_once_t *)once == 0 )
     {
        rtems_mode saveMode;
        rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &saveMode);
!       if( *(volatile __gthread_once_t *)once == 0 )
        {
           *(volatile __gthread_once_t *)once = 1;
-          (*func)();
        }
        rtems_task_mode(saveMode, RTEMS_PREEMPT_MASK, &saveMode);
     }
     return 0;
  }
--- 70,84 ----
     if( *(volatile __gthread_once_t *)once == 0 )
     {
        rtems_mode saveMode;
+       __gthread_once_t o;
        rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &saveMode);
!       if( (o = *(volatile __gthread_once_t *)once) == 0 )
        {
           *(volatile __gthread_once_t *)once = 1;
        }
        rtems_task_mode(saveMode, RTEMS_PREEMPT_MASK, &saveMode);
+       if ( o == 0 )
+          (*func)();
     }
     return 0;
  }
***************
*** 86,100 ****
     * 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( __gthread_key_t ) );
!   *key = ( __gthread_key_t )new_key;
!   *new_key = NULL;
  
  #ifdef DEBUG_GXX_WRAPPERS
    printk( "gxx_wrappers: create key=%x, dtor=%x, new_key=%x\n", key, dtor, new_key );
  #endif
    /* register with RTEMS the buffer that will hold the key values */
!   if( rtems_task_variable_add( RTEMS_SELF, (void **)new_key, NULL ) == RTEMS_SUCCESSFUL )
         return 0;
    return -1;
  }
--- 92,107 ----
     * 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( *__gthread_key_t ) );
!   *key = new_key;
!   new_key->val  = NULL;
!   new_key->dtor = dtor;
  
  #ifdef DEBUG_GXX_WRAPPERS
    printk( "gxx_wrappers: create key=%x, dtor=%x, new_key=%x\n", key, dtor, new_key );
  #endif
    /* register with RTEMS the buffer that will hold the key values */
!   if( rtems_task_variable_add( RTEMS_SELF, (void **)new_key, dtor ) == RTEMS_SUCCESSFUL )
         return 0;
    return -1;
  }
***************
*** 104,110 ****
  #ifdef DEBUG_GXX_WRAPPERS
    printk( "gxx_wrappers: dtor key=%x, ptr=%x\n", key, ptr );
  #endif
!    *(void **)key = 0;
     return 0;
  }
  
--- 111,117 ----
  #ifdef DEBUG_GXX_WRAPPERS
    printk( "gxx_wrappers: dtor key=%x, ptr=%x\n", key, ptr );
  #endif
!    key->val  = 0;
     return 0;
  }
  
***************
*** 116,121 ****
--- 123,129 ----
    /* register with RTEMS the buffer that will hold the key values */
    if( rtems_task_variable_delete( RTEMS_SELF, (void **)key ) == RTEMS_SUCCESSFUL )
    {
+      /* Hmm - hopefully all tasks using this key have gone away... */
       if( key ) free( (void *)key );
       return 0;
    }
***************
*** 131,148 ****
    if( rtems_task_variable_get( RTEMS_SELF, (void **)key, &p ) == RTEMS_SUCCESSFUL )
    {
      /* We do not have to do this, but what the heck ! */
!      p= *( void **)key;
    }
    else
    {
      /* fisrt time, always set to zero, it is unknown the value that the others
       * threads are using at the moment of this call
       */
!     if( rtems_task_variable_add( RTEMS_SELF, (void **)key, NULL ) != RTEMS_SUCCESSFUL )
      {
         rtems_panic ("rtems_gxx_getspecific");
      }
!     *( void ** )key = (void *)0;
    }
  
  #ifdef DEBUG_GXX_WRAPPERS
--- 139,156 ----
    if( rtems_task_variable_get( RTEMS_SELF, (void **)key, &p ) == 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
       */
!     if( rtems_task_variable_add( RTEMS_SELF, (void **)key, key->dtor ) != RTEMS_SUCCESSFUL )
      {
         rtems_panic ("rtems_gxx_getspecific");
      }
!     key->val = (void *)0;
    }
  
  #ifdef DEBUG_GXX_WRAPPERS
***************
*** 158,167 ****
    printk( "gxx_wrappers: setspecific key=%x, ptr=%x, id=%x\n", key, ptr, get_tid() );
  #endif
    /* register with RTEMS the buffer that will hold the key values */
!   if( rtems_task_variable_add( RTEMS_SELF, (void **)key, NULL ) == RTEMS_SUCCESSFUL )
    {
      /* now let's set the proper value */
!     *( void ** )key = (void *)ptr;
       return 0;
    }
    return -1;
--- 166,175 ----
    printk( "gxx_wrappers: setspecific key=%x, ptr=%x, id=%x\n", key, ptr, get_tid() );
  #endif
    /* register with RTEMS the buffer that will hold the key values */
!   if( rtems_task_variable_add( RTEMS_SELF, (void **)key, key->dtor ) == RTEMS_SUCCESSFUL )
    {
      /* now let's set the proper value */
!     key->val =  (void *)ptr;
       return 0;
    }
    return -1;
