Merge branch '7.8'
[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 #include "glapi/mesa.h"
34 #else
35 #include "main/compiler.h"
36 #endif
37
38 #include "glapi/glthread.h"
39
40
41 /*
42 * This file should still compile even when THREADS is not defined.
43 * This is to make things easier to deal with on the makefile scene..
44 */
45 #ifdef THREADS
46 #include <errno.h>
47
48 /*
49 * Error messages
50 */
51 #define INIT_TSD_ERROR "_glthread_: failed to allocate key for thread specific data"
52 #define GET_TSD_ERROR "_glthread_: failed to get thread specific data"
53 #define SET_TSD_ERROR "_glthread_: thread failed to set thread specific data"
54
55
56 /*
57 * Magic number to determine if a TSD object has been initialized.
58 * Kind of a hack but there doesn't appear to be a better cross-platform
59 * solution.
60 */
61 #define INIT_MAGIC 0xff8adc98
62
63
64
65 /*
66 * POSIX Threads -- The best way to go if your platform supports them.
67 * Solaris >= 2.5 have POSIX threads, IRIX >= 6.4 reportedly
68 * has them, and many of the free Unixes now have them.
69 * Be sure to use appropriate -mt or -D_REENTRANT type
70 * compile flags when building.
71 */
72 #ifdef PTHREADS
73
74 PUBLIC unsigned long
75 _glthread_GetID(void)
76 {
77 return (unsigned long) pthread_self();
78 }
79
80
81 void
82 _glthread_InitTSD(_glthread_TSD *tsd)
83 {
84 if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) {
85 perror(INIT_TSD_ERROR);
86 exit(-1);
87 }
88 tsd->initMagic = INIT_MAGIC;
89 }
90
91
92 void *
93 _glthread_GetTSD(_glthread_TSD *tsd)
94 {
95 if (tsd->initMagic != (int) INIT_MAGIC) {
96 _glthread_InitTSD(tsd);
97 }
98 return pthread_getspecific(tsd->key);
99 }
100
101
102 void
103 _glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
104 {
105 if (tsd->initMagic != (int) INIT_MAGIC) {
106 _glthread_InitTSD(tsd);
107 }
108 if (pthread_setspecific(tsd->key, ptr) != 0) {
109 perror(SET_TSD_ERROR);
110 exit(-1);
111 }
112 }
113
114 #endif /* PTHREADS */
115
116
117
118 /*
119 * Win32 Threads. The only available option for Windows 95/NT.
120 * Be sure that you compile using the Multithreaded runtime, otherwise
121 * bad things will happen.
122 */
123 #ifdef WIN32_THREADS
124
125 static void InsteadOf_exit(int nCode)
126 {
127 DWORD dwErr = GetLastError();
128 }
129
130 PUBLIC unsigned long
131 _glthread_GetID(void)
132 {
133 return GetCurrentThreadId();
134 }
135
136
137 void
138 _glthread_InitTSD(_glthread_TSD *tsd)
139 {
140 tsd->key = TlsAlloc();
141 if (tsd->key == TLS_OUT_OF_INDEXES) {
142 perror(INIT_TSD_ERROR);
143 InsteadOf_exit(-1);
144 }
145 tsd->initMagic = INIT_MAGIC;
146 }
147
148
149 void
150 _glthread_DestroyTSD(_glthread_TSD *tsd)
151 {
152 if (tsd->initMagic != INIT_MAGIC) {
153 return;
154 }
155 TlsFree(tsd->key);
156 tsd->initMagic = 0x0;
157 }
158
159
160 void *
161 _glthread_GetTSD(_glthread_TSD *tsd)
162 {
163 if (tsd->initMagic != INIT_MAGIC) {
164 _glthread_InitTSD(tsd);
165 }
166 return TlsGetValue(tsd->key);
167 }
168
169
170 void
171 _glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
172 {
173 /* the following code assumes that the _glthread_TSD has been initialized
174 to zero at creation */
175 if (tsd->initMagic != INIT_MAGIC) {
176 _glthread_InitTSD(tsd);
177 }
178 if (TlsSetValue(tsd->key, ptr) == 0) {
179 perror(SET_TSD_ERROR);
180 InsteadOf_exit(-1);
181 }
182 }
183
184 #endif /* WIN32_THREADS */
185
186 /*
187 * BeOS threads
188 */
189 #ifdef BEOS_THREADS
190
191 PUBLIC unsigned long
192 _glthread_GetID(void)
193 {
194 return (unsigned long) find_thread(NULL);
195 }
196
197 void
198 _glthread_InitTSD(_glthread_TSD *tsd)
199 {
200 tsd->key = tls_allocate();
201 tsd->initMagic = INIT_MAGIC;
202 }
203
204 void *
205 _glthread_GetTSD(_glthread_TSD *tsd)
206 {
207 if (tsd->initMagic != (int) INIT_MAGIC) {
208 _glthread_InitTSD(tsd);
209 }
210 return tls_get(tsd->key);
211 }
212
213 void
214 _glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
215 {
216 if (tsd->initMagic != (int) INIT_MAGIC) {
217 _glthread_InitTSD(tsd);
218 }
219 tls_set(tsd->key, ptr);
220 }
221
222 #endif /* BEOS_THREADS */
223
224
225
226 #else /* THREADS */
227
228
229 /*
230 * no-op functions
231 */
232
233 PUBLIC unsigned long
234 _glthread_GetID(void)
235 {
236 return 0;
237 }
238
239
240 void
241 _glthread_InitTSD(_glthread_TSD *tsd)
242 {
243 (void) tsd;
244 }
245
246
247 void *
248 _glthread_GetTSD(_glthread_TSD *tsd)
249 {
250 (void) tsd;
251 return NULL;
252 }
253
254
255 void
256 _glthread_SetTSD(_glthread_TSD *tsd, void *ptr)
257 {
258 (void) tsd;
259 (void) ptr;
260 }
261
262
263 #endif /* THREADS */