blob: e7cc8d8d4892b9d698d7b2f6f9afc74e6d58430f [file] [log] [blame]
Brian Paul8d365ab2000-01-28 18:57:56 +00001/* $Id: glthread.c,v 1.3 2000/01/28 18:57:56 brianp Exp $ */
Brian Paulc11371a1999-12-16 17:31:06 +00002
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 *
Brian Paul8d365ab2000-01-28 18:57:56 +00007 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
Brian Paulc11371a1999-12-16 17:31:06 +00008 *
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
Brian Paul8d365ab2000-01-28 18:57:56 +000036 *
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.
Brian Paulc11371a1999-12-16 17:31:06 +000039 */
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
84unsigned long
85_glthread_GetID(void)
86{
87 return (unsigned long) pthread_self();
88}
89
90
91void
92_glthread_InitTSD(_glthread_TSD *tsd)
93{
Brian Paule2b10e71999-12-17 11:13:54 +000094 if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) {
Brian Paulc11371a1999-12-16 17:31:06 +000095 perror(INIT_TSD_ERROR);
96 exit(-1);
97 }
98}
99
100
101void *
102_glthread_GetTSD(_glthread_TSD *tsd)
103{
104 return pthread_getspecific(tsd->key);
105}
106
107
108void
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);
Brian Paule2b10e71999-12-17 11:13:54 +0000115 }
Brian Paulc11371a1999-12-16 17:31:06 +0000116}
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
132unsigned long
133_glthread_GetID(void)
134{
135 abort(); /* XXX not implemented yet */
136 return (unsigned long) 0;
137}
138
139
140void
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
151void *
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);
Brian Paule2b10e71999-12-17 11:13:54 +0000163 }
Brian Paulc11371a1999-12-16 17:31:06 +0000164#endif
165 return ret;
166}
167
168
169void
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);
Brian Paule2b10e71999-12-17 11:13:54 +0000182 }
Brian Paulc11371a1999-12-16 17:31:06 +0000183}
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
197unsigned long
198_glthread_GetID(void)
199{
200 abort(); /* XXX not implemented yet */
201 return (unsigned long) 0;
202}
203
204
205void
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
218void *
219_glthread_GetTSD(_glthread_TSD *tsd)
220{
221 return TlsGetValue(tsd->key);
222}
223
224
225void
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);
Brian Paule2b10e71999-12-17 11:13:54 +0000239 }
Brian Paulc11371a1999-12-16 17:31:06 +0000240}
241
242#endif /* WIN32 */
243
244#endif /* THREADS */
245
246