Subversion Repositories shark

Rev

Rev 55 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
55 pj 1
/* $Id: glthread.c,v 1.1 2003-02-28 11:42:02 pj Exp $ */
2
 
3
/*
4
 * Mesa 3-D graphics library
5
 * Version:  4.1
6
 *
7
 * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a
10
 * copy of this software and associated documentation files (the "Software"),
11
 * to deal in the Software without restriction, including without limitation
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
 * and/or sell copies of the Software, and to permit persons to whom the
14
 * Software is furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included
17
 * in all copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 */
26
 
27
 
28
/*
29
 * XXX There's probably some work to do in order to make this file
30
 * truly reusable outside of Mesa.  First, the glheader.h include must go.
31
 */
32
 
33
 
34
#include "glheader.h"
35
#include "glthread.h"
36
 
37
 
38
/*
39
 * This file should still compile even when THREADS is not defined.
40
 * This is to make things easier to deal with on the makefile scene..
41
 */
42
#ifdef THREADS
43
#include <errno.h>
44
 
45
/*
46
 * Error messages
47
 */
48
#define INIT_TSD_ERROR "_glthread_: failed to allocate key for thread specific data"
49
#define GET_TSD_ERROR "_glthread_: failed to get thread specific data"
50
#define SET_TSD_ERROR "_glthread_: thread failed to set thread specific data"
51
 
52
 
53
/*
54
 * Magic number to determine if a TSD object has been initialized.
55
 * Kind of a hack but there doesn't appear to be a better cross-platform
56
 * solution.
57
 */
58
#define INIT_MAGIC 0xff8adc98
59
 
60
 
61
 
62
/*
63
 * POSIX Threads -- The best way to go if your platform supports them.
64
 *                  Solaris >= 2.5 have POSIX threads, IRIX >= 6.4 reportedly
65
 *                  has them, and many of the free Unixes now have them.
66
 *                  Be sure to use appropriate -mt or -D_REENTRANT type
67
 *                  compile flags when building.
68
 */
69
#ifdef PTHREADS
70
 
71
unsigned long
72
_glthread_GetID(void)
73
{
74
   return (unsigned long) pthread_self();
75
}
76
 
77
 
78
void
79
_glthread_InitTSD(_glthread_TSD *tsd)
80
{
81
   if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) {
82
      perror(INIT_TSD_ERROR);
83
      exit(-1);
84
   }
85
   tsd->initMagic = INIT_MAGIC;
86
}
87
 
88
 
89
void *
90
_glthread_GetTSD(_glthread_TSD *tsd)
91
{
92
   if (tsd->initMagic != (int) INIT_MAGIC) {
93
      _glthread_InitTSD(tsd);
94
   }
95
   return pthread_getspecific(tsd->key);
96
}
97
 
98
 
99
void
100
_glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
101
{
102
   if (tsd->initMagic != (int) INIT_MAGIC) {
103
      _glthread_InitTSD(tsd);
104
   }
105
   if (pthread_setspecific(tsd->key, ptr) != 0) {
106
      perror(SET_TSD_ERROR);
107
      exit(-1);
108
   }
109
}
110
 
111
#endif /* PTHREADS */
112
 
113
 
114
 
115
/*
116
 * Solaris/Unix International Threads -- Use only if POSIX threads
117
 *   aren't available on your Unix platform.  Solaris 2.[34] are examples
118
 *   of platforms where this is the case.  Be sure to use -mt and/or
119
 *   -D_REENTRANT when compiling.
120
 */
121
#ifdef SOLARIS_THREADS
122
#define USE_LOCK_FOR_KEY        /* undef this to try a version without
123
                                   lock for the global key... */
124
 
125
unsigned long
126
_glthread_GetID(void)
127
{
128
   abort();   /* XXX not implemented yet */
129
   return (unsigned long) 0;
130
}
131
 
132
 
133
void
134
_glthread_InitTSD(_glthread_TSD *tsd)
135
{
136
   if ((errno = mutex_init(&tsd->keylock, 0, NULL)) != 0 ||
137
      (errno = thr_keycreate(&(tsd->key), free)) != 0) {
138
      perror(INIT_TSD_ERROR);
139
      exit(-1);
140
   }
141
   tsd->initMagic = INIT_MAGIC;
142
}
143
 
144
 
145
void *
146
_glthread_GetTSD(_glthread_TSD *tsd)
147
{
148
   void* ret;
149
   if (tsd->initMagic != INIT_MAGIC) {
150
      _glthread_InitTSD(tsd);
151
   }
152
#ifdef USE_LOCK_FOR_KEY
153
   mutex_lock(&tsd->keylock);
154
   thr_getspecific(tsd->key, &ret);
155
   mutex_unlock(&tsd->keylock);
156
#else
157
   if ((errno = thr_getspecific(tsd->key, &ret)) != 0) {
158
      perror(GET_TSD_ERROR);
159
      exit(-1);
160
   }
161
#endif
162
   return ret;
163
}
164
 
165
 
166
void
167
_glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
168
{
169
   if (tsd->initMagic != INIT_MAGIC) {
170
      _glthread_InitTSD(tsd);
171
   }
172
   if ((errno = thr_setspecific(tsd->key, ptr)) != 0) {
173
      perror(SET_TSD_ERROR);
174
      exit(-1);
175
   }
176
}
177
 
178
#undef USE_LOCK_FOR_KEY
179
#endif /* SOLARIS_THREADS */
180
 
181
 
182
 
183
/*
184
 * Win32 Threads.  The only available option for Windows 95/NT.
185
 * Be sure that you compile using the Multithreaded runtime, otherwise
186
 * bad things will happen.
187
 */
188
#ifdef WIN32_THREADS
189
 
190
unsigned long
191
_glthread_GetID(void)
192
{
193
   abort();   /* XXX not implemented yet */
194
   return (unsigned long) 0;
195
}
196
 
197
 
198
void
199
_glthread_InitTSD(_glthread_TSD *tsd)
200
{
201
   tsd->key = TlsAlloc();
202
   if (tsd->key == 0xffffffff) {
203
      /* Can Windows handle stderr messages for non-console
204
         applications? Does Windows have perror? */
205
      /* perror(SET_INIT_ERROR);*/
206
      exit(-1);
207
   }
208
   tsd->initMagic = INIT_MAGIC;
209
}
210
 
211
 
212
void *
213
_glthread_GetTSD(_glthread_TSD *tsd)
214
{
215
   if (tsd->initMagic != INIT_MAGIC) {
216
      _glthread_InitTSD(tsd);
217
   }
218
   return TlsGetValue(tsd->key);
219
}
220
 
221
 
222
void
223
_glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
224
{
225
   /* the following code assumes that the _glthread_TSD has been initialized
226
      to zero at creation */
227
   if (tsd->initMagic != INIT_MAGIC) {
228
      _glthread_InitTSD(tsd);
229
   }
230
   if (TlsSetValue(tsd->key, ptr) == 0) {
231
      /* Can Windows handle stderr messages for non-console
232
         applications? Does Windows have perror? */
233
      /* perror(SET_TSD_ERROR);*/
234
      exit(-1);
235
   }
236
}
237
 
238
#endif /* WIN32_THREADS */
239
 
240
 
241
 
242
/*
243
 * XFree86 has its own thread wrapper, Xthreads.h
244
 * We wrap it again for GL.
245
 */
246
#ifdef XTHREADS
247
 
248
unsigned long
249
_glthread_GetID(void)
250
{
251
   return (unsigned long) xthread_self();
252
}
253
 
254
 
255
void
256
_glthread_InitTSD(_glthread_TSD *tsd)
257
{
258
   if (xthread_key_create(&tsd->key, NULL) != 0) {
259
      perror(INIT_TSD_ERROR);
260
      exit(-1);
261
   }
262
   tsd->initMagic = INIT_MAGIC;
263
}
264
 
265
 
266
void *
267
_glthread_GetTSD(_glthread_TSD *tsd)
268
{
269
   void *ptr;
270
   if (tsd->initMagic != INIT_MAGIC) {
271
      _glthread_InitTSD(tsd);
272
   }
273
   xthread_get_specific(tsd->key, &ptr);
274
   return ptr;
275
}
276
 
277
 
278
void
279
_glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
280
{
281
   if (tsd->initMagic != INIT_MAGIC) {
282
      _glthread_InitTSD(tsd);
283
   }
284
   xthread_set_specific(tsd->key, ptr);
285
}
286
 
287
#endif /* XTHREAD */
288
 
289
 
290
 
291
/*
292
 * BeOS threads
293
 */
294
#ifdef BEOS_THREADS
295
 
296
unsigned long
297
_glthread_GetID(void)
298
{
299
   return (unsigned long) find_thread(NULL);
300
}
301
 
302
void
303
_glthread_InitTSD(_glthread_TSD *tsd)
304
{
305
   tsd->key = tls_allocate();
306
   tsd->initMagic = INIT_MAGIC;
307
}
308
 
309
void *
310
_glthread_GetTSD(_glthread_TSD *tsd)
311
{
312
   if (tsd->initMagic != (int) INIT_MAGIC) {
313
      _glthread_InitTSD(tsd);
314
   }
315
   return tls_get(tsd->key);
316
}
317
 
318
void
319
_glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
320
{
321
   if (tsd->initMagic != (int) INIT_MAGIC) {
322
      _glthread_InitTSD(tsd);
323
   }
324
   tls_set(tsd->key, ptr);
325
}
326
 
327
#endif /* BEOS_THREADS */
328
 
329
 
330
 
331
#else  /* THREADS */
332
 
333
 
334
/*
335
 * no-op functions
336
 */
337
 
338
unsigned long
339
_glthread_GetID(void)
340
{
341
   return 0;
342
}
343
 
344
 
345
void
346
_glthread_InitTSD(_glthread_TSD *tsd)
347
{
348
   (void) tsd;
349
}
350
 
351
 
352
void *
353
_glthread_GetTSD(_glthread_TSD *tsd)
354
{
355
   (void) tsd;
356
   return NULL;
357
}
358
 
359
 
360
void
361
_glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
362
{
363
   (void) tsd;
364
   (void) ptr;
365
}
366
 
367
 
368
#endif /* THREADS */