FreeTDS API
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 
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  pthread_mutex_lock(mtx);
42 }
43 
44 static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
45 {
46  return pthread_mutex_trylock(mtx);
47 }
48 
49 static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
50 {
51  pthread_mutex_unlock(mtx);
52 }
53 
54 static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
55 {
56  return pthread_mutex_init(mtx, NULL);
57 }
58 
59 static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
60 {
61  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  return pthread_cond_destroy(cond);
70 }
71 static inline int tds_raw_cond_signal(tds_condition *cond)
72 {
73  return pthread_cond_signal(cond);
74 }
75 static inline int tds_raw_cond_wait(tds_condition *cond, tds_raw_mutex *mtx)
76 {
77  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  return pthread_create(ret, NULL, proc, arg);
93 }
94 
95 static 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 
104 static inline int tds_thread_join(tds_thread th, void **ret)
105 {
106  return pthread_join(th, ret);
107 }
108 
109 static inline tds_thread_id tds_thread_get_current_id(void)
110 {
111  return pthread_self();
112 }
113 
114 static 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 
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 static 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 
333 static 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 
346 static 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 
353 static 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 
363 static inline int tds_mutex_init(tds_mutex *mtx)
364 {
365  mtx->locked = 0;
366  return tds_raw_mutex_init(&mtx->mtx);
367 }
368 
369 static inline void tds_mutex_free(tds_mutex *mtx)
370 {
371  assert(mtx && !mtx->locked);
372  tds_raw_mutex_free(&mtx->mtx);
373 }
374 
375 static 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 
386 static 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
Definition: thread.h:267
Definition: thread.h:246
Definition: thread.h:218