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 _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
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 11 /* EAGAIN */;
215
216 /* Avoids leaking the handle - Thread continues to run */
217 CloseHandle(h);
218 return 0;
219}
220
221static 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
238static inline tds_thread_id tds_thread_get_current_id(void)
239{
240 return GetCurrentThreadId();
241}
242
243static 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
259static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
260{
261}
262
263static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
264{
265 return 0;
266}
267
268static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
269{
270}
271
272static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
273{
274 return 0;
275}
276
277static 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
285static inline int tds_raw_cond_init(tds_condition *cond)
286{
287 return 0;
288}
289static 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;
305typedef int tds_thread_id;
306
307typedef 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
321static inline tds_thread_id tds_thread_get_current_id(void)
322{
323 return 0;
324}
325
326static 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
350typedef 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
359static inline void tds_mutex_lock(tds_mutex *mtx)
360{
361 assert(mtx);
362 tds_raw_mutex_lock(&mtx->mtx);
363 assert(!mtx->locked);
364 mtx->locked = 1;
365 mtx->locked_by = tds_thread_get_current_id();
366}
367
368static inline int tds_mutex_trylock(tds_mutex *mtx)
369{
370 int ret;
371 assert(mtx);
372 ret = tds_raw_mutex_trylock(&mtx->mtx);
373 if (!ret) {
374 assert(!mtx->locked);
375 mtx->locked = 1;
376 mtx->locked_by = tds_thread_get_current_id();
377 }
378 return ret;
379}
380
381static inline void tds_mutex_unlock(tds_mutex *mtx)
382{
383 assert(mtx && mtx->locked);
384 mtx->locked = 0;
385 tds_raw_mutex_unlock(&mtx->mtx);
386}
387
388static inline void tds_mutex_check_owned(tds_mutex *mtx)
389{
390 int ret;
391 assert(mtx);
392 ret = tds_raw_mutex_trylock(&mtx->mtx);
393 assert(ret);
394 assert(mtx->locked);
395 assert(tds_thread_is_current(mtx->locked_by));
396}
397
398static inline int tds_mutex_init(tds_mutex *mtx)
399{
400 mtx->locked = 0;
401 return tds_raw_mutex_init(&mtx->mtx);
402}
403
404static inline void tds_mutex_free(tds_mutex *mtx)
405{
406 assert(mtx && !mtx->locked);
407 tds_raw_mutex_free(&mtx->mtx);
408}
409
410static inline int tds_cond_wait(tds_condition *cond, tds_mutex *mtx)
411{
412 int ret;
413 assert(mtx && mtx->locked);
414 mtx->locked = 0;
415 ret = tds_raw_cond_wait(cond, &mtx->mtx);
416 mtx->locked = 1;
417 mtx->locked_by = tds_thread_get_current_id();
418 return ret;
419}
420
421static inline int tds_cond_timedwait(tds_condition *cond, tds_mutex *mtx, int timeout_sec)
422{
423 int ret;
424 assert(mtx && mtx->locked);
425 mtx->locked = 0;
426 ret = tds_raw_cond_timedwait(cond, &mtx->mtx, timeout_sec);
427 mtx->locked = 1;
428 mtx->locked_by = tds_thread_get_current_id();
429 return ret;
430}
431
432# endif
433
434#endif
ptw32_mcs_node_t_
Definition ptw32_MCS_lock.c:98
tds_raw_mutex
Definition thread.h:253
tds_condition
Definition thread.h:281
tds_thread
Definition thread.h:302