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 751195 : pthread_mutex_lock(mtx);
42 : }
43 :
44 : static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
45 : {
46 676239 : return pthread_mutex_trylock(mtx);
47 : }
48 :
49 : static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
50 : {
51 1320889 : pthread_mutex_unlock(mtx);
52 : }
53 :
54 : static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
55 : {
56 108595 : return pthread_mutex_init(mtx, NULL);
57 : }
58 :
59 : static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
60 : {
61 103891 : 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 2343 : return pthread_cond_destroy(cond);
70 : }
71 : static inline int tds_raw_cond_signal(tds_condition *cond)
72 : {
73 49059 : 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 1450 : static inline int tds_thread_create_detached(tds_thread_proc proc, void *arg)
96 : {
97 : tds_thread th;
98 1450 : int ret = pthread_create(&th, NULL, proc, arg);
99 1450 : if (!ret)
100 1450 : pthread_detach(th);
101 1450 : 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 1323943 : return pthread_self();
112 : }
113 :
114 : static inline int tds_thread_is_current(tds_thread_id th)
115 : {
116 112212 : 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 : struct ptw32_mcs_node_t_;
132 :
133 : typedef struct {
134 : struct ptw32_mcs_node_t_ *lock;
135 : LONG done;
136 : DWORD thread_id;
137 : CRITICAL_SECTION crit;
138 : } tds_raw_mutex;
139 :
140 : #define TDS_RAW_MUTEX_INITIALIZER { NULL, 0, 0 }
141 :
142 : static inline int
143 : tds_raw_mutex_init(tds_raw_mutex *mtx)
144 : {
145 : mtx->lock = NULL;
146 : mtx->done = 0;
147 : mtx->thread_id = 0;
148 : return 0;
149 : }
150 :
151 : void tds_win_mutex_lock(tds_raw_mutex *mutex);
152 :
153 : static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
154 : {
155 : if (mtx->done) {
156 : EnterCriticalSection(&mtx->crit);
157 : mtx->thread_id = GetCurrentThreadId();
158 : } else {
159 : tds_win_mutex_lock(mtx);
160 : }
161 : }
162 :
163 : int tds_raw_mutex_trylock(tds_raw_mutex *mtx);
164 :
165 : static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
166 : {
167 : mtx->thread_id = 0;
168 : LeaveCriticalSection(&mtx->crit);
169 : }
170 :
171 : static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
172 : {
173 : if (mtx->done) {
174 : DeleteCriticalSection(&mtx->crit);
175 : mtx->done = 0;
176 : }
177 : }
178 :
179 : #define TDS_HAVE_MUTEX 1
180 :
181 : /* easy way, only single signal supported */
182 : typedef void *TDS_CONDITION_VARIABLE;
183 : typedef union {
184 : HANDLE ev;
185 : TDS_CONDITION_VARIABLE cv;
186 : } tds_condition;
187 :
188 : extern int (*tds_raw_cond_init)(tds_condition *cond);
189 : extern int (*tds_raw_cond_destroy)(tds_condition *cond);
190 : extern int (*tds_raw_cond_signal)(tds_condition *cond);
191 : extern int (*tds_raw_cond_timedwait)(tds_condition *cond, tds_raw_mutex *mtx, int timeout_sec);
192 : static inline int tds_raw_cond_wait(tds_condition *cond, tds_raw_mutex *mtx)
193 : {
194 : return tds_raw_cond_timedwait(cond, mtx, -1);
195 : }
196 :
197 : typedef HANDLE tds_thread;
198 : typedef DWORD tds_thread_id;
199 : typedef DWORD (WINAPI *tds_thread_proc)(void *arg);
200 : #define TDS_THREAD_PROC_DECLARE(name, arg) \
201 : DWORD WINAPI name(void *arg)
202 : #define TDS_THREAD_RESULT(n) ((DWORD)(int)(n))
203 :
204 : static inline int tds_thread_create(tds_thread *ret, tds_thread_proc proc, void *arg)
205 : {
206 : *ret = CreateThread(NULL, 0, proc, arg, 0, NULL);
207 : return *ret != NULL ? 0 : 11 /* EAGAIN */;
208 : }
209 :
210 : static inline int tds_thread_create_detached(tds_thread_proc proc, void *arg)
211 : {
212 : HANDLE h = CreateThread(NULL, 0, proc, arg, 0, NULL);
213 : if (!h)
214 : return 11 /* EAGAIN */;
215 :
216 : /* Avoids leaking the handle - Thread continues to run */
217 : CloseHandle(h);
218 : return 0;
219 : }
220 :
221 : static inline int tds_thread_join(tds_thread th, void **ret)
222 : {
223 : if (WaitForSingleObject(th, INFINITE) == WAIT_OBJECT_0) {
224 : if (ret) {
225 : DWORD r;
226 : if (!GetExitCodeThread(th, &r))
227 : r = 0xffffffffu;
228 : *ret = (void*) (((char*)0) + r);
229 : }
230 :
231 : CloseHandle(th);
232 : return 0;
233 : }
234 : CloseHandle(th);
235 : return 22 /* EINVAL */;
236 : }
237 :
238 : static inline tds_thread_id tds_thread_get_current_id(void)
239 : {
240 : return GetCurrentThreadId();
241 : }
242 :
243 : static inline int tds_thread_is_current(tds_thread_id th)
244 : {
245 : return th == GetCurrentThreadId();
246 : }
247 :
248 : #else
249 :
250 : #include <tds_sysdep_public.h>
251 :
252 : /* define noops as "successful" */
253 : typedef struct {
254 : char dummy[0]; /* compiler compatibility */
255 : } tds_raw_mutex;
256 :
257 : #define TDS_RAW_MUTEX_INITIALIZER {}
258 :
259 : static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
260 : {
261 : }
262 :
263 : static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
264 : {
265 : return 0;
266 : }
267 :
268 : static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
269 : {
270 : }
271 :
272 : static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
273 : {
274 : return 0;
275 : }
276 :
277 : static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
278 : {
279 : }
280 :
281 : typedef struct {
282 : char dummy[0]; /* compiler compatibility */
283 : } tds_condition;
284 :
285 : static inline int tds_raw_cond_init(tds_condition *cond)
286 : {
287 : return 0;
288 : }
289 : static inline int tds_raw_cond_destroy(tds_condition *cond)
290 : {
291 : return 0;
292 : }
293 : #define tds_raw_cond_signal(cond) \
294 : FreeTDS_Condition_not_compiled
295 :
296 : #define tds_raw_cond_wait(cond, mtx) \
297 : FreeTDS_Condition_not_compiled
298 :
299 : #define tds_raw_cond_timedwait(cond, mtx, timeout_sec) \
300 : FreeTDS_Condition_not_compiled
301 :
302 : typedef struct {
303 : char dummy[0]; /* compiler compatibility */
304 : } tds_thread;
305 : typedef int tds_thread_id;
306 :
307 : typedef void *(*tds_thread_proc)(void *arg);
308 : #define TDS_THREAD_PROC_DECLARE(name, arg) \
309 : void *name(void *arg)
310 : #define TDS_THREAD_RESULT(n) ((void*)(TDS_INTPTR)(n))
311 :
312 : #define tds_thread_create(ret, proc, arg) \
313 : FreeTDS_Thread_not_compiled
314 :
315 : #define tds_thread_create_detached(proc, arg) \
316 : FreeTDS_Thread_not_compiled
317 :
318 : #define tds_thread_join(th, ret) \
319 : FreeTDS_Thread_not_compiled
320 :
321 : static inline tds_thread_id tds_thread_get_current_id(void)
322 : {
323 : return 0;
324 : }
325 :
326 : static inline int tds_thread_is_current(tds_thread_id th)
327 : {
328 : return 1;
329 : }
330 :
331 : #endif
332 :
333 : # define tds_cond_init tds_raw_cond_init
334 : # define tds_cond_destroy tds_raw_cond_destroy
335 : # define tds_cond_signal tds_raw_cond_signal
336 : # if !ENABLE_EXTRA_CHECKS || !defined(TDS_HAVE_MUTEX)
337 : # define TDS_MUTEX_INITIALIZER TDS_RAW_MUTEX_INITIALIZER
338 : # define tds_mutex tds_raw_mutex
339 : # define tds_mutex_lock tds_raw_mutex_lock
340 : # define tds_mutex_trylock tds_raw_mutex_trylock
341 : # define tds_mutex_unlock tds_raw_mutex_unlock
342 : # define tds_mutex_check_owned(mtx) do {} while(0)
343 : # define tds_mutex_init tds_raw_mutex_init
344 : # define tds_mutex_free tds_raw_mutex_free
345 : # define tds_cond_wait tds_raw_cond_wait
346 : # define tds_cond_timedwait tds_raw_cond_timedwait
347 : # else
348 : # include <assert.h>
349 :
350 : typedef struct tds_mutex
351 : {
352 : tds_raw_mutex mtx;
353 : volatile int locked;
354 : volatile tds_thread_id locked_by;
355 : } tds_mutex;
356 :
357 : # define TDS_MUTEX_INITIALIZER { TDS_RAW_MUTEX_INITIALIZER, 0 }
358 :
359 751195 : static inline void tds_mutex_lock(tds_mutex *mtx)
360 : {
361 751195 : assert(mtx);
362 1502390 : tds_raw_mutex_lock(&mtx->mtx);
363 751195 : assert(!mtx->locked);
364 751195 : mtx->locked = 1;
365 751195 : mtx->locked_by = tds_thread_get_current_id();
366 751195 : }
367 :
368 569983 : static inline int tds_mutex_trylock(tds_mutex *mtx)
369 : {
370 : int ret;
371 569983 : assert(mtx);
372 1139966 : ret = tds_raw_mutex_trylock(&mtx->mtx);
373 569983 : if (!ret) {
374 569694 : assert(!mtx->locked);
375 569694 : mtx->locked = 1;
376 569694 : mtx->locked_by = tds_thread_get_current_id();
377 : }
378 569983 : return ret;
379 : }
380 :
381 1320889 : static inline void tds_mutex_unlock(tds_mutex *mtx)
382 : {
383 1320889 : assert(mtx && mtx->locked);
384 1320889 : mtx->locked = 0;
385 2641778 : tds_raw_mutex_unlock(&mtx->mtx);
386 1320889 : }
387 :
388 106256 : static inline void tds_mutex_check_owned(tds_mutex *mtx)
389 : {
390 : int ret;
391 106256 : assert(mtx);
392 212512 : ret = tds_raw_mutex_trylock(&mtx->mtx);
393 106256 : assert(ret);
394 106256 : assert(mtx->locked);
395 212512 : assert(tds_thread_is_current(mtx->locked_by));
396 106256 : }
397 :
398 : static inline int tds_mutex_init(tds_mutex *mtx)
399 : {
400 108595 : mtx->locked = 0;
401 217190 : return tds_raw_mutex_init(&mtx->mtx);
402 : }
403 :
404 103891 : static inline void tds_mutex_free(tds_mutex *mtx)
405 : {
406 103891 : assert(mtx && !mtx->locked);
407 207782 : tds_raw_mutex_free(&mtx->mtx);
408 103891 : }
409 :
410 10 : static inline int tds_cond_wait(tds_condition *cond, tds_mutex *mtx)
411 : {
412 : int ret;
413 10 : assert(mtx && mtx->locked);
414 10 : mtx->locked = 0;
415 20 : ret = tds_raw_cond_wait(cond, &mtx->mtx);
416 10 : mtx->locked = 1;
417 10 : mtx->locked_by = tds_thread_get_current_id();
418 10 : return ret;
419 : }
420 :
421 40 : static inline int tds_cond_timedwait(tds_condition *cond, tds_mutex *mtx, int timeout_sec)
422 : {
423 : int ret;
424 40 : assert(mtx && mtx->locked);
425 40 : mtx->locked = 0;
426 40 : ret = tds_raw_cond_timedwait(cond, &mtx->mtx, timeout_sec);
427 40 : mtx->locked = 1;
428 40 : mtx->locked_by = tds_thread_get_current_id();
429 40 : return ret;
430 : }
431 :
432 : # endif
433 :
434 : #endif
|