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
131typedef struct
132{
133 SRWLOCK srwlock;
134} tds_raw_mutex;
135
136#define TDS_RAW_MUTEX_INITIALIZER { SRWLOCK_INIT }
137
138extern int (*tds_raw_mutex_init)(tds_raw_mutex * mtx);
139extern void (*tds_raw_mutex_free)(tds_raw_mutex * mtx);
140extern void (*tds_raw_mutex_lock)(tds_raw_mutex * mtx);
141extern void (*tds_raw_mutex_unlock)(tds_raw_mutex * mtx);
142extern int (*tds_raw_mutex_trylock)(tds_raw_mutex * mtx);
143
144#define TDS_HAVE_MUTEX 1
145
146/* easy way, only single signal supported */
147typedef void *TDS_CONDITION_VARIABLE;
148typedef union {
149 HANDLE ev;
150 TDS_CONDITION_VARIABLE cv;
151} tds_condition;
152
153extern int (*tds_raw_cond_init)(tds_condition *cond);
154extern int (*tds_raw_cond_destroy)(tds_condition *cond);
155extern int (*tds_raw_cond_signal)(tds_condition *cond);
156extern int (*tds_raw_cond_timedwait)(tds_condition *cond, tds_raw_mutex *mtx, int timeout_sec);
157static 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
162typedef HANDLE tds_thread;
163typedef DWORD tds_thread_id;
164typedef 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
169static 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
175static 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
186static 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
203static inline tds_thread_id tds_thread_get_current_id(void)
204{
205 return GetCurrentThreadId();
206}
207
208static 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
224static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
225{
226}
227
228static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
229{
230 return 0;
231}
232
233static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
234{
235}
236
237static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
238{
239 return 0;
240}
241
242static 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
250static inline int tds_raw_cond_init(tds_condition *cond)
251{
252 return 0;
253}
254static 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;
270typedef int tds_thread_id;
271
272typedef 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
286static inline tds_thread_id tds_thread_get_current_id(void)
287{
288 return 0;
289}
290
291static 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
315typedef 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
324static inline void tds_mutex_lock(tds_mutex *mtx)
325{
326 assert(mtx);
327 tds_raw_mutex_lock(&mtx->mtx);
328 assert(!mtx->locked);
329 mtx->locked = 1;
330 mtx->locked_by = tds_thread_get_current_id();
331}
332
333static inline int tds_mutex_trylock(tds_mutex *mtx)
334{
335 int ret;
336 assert(mtx);
337 ret = tds_raw_mutex_trylock(&mtx->mtx);
338 if (!ret) {
339 assert(!mtx->locked);
340 mtx->locked = 1;
341 mtx->locked_by = tds_thread_get_current_id();
342 }
343 return ret;
344}
345
346static inline void tds_mutex_unlock(tds_mutex *mtx)
347{
348 assert(mtx && mtx->locked);
349 mtx->locked = 0;
350 tds_raw_mutex_unlock(&mtx->mtx);
351}
352
353static inline void tds_mutex_check_owned(tds_mutex *mtx)
354{
355 int ret;
356 assert(mtx);
357 ret = tds_raw_mutex_trylock(&mtx->mtx);
358 assert(ret);
359 assert(mtx->locked);
360 assert(tds_thread_is_current(mtx->locked_by));
361}
362
363static inline int tds_mutex_init(tds_mutex *mtx)
364{
365 mtx->locked = 0;
366 return tds_raw_mutex_init(&mtx->mtx);
367}
368
369static inline void tds_mutex_free(tds_mutex *mtx)
370{
371 assert(mtx && !mtx->locked);
372 tds_raw_mutex_free(&mtx->mtx);
373}
374
375static inline int tds_cond_wait(tds_condition *cond, tds_mutex *mtx)
376{
377 int ret;
378 assert(mtx && mtx->locked);
379 mtx->locked = 0;
380 ret = tds_raw_cond_wait(cond, &mtx->mtx);
381 mtx->locked = 1;
382 mtx->locked_by = tds_thread_get_current_id();
383 return ret;
384}
385
386static inline int tds_cond_timedwait(tds_condition *cond, tds_mutex *mtx, int timeout_sec)
387{
388 int ret;
389 assert(mtx && mtx->locked);
390 mtx->locked = 0;
391 ret = tds_raw_cond_timedwait(cond, &mtx->mtx, timeout_sec);
392 mtx->locked = 1;
393 mtx->locked_by = tds_thread_get_current_id();
394 return ret;
395}
396
397# endif
398
399#endif
tds_raw_mutex
Definition thread.h:218
tds_condition
Definition thread.h:246
tds_thread
Definition thread.h:267