1 /**************************************************************************
2  *
3  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, TX., USA
4  * All Rights Reserved.
5  * Copyright 2009 VMware, Inc., Palo Alto, CA., USA
6  * All Rights Reserved.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the
10  * "Software"), to deal in the Software without restriction, including
11  * without limitation the rights to use, copy, modify, merge, publish,
12  * distribute, sub license, and/or sell copies of the Software, and to
13  * permit persons to whom the Software is furnished to do so, subject to
14  * the following conditions:
15  *
16  * The above copyright notice and this permission notice (including the
17  * next paragraph) shall be included in all copies or substantial portions
18  * of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
23  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
24  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
25  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
26  * USE OR OTHER DEALINGS IN THE SOFTWARE.
27  *
28  **************************************************************************/
29 /*
30  * Authors:
31  * Thomas Hellstr�m <thomas-at-tungstengraphics-dot-com>
32  */
33 
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
37 
38 #include <stdlib.h>
39 #include <stddef.h>
40 #include <errno.h>
41 #include "wsbm_driver.h"
42 
43 struct _WsbmThreadFuncs *wsbmCurThreadFunc = NULL;
44 struct _WsbmVNodeFuncs *wsbmCurVNodeFunc = NULL;
45 
46 /*
47  * Single-threaded implementation.
48  */
49 
50 static int
n_mutexInit(struct _WsbmMutex * mutex,struct _WsbmThreadFuncs * func)51 n_mutexInit(struct _WsbmMutex *mutex, struct _WsbmThreadFuncs *func)
52 {
53     mutex->func = func;
54     return 0;
55 }
56 
57 static int
n_condInit(struct _WsbmCond * cond,struct _WsbmThreadFuncs * func)58 n_condInit(struct _WsbmCond *cond, struct _WsbmThreadFuncs *func)
59 {
60     cond->func = func;
61     return 0;
62 }
63 
64 static void
n_mutexNone(struct _WsbmMutex * mutex)65 n_mutexNone(struct _WsbmMutex *mutex __attribute__ ((unused)))
66 {
67     ;
68 }
69 
70 static void
n_condNone(struct _WsbmCond * cond)71 n_condNone(struct _WsbmCond *cond __attribute__ ((unused)))
72 {
73     ;
74 }
75 
76 static void
n_condWait(struct _WsbmCond * cond,struct _WsbmMutex * mutex)77 n_condWait(struct _WsbmCond *cond __attribute__ ((unused)), struct _WsbmMutex *mutex __attribute__ ((unused)))
78 {
79     ;
80 }
81 
82 static struct _WsbmThreadFuncs nullFunc = {
83     .mutexInit = n_mutexInit,
84     .mutexFree = n_mutexNone,
85     .mutexLock = n_mutexNone,
86     .mutexUnlock = n_mutexNone,
87     .condInit = n_condInit,
88     .condFree = n_condNone,
89     .condWait = n_condWait,
90     .condBroadcast = n_condNone
91 };
92 
93 struct _WsbmThreadFuncs *
wsbmNullThreadFuncs(void)94 wsbmNullThreadFuncs(void)
95 {
96     return &nullFunc;
97 }
98 
99 #if (HAVE_PTHREADS == 1)
100 #include "pthread.h"
101 
102 /*
103  * pthreads implementation:
104  */
105 
106 struct _WsbmPMutex
107 {
108     struct _WsbmThreadFuncs *func;
109     pthread_mutex_t mutex;
110 };
111 
112 struct _WsbmPCond
113 {
114     struct _WsbmThreadFuncs *func;
115     pthread_cond_t cond;
116 };
117 
118 static inline struct _WsbmPMutex *
pMutexConvert(struct _WsbmMutex * m)119 pMutexConvert(struct _WsbmMutex *m)
120 {
121     union _PMutexConverter
122     {
123 	struct _WsbmMutex wm;
124 	struct _WsbmPMutex pm;
125     }  *um = containerOf(m, union _PMutexConverter, wm);
126 
127     return &um->pm;
128 }
129 
130 static inline struct _WsbmPCond *
pCondConvert(struct _WsbmCond * c)131 pCondConvert(struct _WsbmCond *c)
132 {
133     union _PCondConverter
134     {
135 	struct _WsbmCond wc;
136 	struct _WsbmPCond pc;
137     }  *uc = containerOf(c, union _PCondConverter, wc);
138 
139     return &uc->pc;
140 }
141 
142 static int
p_mutexInit(struct _WsbmMutex * mutex,struct _WsbmThreadFuncs * func)143 p_mutexInit(struct _WsbmMutex *mutex, struct _WsbmThreadFuncs *func)
144 {
145     struct _WsbmPMutex *pMutex = pMutexConvert(mutex);
146 
147     if (sizeof(struct _WsbmMutex) < sizeof(struct _WsbmPMutex))
148 	return -EINVAL;
149 
150     pMutex->func = func;
151     pthread_mutex_init(&pMutex->mutex, NULL);
152     return 0;
153 }
154 
155 static void
p_mutexFree(struct _WsbmMutex * mutex)156 p_mutexFree(struct _WsbmMutex *mutex)
157 {
158     struct _WsbmPMutex *pMutex = pMutexConvert(mutex);
159 
160     pthread_mutex_destroy(&pMutex->mutex);
161 }
162 
163 static void
p_mutexLock(struct _WsbmMutex * mutex)164 p_mutexLock(struct _WsbmMutex *mutex)
165 {
166     struct _WsbmPMutex *pMutex = pMutexConvert(mutex);
167 
168     pthread_mutex_lock(&pMutex->mutex);
169 }
170 
171 static void
p_mutexUnlock(struct _WsbmMutex * mutex)172 p_mutexUnlock(struct _WsbmMutex *mutex)
173 {
174     struct _WsbmPMutex *pMutex = pMutexConvert(mutex);
175 
176     pthread_mutex_unlock(&pMutex->mutex);
177 }
178 
179 static int
p_condInit(struct _WsbmCond * cond,struct _WsbmThreadFuncs * func)180 p_condInit(struct _WsbmCond *cond, struct _WsbmThreadFuncs *func)
181 {
182     struct _WsbmPCond *pCond = pCondConvert(cond);
183 
184     if (sizeof(struct _WsbmCond) < sizeof(struct _WsbmPCond))
185 	return -EINVAL;
186 
187     pCond->func = func;
188     pthread_cond_init(&pCond->cond, NULL);
189     return 0;
190 }
191 
192 static void
p_condFree(struct _WsbmCond * cond)193 p_condFree(struct _WsbmCond *cond)
194 {
195     struct _WsbmPCond *pCond = pCondConvert(cond);
196 
197     pthread_cond_destroy(&pCond->cond);
198 }
199 
200 static void
p_condBroadcast(struct _WsbmCond * cond)201 p_condBroadcast(struct _WsbmCond *cond)
202 {
203     struct _WsbmPCond *pCond = pCondConvert(cond);
204 
205     pthread_cond_broadcast(&pCond->cond);
206 }
207 
208 static void
p_condWait(struct _WsbmCond * cond,struct _WsbmMutex * mutex)209 p_condWait(struct _WsbmCond *cond, struct _WsbmMutex *mutex)
210 {
211     struct _WsbmPCond *pCond = pCondConvert(cond);
212     struct _WsbmPMutex *pMutex = pMutexConvert(mutex);
213 
214     pthread_cond_wait(&pCond->cond, &pMutex->mutex);
215 }
216 
217 static struct _WsbmThreadFuncs pthreadFunc = {
218     .mutexInit = p_mutexInit,
219     .mutexFree = p_mutexFree,
220     .mutexLock = p_mutexLock,
221     .mutexUnlock = p_mutexUnlock,
222     .condInit = p_condInit,
223     .condFree = p_condFree,
224     .condWait = p_condWait,
225     .condBroadcast = p_condBroadcast
226 };
227 
228 struct _WsbmThreadFuncs *
wsbmPThreadFuncs(void)229 wsbmPThreadFuncs(void)
230 {
231     return &pthreadFunc;
232 }
233 
234 #else
235 #warning Pthreads is not present. Compiling without.
236 
237 struct _WsbmThreadFuncs *
wsbmPThreadFuncs(void)238 wsbmPThreadFuncs(void)
239 {
240     return &pthreadFunc;
241 }
242 
243 #endif
244