OSDN Git Service

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