FreeTDS API: include/freetds/thread.h Source File

FreeTDS API

Loading...
Searching...
No Matches
thread.h
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 TDSTHREAD_H
23#define TDSTHREAD_H 1
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
36typedef pthread_mutex_t tds_raw_mutex;
37#define TDS_RAW_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
38
39static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
40{
41 pthread_mutex_lock(mtx);
42}
43
44static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
45{
46 return pthread_mutex_trylock(mtx);
47}
48
49static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
50{
51 pthread_mutex_unlock(mtx);
52}
53
54static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
55{
56 return pthread_mutex_init(mtx, NULL);
57}
58
59static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
60{
61 pthread_mutex_destroy(mtx);
62}
63
64typedef pthread_cond_t tds_condition;
65
66int tds_raw_cond_init(tds_condition *cond);
67static inline int tds_raw_cond_destroy(tds_condition *cond)
68{
69 return pthread_cond_destroy(cond);
70}
71static inline int tds_raw_cond_signal(tds_condition *cond)
72{
73 return pthread_cond_signal(cond);
74}
75static inline int tds_raw_cond_wait(tds_condition *cond, tds_raw_mutex *mtx)
76{
77 return pthread_cond_wait(cond, mtx);
78}
79int tds_raw_cond_timedwait(tds_condition *cond, tds_raw_mutex *mtx, int timeout_sec);
80
81#define TDS_HAVE_MUTEX 1
82
83typedef pthread_t tds_thread;
84typedef pthread_t tds_thread_id;
85typedef 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
90static inline int tds_thread_create(tds_thread *ret, tds_thread_proc proc, void *arg)
91{
92 return pthread_create(ret, NULL, proc, arg);
93}
94
95static inline int tds_thread_create_detached(tds_thread_proc proc, void *arg)
96{
97 tds_thread th;
98 int ret = pthread_create(&th, NULL, proc, arg);
99 if (!ret)
100 pthread_detach(th);
101 return ret;
102}
103
104static inline int tds_thread_join(tds_thread th, void **ret)
105{
106 return pthread_join(th, ret);
107}
108
109static inline tds_thread_id tds_thread_get_current_id(void)
110{
111 return pthread_self();
112}
113
114static inline int tds_thread_is_current(tds_thread_id th)
115{
116 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
131struct ptw32_mcs_node_t_;
132
133typedef 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
142static inline int
143tds_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
151void tds_win_mutex_lock(tds_raw_mutex *mutex);
152
153static 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
163int tds_raw_mutex_trylock(tds_raw_mutex *mtx);
164
165static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
166{
167 mtx->thread_id = 0;
168 LeaveCriticalSection(&mtx->crit);
169}
170
171static 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 */
182typedef void *TDS_CONDITION_VARIABLE;
183typedef union {
184 HANDLE ev;
185 TDS_CONDITION_VARIABLE cv;
186} tds_condition;
187
188extern int (*tds_raw_cond_init)(tds_condition *cond);
189extern int (*tds_raw_cond_destroy)(tds_condition *cond);
190extern int (*tds_raw_cond_signal)(tds_condition *cond);
191extern int (*tds_raw_cond_timedwait)(tds_condition *cond, tds_raw_mutex *mtx, int timeout_sec);
192static 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
197typedef HANDLE tds_thread;
198typedef DWORD tds_thread_id;
199typedef 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
204static 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
210static 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 0;
215 CloseHandle(h);
216 return 11 /* EAGAIN */;
217}
218
219static inline int tds_thread_join(tds_thread th, void **ret)
220{
221 if (WaitForSingleObject(th, INFINITE) == WAIT_OBJECT_0) {
222 if (ret) {
223 DWORD r;
224 if (!GetExitCodeThread(th, &r))
225 r = 0xffffffffu;
226 *ret = (void*) (((char*)0) + r);
227 }
228
229 CloseHandle(th);
230 return 0;
231 }
232 CloseHandle(th);
233 return 22 /* EINVAL */;
234}
235
236static inline tds_thread_id tds_thread_get_current_id(void)
237{
238 return GetCurrentThreadId();
239}
240
241static inline int tds_thread_is_current(tds_thread_id th)
242{
243 return th == GetCurrentThreadId();
244}
245
246#else
247
248#include <tds_sysdep_public.h>
249
250/* define noops as "successful" */
251 typedef struct {
252 char dummy[0]; /* compiler compatibility */
253} tds_raw_mutex;
254
255#define TDS_RAW_MUTEX_INITIALIZER {}
256
257static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
258{
259}
260
261static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
262{
263 return 0;
264}
265
266static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
267{
268}
269
270static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
271{
272 return 0;
273}
274
275static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
276{
277}
278
279 typedef struct {
280 char dummy[0]; /* compiler compatibility */
281} tds_condition;
282
283static inline int tds_raw_cond_init(tds_condition *cond)
284{
285 return 0;
286}
287static inline int tds_raw_cond_destroy(tds_condition *cond)
288{
289 return 0;
290}
291#define tds_raw_cond_signal(cond) \
292 FreeTDS_Condition_not_compiled
293
294#define tds_raw_cond_wait(cond, mtx) \
295 FreeTDS_Condition_not_compiled
296
297#define tds_raw_cond_timedwait(cond, mtx, timeout_sec) \
298 FreeTDS_Condition_not_compiled
299
300 typedef struct {
301 char dummy[0]; /* compiler compatibility */
302} tds_thread;
303typedef int tds_thread_id;
304
305typedef void *(*tds_thread_proc)(void *arg);
306#define TDS_THREAD_PROC_DECLARE(name, arg) \
307 void *name(void *arg)
308#define TDS_THREAD_RESULT(n) ((void*)(TDS_INTPTR)(n))
309
310#define tds_thread_create(ret, proc, arg) \
311 FreeTDS_Thread_not_compiled
312
313#define tds_thread_create_detached(proc, arg) \
314 FreeTDS_Thread_not_compiled
315
316#define tds_thread_join(th, ret) \
317 FreeTDS_Thread_not_compiled
318
319static inline tds_thread_id tds_thread_get_current_id(void)
320{
321 return 0;
322}
323
324static inline int tds_thread_is_current(tds_thread_id th)
325{
326 return 1;
327}
328
329#endif
330
331# define tds_cond_init tds_raw_cond_init
332# define tds_cond_destroy tds_raw_cond_destroy
333# define tds_cond_signal tds_raw_cond_signal
334# if !ENABLE_EXTRA_CHECKS
335# define TDS_MUTEX_INITIALIZER TDS_RAW_MUTEX_INITIALIZER
336# define tds_mutex tds_raw_mutex
337# define tds_mutex_lock tds_raw_mutex_lock
338# define tds_mutex_trylock tds_raw_mutex_trylock
339# define tds_mutex_unlock tds_raw_mutex_unlock
340# define tds_mutex_check_owned(mtx) do {} while(0)
341# define tds_mutex_init tds_raw_mutex_init
342# define tds_mutex_free tds_raw_mutex_free
343# define tds_cond_wait tds_raw_cond_wait
344# define tds_cond_timedwait tds_raw_cond_timedwait
345# else
346# include <assert.h>
347
348typedef struct tds_mutex
349{
350 tds_raw_mutex mtx;
351 volatile int locked;
352 volatile tds_thread_id locked_by;
353} tds_mutex;
354
355# define TDS_MUTEX_INITIALIZER { TDS_RAW_MUTEX_INITIALIZER, 0 }
356
357static inline void tds_mutex_lock(tds_mutex *mtx)
358{
359 assert(mtx);
360 tds_raw_mutex_lock(&mtx->mtx);
361 assert(!mtx->locked);
362 mtx->locked = 1;
363 mtx->locked_by = tds_thread_get_current_id();
364}
365
366static inline int tds_mutex_trylock(tds_mutex *mtx)
367{
368 int ret;
369 assert(mtx);
370 ret = tds_raw_mutex_trylock(&mtx->mtx);
371 if (!ret) {
372 assert(!mtx->locked);
373 mtx->locked = 1;
374 mtx->locked_by = tds_thread_get_current_id();
375 }
376 return ret;
377}
378
379static inline void tds_mutex_unlock(tds_mutex *mtx)
380{
381 assert(mtx && mtx->locked);
382 mtx->locked = 0;
383 tds_raw_mutex_unlock(&mtx->mtx);
384}
385
386static inline void tds_mutex_check_owned(tds_mutex *mtx)
387{
388 int ret;
389 assert(mtx);
390 ret = tds_raw_mutex_trylock(&mtx->mtx);
391 assert(ret);
392 assert(mtx->locked);
393 assert(tds_thread_is_current(mtx->locked_by));
394}
395
396static inline int tds_mutex_init(tds_mutex *mtx)
397{
398 mtx->locked = 0;
399 return tds_raw_mutex_init(&mtx->mtx);
400}
401
402static inline void tds_mutex_free(tds_mutex *mtx)
403{
404 assert(mtx && !mtx->locked);
405 tds_raw_mutex_free(&mtx->mtx);
406}
407
408static inline int tds_cond_wait(tds_condition *cond, tds_mutex *mtx)
409{
410 int ret;
411 assert(mtx && mtx->locked);
412 mtx->locked = 0;
413 ret = tds_raw_cond_wait(cond, &mtx->mtx);
414 mtx->locked = 1;
415 mtx->locked_by = tds_thread_get_current_id();
416 return ret;
417}
418
419static inline int tds_cond_timedwait(tds_condition *cond, tds_mutex *mtx, int timeout_sec)
420{
421 int ret;
422 assert(mtx && mtx->locked);
423 mtx->locked = 0;
424 ret = tds_raw_cond_timedwait(cond, &mtx->mtx, timeout_sec);
425 mtx->locked = 1;
426 mtx->locked_by = tds_thread_get_current_id();
427 return ret;
428}
429
430# endif
431
432#endif
ptw32_mcs_node_t_
Definition ptw32_MCS_lock.c:98
tds_raw_mutex
Definition thread.h:251
tds_condition
Definition thread.h:279
tds_thread
Definition thread.h:300