Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : *
3 : * Copyright (C) 2005 Liam Widdowson
4 : * Copyright (C) 2010-2012 Frediano Ziglio
5 : *
6 : * This library is free software; you can redistribute it and/or
7 : * modify it under the terms of the GNU Library General Public
8 : * License as published by the Free Software Foundation; either
9 : * version 2 of the License, or (at your option) any later version.
10 : *
11 : * This library is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * Library General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Library General Public
17 : * License along with this library; if not, write to the
18 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 : * Boston, MA 02111-1307, USA.
20 : */
21 :
22 : #ifndef _tdsguard_cIfZP7JZiHtLLfanwl7ubP_
23 : #define _tdsguard_cIfZP7JZiHtLLfanwl7ubP_
24 :
25 : #undef TDS_HAVE_MUTEX
26 :
27 : #if defined(_THREAD_SAFE) && defined(TDS_HAVE_PTHREAD_MUTEX)
28 :
29 : #include <tds_sysdep_public.h>
30 : #include <freetds/sysdep_private.h>
31 : #include <pthread.h>
32 : #include <errno.h>
33 :
34 : #include <freetds/pushvis.h>
35 :
36 : typedef pthread_mutex_t tds_raw_mutex;
37 : #define TDS_RAW_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
38 :
39 : static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
40 : {
41 754345 : pthread_mutex_lock(mtx);
42 : }
43 :
44 : static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
45 : {
46 679277 : return pthread_mutex_trylock(mtx);
47 : }
48 :
49 : static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
50 : {
51 1326565 : pthread_mutex_unlock(mtx);
52 : }
53 :
54 : static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
55 : {
56 108971 : return pthread_mutex_init(mtx, NULL);
57 : }
58 :
59 : static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
60 : {
61 104254 : pthread_mutex_destroy(mtx);
62 : }
63 :
64 : typedef pthread_cond_t tds_condition;
65 :
66 : int tds_raw_cond_init(tds_condition *cond);
67 : static inline int tds_raw_cond_destroy(tds_condition *cond)
68 : {
69 2350 : return pthread_cond_destroy(cond);
70 : }
71 : static inline int tds_raw_cond_signal(tds_condition *cond)
72 : {
73 49391 : return pthread_cond_signal(cond);
74 : }
75 : static inline int tds_raw_cond_wait(tds_condition *cond, tds_raw_mutex *mtx)
76 : {
77 30 : return pthread_cond_wait(cond, mtx);
78 : }
79 : int tds_raw_cond_timedwait(tds_condition *cond, tds_raw_mutex *mtx, int timeout_sec);
80 :
81 : #define TDS_HAVE_MUTEX 1
82 :
83 : typedef pthread_t tds_thread;
84 : typedef pthread_t tds_thread_id;
85 : typedef void *(*tds_thread_proc)(void *arg);
86 : #define TDS_THREAD_PROC_DECLARE(name, arg) \
87 : void *name(void *arg)
88 : #define TDS_THREAD_RESULT(n) ((void*)(TDS_INTPTR)(n))
89 :
90 : static inline int tds_thread_create(tds_thread *ret, tds_thread_proc proc, void *arg)
91 : {
92 379 : return pthread_create(ret, NULL, proc, arg);
93 : }
94 :
95 1454 : static inline int tds_thread_create_detached(tds_thread_proc proc, void *arg)
96 : {
97 : tds_thread th;
98 1454 : int ret = pthread_create(&th, NULL, proc, arg);
99 1454 : if (!ret)
100 1454 : pthread_detach(th);
101 1454 : return ret;
102 : }
103 :
104 : static inline int tds_thread_join(tds_thread th, void **ret)
105 : {
106 379 : return pthread_join(th, ret);
107 : }
108 :
109 : static inline tds_thread_id tds_thread_get_current_id(void)
110 : {
111 1329619 : return pthread_self();
112 : }
113 :
114 : static inline int tds_thread_is_current(tds_thread_id th)
115 : {
116 112690 : return pthread_equal(th, pthread_self());
117 : }
118 :
119 : #include <freetds/popvis.h>
120 :
121 : #elif defined(_WIN32)
122 :
123 : #include <freetds/windows.h>
124 : #include <errno.h>
125 :
126 : /* old version of Windows do not define this constant */
127 : #ifndef ETIMEDOUT
128 : #define ETIMEDOUT 138
129 : #endif
130 :
131 : typedef struct
132 : {
133 : SRWLOCK srwlock;
134 : } tds_raw_mutex;
135 :
136 : #define TDS_RAW_MUTEX_INITIALIZER { SRWLOCK_INIT }
137 :
138 : extern int (*tds_raw_mutex_init)(tds_raw_mutex * mtx);
139 : extern void (*tds_raw_mutex_free)(tds_raw_mutex * mtx);
140 : extern void (*tds_raw_mutex_lock)(tds_raw_mutex * mtx);
141 : extern void (*tds_raw_mutex_unlock)(tds_raw_mutex * mtx);
142 : extern int (*tds_raw_mutex_trylock)(tds_raw_mutex * mtx);
143 :
144 : #define TDS_HAVE_MUTEX 1
145 :
146 : /* easy way, only single signal supported */
147 : typedef void *TDS_CONDITION_VARIABLE;
148 : typedef union {
149 : HANDLE ev;
150 : TDS_CONDITION_VARIABLE cv;
151 : } tds_condition;
152 :
153 : extern int (*tds_raw_cond_init)(tds_condition *cond);
154 : extern int (*tds_raw_cond_destroy)(tds_condition *cond);
155 : extern int (*tds_raw_cond_signal)(tds_condition *cond);
156 : extern int (*tds_raw_cond_timedwait)(tds_condition *cond, tds_raw_mutex *mtx, int timeout_sec);
157 : static inline int tds_raw_cond_wait(tds_condition *cond, tds_raw_mutex *mtx)
158 : {
159 : return tds_raw_cond_timedwait(cond, mtx, -1);
160 : }
161 :
162 : typedef HANDLE tds_thread;
163 : typedef DWORD tds_thread_id;
164 : typedef DWORD (WINAPI *tds_thread_proc)(void *arg);
165 : #define TDS_THREAD_PROC_DECLARE(name, arg) \
166 : DWORD WINAPI name(void *arg)
167 : #define TDS_THREAD_RESULT(n) ((DWORD)(int)(n))
168 :
169 : static inline int tds_thread_create(tds_thread *ret, tds_thread_proc proc, void *arg)
170 : {
171 : *ret = CreateThread(NULL, 0, proc, arg, 0, NULL);
172 : return *ret != NULL ? 0 : 11 /* EAGAIN */;
173 : }
174 :
175 : static inline int tds_thread_create_detached(tds_thread_proc proc, void *arg)
176 : {
177 : HANDLE h = CreateThread(NULL, 0, proc, arg, 0, NULL);
178 : if (!h)
179 : return 11 /* EAGAIN */;
180 :
181 : /* Avoids leaking the handle - Thread continues to run */
182 : CloseHandle(h);
183 : return 0;
184 : }
185 :
186 : static inline int tds_thread_join(tds_thread th, void **ret)
187 : {
188 : if (WaitForSingleObject(th, INFINITE) == WAIT_OBJECT_0) {
189 : if (ret) {
190 : DWORD r;
191 : if (!GetExitCodeThread(th, &r))
192 : r = 0xffffffffu;
193 : *ret = (void*) (((char*)0) + r);
194 : }
195 :
196 : CloseHandle(th);
197 : return 0;
198 : }
199 : CloseHandle(th);
200 : return 22 /* EINVAL */;
201 : }
202 :
203 : static inline tds_thread_id tds_thread_get_current_id(void)
204 : {
205 : return GetCurrentThreadId();
206 : }
207 :
208 : static inline int tds_thread_is_current(tds_thread_id th)
209 : {
210 : return th == GetCurrentThreadId();
211 : }
212 :
213 : #else
214 :
215 : #include <tds_sysdep_public.h>
216 :
217 : /* define noops as "successful" */
218 : typedef struct {
219 : char dummy[0]; /* compiler compatibility */
220 : } tds_raw_mutex;
221 :
222 : #define TDS_RAW_MUTEX_INITIALIZER {}
223 :
224 : static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
225 : {
226 : }
227 :
228 : static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
229 : {
230 : return 0;
231 : }
232 :
233 : static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
234 : {
235 : }
236 :
237 : static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
238 : {
239 : return 0;
240 : }
241 :
242 : static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
243 : {
244 : }
245 :
246 : typedef struct {
247 : char dummy[0]; /* compiler compatibility */
248 : } tds_condition;
249 :
250 : static inline int tds_raw_cond_init(tds_condition *cond)
251 : {
252 : return 0;
253 : }
254 : static inline int tds_raw_cond_destroy(tds_condition *cond)
255 : {
256 : return 0;
257 : }
258 : #define tds_raw_cond_signal(cond) \
259 : FreeTDS_Condition_not_compiled
260 :
261 : #define tds_raw_cond_wait(cond, mtx) \
262 : FreeTDS_Condition_not_compiled
263 :
264 : #define tds_raw_cond_timedwait(cond, mtx, timeout_sec) \
265 : FreeTDS_Condition_not_compiled
266 :
267 : typedef struct {
268 : char dummy[0]; /* compiler compatibility */
269 : } tds_thread;
270 : typedef int tds_thread_id;
271 :
272 : typedef void *(*tds_thread_proc)(void *arg);
273 : #define TDS_THREAD_PROC_DECLARE(name, arg) \
274 : void *name(void *arg)
275 : #define TDS_THREAD_RESULT(n) ((void*)(TDS_INTPTR)(n))
276 :
277 : #define tds_thread_create(ret, proc, arg) \
278 : FreeTDS_Thread_not_compiled
279 :
280 : #define tds_thread_create_detached(proc, arg) \
281 : FreeTDS_Thread_not_compiled
282 :
283 : #define tds_thread_join(th, ret) \
284 : FreeTDS_Thread_not_compiled
285 :
286 : static inline tds_thread_id tds_thread_get_current_id(void)
287 : {
288 : return 0;
289 : }
290 :
291 : static inline int tds_thread_is_current(tds_thread_id th)
292 : {
293 : return 1;
294 : }
295 :
296 : #endif
297 :
298 : # define tds_cond_init tds_raw_cond_init
299 : # define tds_cond_destroy tds_raw_cond_destroy
300 : # define tds_cond_signal tds_raw_cond_signal
301 : # if !ENABLE_EXTRA_CHECKS || !defined(TDS_HAVE_MUTEX)
302 : # define TDS_MUTEX_INITIALIZER TDS_RAW_MUTEX_INITIALIZER
303 : # define tds_mutex tds_raw_mutex
304 : # define tds_mutex_lock tds_raw_mutex_lock
305 : # define tds_mutex_trylock tds_raw_mutex_trylock
306 : # define tds_mutex_unlock tds_raw_mutex_unlock
307 : # define tds_mutex_check_owned(mtx) do {} while(0)
308 : # define tds_mutex_init tds_raw_mutex_init
309 : # define tds_mutex_free tds_raw_mutex_free
310 : # define tds_cond_wait tds_raw_cond_wait
311 : # define tds_cond_timedwait tds_raw_cond_timedwait
312 : # else
313 : # include <assert.h>
314 :
315 : typedef struct tds_mutex
316 : {
317 : tds_raw_mutex mtx;
318 : volatile int locked;
319 : volatile tds_thread_id locked_by;
320 : } tds_mutex;
321 :
322 : # define TDS_MUTEX_INITIALIZER { TDS_RAW_MUTEX_INITIALIZER, 0 }
323 :
324 754345 : static inline void tds_mutex_lock(tds_mutex *mtx)
325 : {
326 754345 : assert(mtx);
327 1508690 : tds_raw_mutex_lock(&mtx->mtx);
328 754345 : assert(!mtx->locked);
329 754345 : mtx->locked = 1;
330 754345 : mtx->locked_by = tds_thread_get_current_id();
331 754345 : }
332 :
333 572511 : static inline int tds_mutex_trylock(tds_mutex *mtx)
334 : {
335 : int ret;
336 572511 : assert(mtx);
337 1145022 : ret = tds_raw_mutex_trylock(&mtx->mtx);
338 572511 : if (!ret) {
339 572220 : assert(!mtx->locked);
340 572220 : mtx->locked = 1;
341 572220 : mtx->locked_by = tds_thread_get_current_id();
342 : }
343 572511 : return ret;
344 : }
345 :
346 1326565 : static inline void tds_mutex_unlock(tds_mutex *mtx)
347 : {
348 1326565 : assert(mtx && mtx->locked);
349 1326565 : mtx->locked = 0;
350 2653130 : tds_raw_mutex_unlock(&mtx->mtx);
351 1326565 : }
352 :
353 106766 : static inline void tds_mutex_check_owned(tds_mutex *mtx)
354 : {
355 : int ret;
356 106766 : assert(mtx);
357 213532 : ret = tds_raw_mutex_trylock(&mtx->mtx);
358 106766 : assert(ret);
359 106766 : assert(mtx->locked);
360 213532 : assert(tds_thread_is_current(mtx->locked_by));
361 106766 : }
362 :
363 : static inline int tds_mutex_init(tds_mutex *mtx)
364 : {
365 108971 : mtx->locked = 0;
366 217942 : return tds_raw_mutex_init(&mtx->mtx);
367 : }
368 :
369 104254 : static inline void tds_mutex_free(tds_mutex *mtx)
370 : {
371 104254 : assert(mtx && !mtx->locked);
372 208508 : tds_raw_mutex_free(&mtx->mtx);
373 104254 : }
374 :
375 10 : static inline int tds_cond_wait(tds_condition *cond, tds_mutex *mtx)
376 : {
377 : int ret;
378 10 : assert(mtx && mtx->locked);
379 10 : mtx->locked = 0;
380 20 : ret = tds_raw_cond_wait(cond, &mtx->mtx);
381 10 : mtx->locked = 1;
382 10 : mtx->locked_by = tds_thread_get_current_id();
383 10 : return ret;
384 : }
385 :
386 40 : static inline int tds_cond_timedwait(tds_condition *cond, tds_mutex *mtx, int timeout_sec)
387 : {
388 : int ret;
389 40 : assert(mtx && mtx->locked);
390 40 : mtx->locked = 0;
391 40 : ret = tds_raw_cond_timedwait(cond, &mtx->mtx, timeout_sec);
392 40 : mtx->locked = 1;
393 40 : mtx->locked_by = tds_thread_get_current_id();
394 40 : return ret;
395 : }
396 :
397 : # endif
398 :
399 : #endif
|