e7cc8d8d4892b9d698d7b2f6f9afc74e6d58430f
[mesa.git] / src / mesa / glapi / glthread.c
1 /* $Id: glthread.c,v 1.3 2000/01/28 18:57:56 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 *
7 * Copyright (C) 1999-2000 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 * Thread support for gl dispatch.
30 *
31 * Initial version by John Stone (j.stone@acm.org) (johns@cs.umr.edu)
32 * and Christoph Poliwoda (poliwoda@volumegraphics.com)
33 *
34 * Revised by Keith Whitwell
35 * Adapted for new gl dispatcher by Brian Paul
36 *
37 * XXX There's probably some work to do in order to make this file
38 * truly reusable outside of Mesa. First, the glheader.h include must go.
39 */
40
41
42 #ifdef PC_ALL
43 #include "all.h"
44 #else
45 #include "glheader.h"
46 #endif
47
48
49
50 /*
51 * This file should still compile even when THREADS is not defined.
52 * This is to make things easier to deal with on the makefile scene..
53 */
54 #ifdef THREADS
55 #include <errno.h>
56 #include "glthread.h"
57
58
59 /*
60 * Error messages
61 */
62 #define INIT_TSD_ERROR "_glthread_: failed to allocate key for thread specific data"
63 #define GET_TSD_ERROR "_glthread_: failed to get thread specific data"
64 #define SET_TSD_ERROR "_glthread_: thread failed to set thread specific data"
65
66
67 /*
68 * magic number for win32 and solaris threads equivalents of pthread_once
69 * This could probably be done better, but we haven't figured out how yet.
70 */
71 #define INITFUNC_CALLED_MAGIC 0xff8adc98
72
73
74
75 /*
76 * POSIX Threads -- The best way to go if your platform supports them.
77 * Solaris >= 2.5 have POSIX threads, IRIX >= 6.4 reportedly
78 * has them, and many of the free Unixes now have them.
79 * Be sure to use appropriate -mt or -D_REENTRANT type
80 * compile flags when building.
81 */
82 #ifdef PTHREADS
83
84 unsigned long
85 _glthread_GetID(void)
86 {
87 return (unsigned long) pthread_self();
88 }
89
90
91 void
92 _glthread_InitTSD(_glthread_TSD *tsd)
93 {
94 if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) {
95 perror(INIT_TSD_ERROR);
96 exit(-1);
97 }
98 }
99
100
101 void *
102 _glthread_GetTSD(_glthread_TSD *tsd)
103 {
104 return pthread_getspecific(tsd->key);
105 }
106
107
108 void
109 _glthread_SetTSD(_glthread_TSD *tsd, void *ptr, void (*initfunc)(void))
110 {
111 pthread_once(&tsd->once, initfunc);
112 if (pthread_setspecific(tsd->key, ptr) != 0) {
113 perror(SET_TSD_ERROR);
114 exit(-1);
115 }
116 }
117
118 #endif /* PTHREADS */
119
120
121
122 /*
123 * Solaris/Unix International Threads -- Use only if POSIX threads
124 * aren't available on your Unix platform. Solaris 2.[34] are examples
125 * of platforms where this is the case. Be sure to use -mt and/or
126 * -D_REENTRANT when compiling.
127 */
128 #ifdef SOLARIS_THREADS
129 #define USE_LOCK_FOR_KEY /* undef this to try a version without
130 lock for the global key... */
131
132 unsigned long
133 _glthread_GetID(void)
134 {
135 abort(); /* XXX not implemented yet */
136 return (unsigned long) 0;
137 }
138
139
140 void
141 _glthread_InitTSD(_glthread_TSD *tsd)
142 {
143 if ((errno = mutex_init(&tsd->keylock, 0, NULL)) != 0 ||
144 (errno = thr_keycreate(&(tsd->key), free)) != 0) {
145 perror(INIT_TSD_ERROR);
146 exit(-1);
147 }
148 }
149
150
151 void *
152 _glthread_GetTSD(_glthread_TSD *tsd)
153 {
154 void* ret;
155 #ifdef USE_LOCK_FOR_KEY
156 mutex_lock(&tsd->keylock);
157 thr_getspecific(tsd->key, &ret);
158 mutex_unlock(&tsd->keylock);
159 #else
160 if ((errno = thr_getspecific(tsd->key, &ret)) != 0) {
161 perror(GET_TSD_ERROR);
162 exit(-1);
163 }
164 #endif
165 return ret;
166 }
167
168
169 void
170 _glthread_SetTSD(_glthread_TSD *tsd, void *ptr, void (*initfunc)(void))
171 {
172 /* the following code assumes that the _glthread_TSD has been initialized
173 to zero at creation */
174 fprintf(stderr, "initfuncCalled = %d\n", tsd->initfuncCalled);
175 if (tsd->initfuncCalled != INITFUNC_CALLED_MAGIC) {
176 initfunc();
177 tsd->initfuncCalled = INITFUNC_CALLED_MAGIC;
178 }
179 if ((errno = thr_setspecific(tsd->key, ptr)) != 0) {
180 perror(SET_TSD_ERROR);
181 exit(-1);
182 }
183 }
184
185 #undef USE_LOCK_FOR_KEY
186 #endif /* SOLARIS_THREADS */
187
188
189
190 /*
191 * Win32 Threads. The only available option for Windows 95/NT.
192 * Be sure that you compile using the Multithreaded runtime, otherwise
193 * bad things will happen.
194 */
195 #ifdef WIN32
196
197 unsigned long
198 _glthread_GetID(void)
199 {
200 abort(); /* XXX not implemented yet */
201 return (unsigned long) 0;
202 }
203
204
205 void
206 _glthread_InitTSD(_glthread_TSD *tsd)
207 {
208 tsd->key = TlsAlloc();
209 if (tsd->key == 0xffffffff) {
210 /* Can Windows handle stderr messages for non-console
211 applications? Does Windows have perror? */
212 /* perror(SET_INIT_ERROR);*/
213 exit(-1);
214 }
215 }
216
217
218 void *
219 _glthread_GetTSD(_glthread_TSD *tsd)
220 {
221 return TlsGetValue(tsd->key);
222 }
223
224
225 void
226 _glthread_SetTSD(_glthread_TSD *tsd, void *ptr, void (*initfunc)(void))
227 {
228 /* the following code assumes that the _glthread_TSD has been initialized
229 to zero at creation */
230 if (tsd->initfuncCalled != INITFUNC_CALLED_MAGIC) {
231 initfunc();
232 tsd->initfuncCalled = INITFUNC_CALLED_MAGIC;
233 }
234 if (TlsSetValue(tsd->key, ptr) == 0) {
235 /* Can Windows handle stderr messages for non-console
236 applications? Does Windows have perror? */
237 /* perror(SET_TSD_ERROR);*/
238 exit(-1);
239 }
240 }
241
242 #endif /* WIN32 */
243
244 #endif /* THREADS */
245
246