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
43struct _WsbmThreadFuncs *wsbmCurThreadFunc = NULL;
44struct _WsbmVNodeFuncs *wsbmCurVNodeFunc = NULL;
45
46/*
47 * Single-threaded implementation.
48 */
49
50static int
51n_mutexInit(struct _WsbmMutex *mutex, struct _WsbmThreadFuncs *func)
52{
53    mutex->func = func;
54    return 0;
55}
56
57static int
58n_condInit(struct _WsbmCond *cond, struct _WsbmThreadFuncs *func)
59{
60    cond->func = func;
61    return 0;
62}
63
64static void
65n_mutexNone(struct _WsbmMutex *mutex __attribute__ ((unused)))
66{
67    ;
68}
69
70static void
71n_condNone(struct _WsbmCond *cond __attribute__ ((unused)))
72{
73    ;
74}
75
76static void
77n_condWait(struct _WsbmCond *cond __attribute__ ((unused)), struct _WsbmMutex *mutex __attribute__ ((unused)))
78{
79    ;
80}
81
82static 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
93struct _WsbmThreadFuncs *
94wsbmNullThreadFuncs(void)
95{
96    return &nullFunc;
97}
98
99#if (HAVE_PTHREADS == 1)
100#include "pthread.h"
101
102/*
103 * pthreads implementation:
104 */
105
106struct _WsbmPMutex
107{
108    struct _WsbmThreadFuncs *func;
109    pthread_mutex_t mutex;
110};
111
112struct _WsbmPCond
113{
114    struct _WsbmThreadFuncs *func;
115    pthread_cond_t cond;
116};
117
118static inline struct _WsbmPMutex *
119pMutexConvert(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
130static inline struct _WsbmPCond *
131pCondConvert(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
142static int
143p_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
155static void
156p_mutexFree(struct _WsbmMutex *mutex)
157{
158    struct _WsbmPMutex *pMutex = pMutexConvert(mutex);
159
160    pthread_mutex_destroy(&pMutex->mutex);
161}
162
163static void
164p_mutexLock(struct _WsbmMutex *mutex)
165{
166    struct _WsbmPMutex *pMutex = pMutexConvert(mutex);
167
168    pthread_mutex_lock(&pMutex->mutex);
169}
170
171static void
172p_mutexUnlock(struct _WsbmMutex *mutex)
173{
174    struct _WsbmPMutex *pMutex = pMutexConvert(mutex);
175
176    pthread_mutex_unlock(&pMutex->mutex);
177}
178
179static int
180p_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
192static void
193p_condFree(struct _WsbmCond *cond)
194{
195    struct _WsbmPCond *pCond = pCondConvert(cond);
196
197    pthread_cond_destroy(&pCond->cond);
198}
199
200static void
201p_condBroadcast(struct _WsbmCond *cond)
202{
203    struct _WsbmPCond *pCond = pCondConvert(cond);
204
205    pthread_cond_broadcast(&pCond->cond);
206}
207
208static void
209p_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
217static 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
228struct _WsbmThreadFuncs *
229wsbmPThreadFuncs(void)
230{
231    return &pthreadFunc;
232}
233
234#else
235#warning Pthreads is not present. Compiling without.
236
237struct _WsbmThreadFuncs *
238wsbmPThreadFuncs(void)
239{
240    return &pthreadFunc;
241}
242
243#endif
244