source: rtems/cpukit/libcsupport/src/gxx_wrappers.c @ 4a2fee47

Last change on this file since 4a2fee47 was 4a2fee47, checked in by Till Straumann <strauman@…>, on Feb 6, 2007 at 10:54:34 PM

2007-02-06 Till Straumann <strauman@…>

  • libcsupport/src/gxx_wrappers.c: fix PR#690. Supply taskvar dtor to plug memory leak. Applied patch attached to PR#690.
  • Property mode set to 100644
File size: 6.7 KB
Line 
1/*
2 * RTEMS threads compatibily routines for libgcc2.
3 *
4 * by: Rosimildo da Silva ( rdasilva@connecttel.com
5 *
6 * Used ideas from:
7 *    W. Eric Norum
8 *    Canadian Light Source
9 *    University of Saskatchewan
10 *    Saskatoon, Saskatchewan, CANADA
11 *    eric@cls.usask.ca
12 *
13 * Eric sent some e-mail in the rtems-list as a start point for this
14 * module implementation.
15 *
16 * $Id$
17 */
18
19/*
20 * This file is only used if using gcc
21 */
22#if defined(__GNUC__)
23
24#if HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28/* We might not need, defined just in case */
29#define  __RTEMS_INSIDE__  1
30
31
32#include <stdlib.h>
33#include <stdio.h>
34
35#include <rtems.h>
36#include <rtems/system.h>
37#include <rtems/error.h>        /* rtems_panic */
38#include <rtems/rtems/tasks.h>
39
40/*
41 * These typedefs should match with the ones defined in the file
42 * gcc/gthr-rtems.h in the gcc distribution.
43 * FIXME: T.S, 2007/01/31: -> gcc/gthr-rtems.h still declares
44 *                            void * __gthread_key_t;
45 */
46typedef struct __gthread_key_ {
47        void *val;                 /* this is switched with the task      */
48        void (*dtor)(void*);   /* this remains in place for all tasks */
49} __gthread_key, *__gthread_key_t;
50typedef int   __gthread_once_t;
51typedef void *__gthread_mutex_t;
52typedef void *__gthread_recursive_mutex_t;
53
54/* uncomment this if you need to debug this interface */
55
56/*
57#define DEBUG_GXX_WRAPPERS 1
58*/
59
60#ifdef DEBUG_GXX_WRAPPERS
61/* local function to return the ID of the calling thread */
62static rtems_id get_tid( void )
63{
64   rtems_id id = 0;
65   rtems_task_ident( RTEMS_SELF, 0, &id );
66   return id;
67}
68#endif
69
70
71int rtems_gxx_once(__gthread_once_t *once, void (*func) (void))
72{
73#ifdef DEBUG_GXX_WRAPPERS
74   printk( "gxx_wrappers: once=%x, func=%x\n", *once, func );
75#endif
76   if( *(volatile __gthread_once_t *)once == 0 )
77   {
78      rtems_mode saveMode;
79      __gthread_once_t o;
80      rtems_task_mode(RTEMS_NO_PREEMPT, RTEMS_PREEMPT_MASK, &saveMode);
81      if( (o = *(volatile __gthread_once_t *)once) == 0 )
82      {
83         *(volatile __gthread_once_t *)once = 1;
84      }
85      rtems_task_mode(saveMode, RTEMS_PREEMPT_MASK, &saveMode);
86      if ( o == 0 )
87         (*func)();
88   }
89   return 0;
90}
91
92
93int rtems_gxx_key_create (__gthread_key_t *key, void (*dtor) (void *))
94{
95  /* Ok, this can be a bit tricky. We are going to return a "key" as a
96   * pointer to the buffer that will hold the value of the key itself.
97   * We have to to this, because the others functions on this interface
98   * deal with the value of the key, as used with the POSIX API.
99   */
100   /* Do not pull your hair, trust me this works. :-) */
101  __gthread_key_t new_key = ( __gthread_key_t )malloc( sizeof( *new_key ) );
102  *key = new_key;
103  new_key->val  = NULL;
104  new_key->dtor = dtor;
105
106#ifdef DEBUG_GXX_WRAPPERS
107  printk( "gxx_wrappers: create key=%x, dtor=%x, new_key=%x\n", key, dtor, new_key );
108#endif
109  /* register with RTEMS the buffer that will hold the key values */
110  if( rtems_task_variable_add( RTEMS_SELF, (void **)new_key, dtor ) == RTEMS_SUCCESSFUL )
111       return 0;
112  return -1;
113}
114
115int rtems_gxx_key_dtor (__gthread_key_t key, void *ptr)
116{
117#ifdef DEBUG_GXX_WRAPPERS
118  printk( "gxx_wrappers: dtor key=%x, ptr=%x\n", key, ptr );
119#endif
120   key->val  = 0;
121   return 0;
122}
123
124int rtems_gxx_key_delete (__gthread_key_t key)
125{
126#ifdef DEBUG_GXX_WRAPPERS
127  printk( "gxx_wrappers: delete key=%x\n", key );
128#endif
129  /* register with RTEMS the buffer that will hold the key values */
130  if( rtems_task_variable_delete( RTEMS_SELF, (void **)key ) == RTEMS_SUCCESSFUL )
131  {
132     /* Hmm - hopefully all tasks using this key have gone away... */
133     if( key ) free( (void *)key );
134     return 0;
135  }
136  return 0;
137}
138
139
140void *rtems_gxx_getspecific(__gthread_key_t key)
141{
142  void *p= 0;
143
144  /* register with RTEMS the buffer that will hold the key values */
145  if( rtems_task_variable_get( RTEMS_SELF, (void **)key, &p ) == RTEMS_SUCCESSFUL )
146  {
147    /* We do not have to do this, but what the heck ! */
148     p= key->val;
149  }
150  else
151  {
152    /* fisrt time, always set to zero, it is unknown the value that the others
153     * threads are using at the moment of this call
154     */
155    if( rtems_task_variable_add( RTEMS_SELF, (void **)key, key->dtor ) != RTEMS_SUCCESSFUL )
156    {
157       rtems_panic ("rtems_gxx_getspecific");
158    }
159    key->val = (void *)0;
160  }
161
162#ifdef DEBUG_GXX_WRAPPERS
163   printk( "gxx_wrappers: getspecific key=%x, ptr=%x, id=%x\n", key, p, get_tid() );
164#endif
165   return p;
166}
167
168
169int rtems_gxx_setspecific(__gthread_key_t key, const void *ptr)
170{
171#ifdef DEBUG_GXX_WRAPPERS
172  printk( "gxx_wrappers: setspecific key=%x, ptr=%x, id=%x\n", key, ptr, get_tid() );
173#endif
174  /* register with RTEMS the buffer that will hold the key values */
175  if( rtems_task_variable_add( RTEMS_SELF, (void **)key, key->dtor ) == RTEMS_SUCCESSFUL )
176  {
177    /* now let's set the proper value */
178    key->val =  (void *)ptr;
179     return 0;
180  }
181  return -1;
182}
183
184
185/*
186 * MUTEX support
187 */
188void rtems_gxx_mutex_init (__gthread_mutex_t *mutex)
189{
190#ifdef DEBUG_GXX_WRAPPERS
191  printk( "gxx_wrappers: mutex init =%X\n", *mutex );
192#endif
193  if( rtems_semaphore_create( rtems_build_name ('G', 'C', 'C', '2'),
194                              1,
195                             RTEMS_PRIORITY|RTEMS_BINARY_SEMAPHORE
196                             |RTEMS_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING|RTEMS_LOCAL,
197                             0,
198                             (rtems_id *)mutex ) != RTEMS_SUCCESSFUL )
199  {
200      rtems_panic ("rtems_gxx_mutex_init");
201  }
202#ifdef DEBUG_GXX_WRAPPERS
203  printk( "gxx_wrappers: mutex init complete =%X\n", *mutex );
204#endif
205}
206
207int rtems_gxx_mutex_lock (__gthread_mutex_t *mutex)
208{
209#ifdef DEBUG_GXX_WRAPPERS
210  printk( "gxx_wrappers: lock mutex=%X\n", *mutex );
211#endif
212  return ( rtems_semaphore_obtain( (rtems_id)*mutex,
213            RTEMS_WAIT, RTEMS_NO_TIMEOUT ) ==  RTEMS_SUCCESSFUL) ? 0 : -1;
214}
215
216int rtems_gxx_mutex_trylock (__gthread_mutex_t *mutex)
217{
218#ifdef DEBUG_GXX_WRAPPERS
219  printk( "gxx_wrappers: trylock mutex=%X\n", *mutex );
220#endif
221  return (rtems_semaphore_obtain ((rtems_id)*mutex,
222               RTEMS_NO_WAIT, 0) == RTEMS_SUCCESSFUL) ? 0 : -1;
223}
224
225int rtems_gxx_mutex_unlock (__gthread_mutex_t *mutex)
226{
227#ifdef DEBUG_GXX_WRAPPERS
228   printk( "gxx_wrappers: unlock mutex=%X\n", *mutex );
229#endif
230  return (rtems_semaphore_release( (rtems_id)*mutex ) ==  RTEMS_SUCCESSFUL) ? 0 :-1;
231}
232
233void rtems_gxx_recursive_mutex_init(__gthread_recursive_mutex_t *mutex)
234{
235  rtems_gxx_mutex_init(mutex);
236}
237
238int rtems_gxx_recursive_mutex_lock(__gthread_recursive_mutex_t *mutex)
239{
240  return rtems_gxx_mutex_lock(mutex);
241}
242
243int rtems_gxx_recursive_mutex_trylock(__gthread_recursive_mutex_t *mutex)
244{
245  return rtems_gxx_mutex_trylock(mutex);
246}
247
248int rtems_gxx_recursive_mutex_unlock(__gthread_recursive_mutex_t *mutex)
249{
250  return rtems_gxx_mutex_unlock(mutex);
251}
252
253#endif /* __GNUC__ */
Note: See TracBrowser for help on using the repository browser.