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 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 <pthread.h>
30
31 #include <freetds/pushvis.h>
32
33 typedef pthread_mutex_t tds_raw_mutex;
34 #define TDS_RAW_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
35
36 static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
37 {
38 pthread_mutex_lock(mtx);
39 }
40
41 static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
42 {
43 return pthread_mutex_trylock(mtx);
44 }
45
46 static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
47 {
48 pthread_mutex_unlock(mtx);
49 }
50
51 static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
52 {
53 return pthread_mutex_init(mtx, NULL);
54 }
55
56 static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
57 {
58 pthread_mutex_destroy(mtx);
59 }
60
61 typedef pthread_cond_t tds_condition;
62
63 int tds_raw_cond_init(tds_condition *cond);
64 static inline int tds_raw_cond_destroy(tds_condition *cond)
65 {
66 return pthread_cond_destroy(cond);
67 }
68 static inline int tds_raw_cond_signal(tds_condition *cond)
69 {
70 return pthread_cond_signal(cond);
71 }
72 static inline int tds_raw_cond_wait(tds_condition *cond, tds_raw_mutex *mtx)
73 {
74 return pthread_cond_wait(cond, mtx);
75 }
76 int tds_raw_cond_timedwait(tds_condition *cond, tds_raw_mutex *mtx, int timeout_sec);
77
78 #define TDS_HAVE_MUTEX 1
79
80 typedef pthread_t tds_thread;
81 typedef pthread_t tds_thread_id;
82 typedef void *(*tds_thread_proc)(void *arg);
83 #define TDS_THREAD_PROC_DECLARE(name, arg) \
84 void *name(void *arg)
85
86 static inline int tds_thread_create(tds_thread *ret, tds_thread_proc proc, void *arg)
87 {
88 return pthread_create(ret, NULL, proc, arg);
89 }
90
91 static inline int tds_thread_create_detached(tds_thread_proc proc, void *arg)
92 {
93 tds_thread th;
94 int ret = pthread_create(&th, NULL, proc, arg);
95 if (!ret)
96 pthread_detach(th);
97 return ret;
98 }
99
100 static inline int tds_thread_join(tds_thread th, void **ret)
101 {
102 return pthread_join(th, ret);
103 }
104
105 static inline tds_thread_id tds_thread_get_current_id(void)
106 {
107 return pthread_self();
108 }
109
110 static inline int tds_thread_is_current(tds_thread_id th)
111 {
112 return pthread_equal(th, pthread_self());
113 }
114
115 #include <freetds/popvis.h>
116
117 #elif defined(_WIN32)
118
119 struct ptw32_mcs_node_t_;
120
121 typedef struct {
122 struct ptw32_mcs_node_t_ *lock;
123 LONG done;
124 CRITICAL_SECTION crit;
125 } tds_raw_mutex;
126
127 #define TDS_RAW_MUTEX_INITIALIZER { NULL, 0 }
128
129 static inline int
130 tds_raw_mutex_init(tds_raw_mutex *mtx)
131 {
132 mtx->lock = NULL;
133 mtx->done = 0;
134 return 0;
135 }
136
137 void tds_win_mutex_lock(tds_raw_mutex *mutex);
138
139 static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
140 {
141 if ((mtx)->done)
142 EnterCriticalSection(&(mtx)->crit);
143 else
144 tds_win_mutex_lock(mtx);
145 }
146
147 int tds_raw_mutex_trylock(tds_raw_mutex *mtx);
148
149 static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
150 {
151 LeaveCriticalSection(&(mtx)->crit);
152 }
153
154 static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
155 {
156 if ((mtx)->done) {
157 DeleteCriticalSection(&(mtx)->crit);
158 (mtx)->done = 0;
159 }
160 }
161
162 #define TDS_HAVE_MUTEX 1
163
164 /* easy way, only single signal supported */
165 typedef void *TDS_CONDITION_VARIABLE;
166 typedef union {
167 HANDLE ev;
168 TDS_CONDITION_VARIABLE cv;
169 } tds_condition;
170
171 extern int (*tds_raw_cond_init)(tds_condition *cond);
172 extern int (*tds_raw_cond_destroy)(tds_condition *cond);
173 extern int (*tds_raw_cond_signal)(tds_condition *cond);
174 extern int (*tds_raw_cond_timedwait)(tds_condition *cond, tds_raw_mutex *mtx, int timeout_sec);
175 static inline int tds_raw_cond_wait(tds_condition *cond, tds_raw_mutex *mtx)
176 {
177 return tds_raw_cond_timedwait(cond, mtx, -1);
178 }
179
180 typedef HANDLE tds_thread;
181 typedef DWORD tds_thread_id;
182 typedef void *(WINAPI *tds_thread_proc)(void *arg);
183 #define TDS_THREAD_PROC_DECLARE(name, arg) \
184 void *WINAPI name(void *arg)
185
186 static inline int tds_thread_create(tds_thread *ret, tds_thread_proc proc, void *arg)
187 {
188 *ret = CreateThread(NULL, 0, (DWORD (WINAPI *)(void*)) proc, arg, 0, NULL);
189 return *ret != NULL ? 0 : 11 /* EAGAIN */;
190 }
191
192 static inline int tds_thread_create_detached(tds_thread_proc proc, void *arg)
193 {
194 HANDLE h = CreateThread(NULL, 0, (DWORD (WINAPI *)(void*)) proc, arg, 0, NULL);
195 if (h)
196 return 0;
197 CloseHandle(h);
198 return 11 /* EAGAIN */;
199 }
200
201 static inline int tds_thread_join(tds_thread th, void **ret)
202 {
203 if (WaitForSingleObject(th, INFINITE) == WAIT_OBJECT_0) {
204 DWORD r;
205 if (ret && GetExitCodeThread(th, &r))
206 *ret = (void*) (((char*)0) + r);
207
208 CloseHandle(th);
209 return 0;
210 }
211 CloseHandle(th);
212 return 22 /* EINVAL */;
213 }
214
215 static inline tds_thread_id tds_thread_get_current_id(void)
216 {
217 return GetCurrentThreadId();
218 }
219
220 static inline int tds_thread_is_current(tds_thread_id th)
221 {
222 return th == GetCurrentThreadId();
223 }
224
225 #else
226
227 /* define noops as "successful" */
228 typedef struct {
229 } tds_raw_mutex;
230
231 #define TDS_RAW_MUTEX_INITIALIZER {}
232
233 static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
234 {
235 }
236
237 static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
238 {
239 return 0;
240 }
241
242 static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
243 {
244 }
245
246 static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
247 {
248 return 0;
249 }
250
251 static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
252 {
253 }
254
255 typedef struct {
256 } tds_condition;
257
258 static inline int tds_raw_cond_init(tds_condition *cond)
259 {
260 return 0;
261 }
262 static inline int tds_raw_cond_destroy(tds_condition *cond)
263 {
264 return 0;
265 }
266 #define tds_raw_cond_signal(cond) \
267 FreeTDS_Condition_not_compiled
268
269 #define tds_raw_cond_wait(cond, mtx) \
270 FreeTDS_Condition_not_compiled
271
272 #define tds_raw_cond_timedwait(cond, mtx, timeout_sec) \
273 FreeTDS_Condition_not_compiled
274
275 typedef struct {
276 } tds_thread;
277 typedef int tds_thread_id;
278
279 typedef void *(*tds_thread_proc)(void *arg);
280 #define TDS_THREAD_PROC_DECLARE(name, arg) \
281 void *name(void *arg)
282
283 #define tds_thread_create(ret, proc, arg) \
284 FreeTDS_Thread_not_compiled
285
286 #define tds_thread_create_detached(proc, arg) \
287 FreeTDS_Thread_not_compiled
288
289 #define tds_thread_join(th, ret) \
290 FreeTDS_Thread_not_compiled
291
292 static inline tds_thread_id tds_thread_get_current_id(void)
293 {
294 return 0;
295 }
296
297 static inline int tds_thread_is_current(tds_thread_id th)
298 {
299 return 1;
300 }
301
302
303 #endif
304
305 #ifdef TDS_HAVE_MUTEX
306 # define tds_cond_init tds_raw_cond_init
307 # define tds_cond_destroy tds_raw_cond_destroy
308 # define tds_cond_signal tds_raw_cond_signal
309 # if !ENABLE_EXTRA_CHECKS
310 # define TDS_MUTEX_INITIALIZER TDS_RAW_MUTEX_INITIALIZER
311 # define tds_mutex tds_raw_mutex
312 # define tds_mutex_lock tds_raw_mutex_lock
313 # define tds_mutex_trylock tds_raw_mutex_trylock
314 # define tds_mutex_unlock tds_raw_mutex_unlock
315 # define tds_mutex_check_owned(mtx) do {} while(0)
316 # define tds_mutex_init tds_raw_mutex_init
317 # define tds_mutex_free tds_raw_mutex_free
318 # define tds_cond_wait tds_raw_cond_wait
319 # define tds_cond_timedwait tds_raw_cond_timedwait
320 # else
321 # include <assert.h>
322
323 typedef struct tds_mutex
324 {
325 tds_raw_mutex mtx;
326 volatile int locked;
327 volatile tds_thread_id locked_by;
328 } tds_mutex;
329
330 # define TDS_MUTEX_INITIALIZER { TDS_RAW_MUTEX_INITIALIZER, 0 }
331
332 static inline void tds_mutex_lock(tds_mutex *mtx)
333 {
334 assert(mtx);
335 tds_raw_mutex_lock(&mtx->mtx);
336 assert(!mtx->locked);
337 mtx->locked = 1;
338 mtx->locked_by = tds_thread_get_current_id();
339 }
340
341 static inline int tds_mutex_trylock(tds_mutex *mtx)
342 {
343 int ret;
344 assert(mtx);
345 ret = tds_raw_mutex_trylock(&mtx->mtx);
346 if (!ret) {
347 assert(!mtx->locked);
348 mtx->locked = 1;
349 mtx->locked_by = tds_thread_get_current_id();
350 }
351 return ret;
352 }
353
354 static inline void tds_mutex_unlock(tds_mutex *mtx)
355 {
356 assert(mtx && mtx->locked);
357 mtx->locked = 0;
358 tds_raw_mutex_unlock(&mtx->mtx);
359 }
360
361 static inline void tds_mutex_check_owned(tds_mutex *mtx)
362 {
363 int ret;
364 assert(mtx);
365 ret = tds_raw_mutex_trylock(&mtx->mtx);
366 assert(ret);
367 assert(mtx->locked);
368 assert(tds_thread_is_current(mtx->locked_by));
369 }
370
371 static inline int tds_mutex_init(tds_mutex *mtx)
372 {
373 mtx->locked = 0;
374 return tds_raw_mutex_init(&mtx->mtx);
375 }
376
377 static inline void tds_mutex_free(tds_mutex *mtx)
378 {
379 assert(mtx && !mtx->locked);
380 tds_raw_mutex_free(&mtx->mtx);
381 }
382
383 static inline int tds_cond_wait(tds_condition *cond, tds_mutex *mtx)
384 {
385 int ret;
386 assert(mtx && mtx->locked);
387 mtx->locked = 0;
388 ret = tds_raw_cond_wait(cond, &mtx->mtx);
389 mtx->locked = 1;
390 mtx->locked_by = tds_thread_get_current_id();
391 return ret;
392 }
393
394 static inline int tds_cond_timedwait(tds_condition *cond, tds_mutex *mtx, int timeout_sec)
395 {
396 int ret;
397 assert(mtx && mtx->locked);
398 mtx->locked = 0;
399 ret = tds_raw_cond_timedwait(cond, &mtx->mtx, timeout_sec);
400 mtx->locked = 1;
401 mtx->locked_by = tds_thread_get_current_id();
402 return ret;
403 }
404
405 # endif
406 #endif
407
408 #endif
tds_raw_mutex
Definition: thread.h:228
tds_thread
Definition: thread.h:275
tds_condition
Definition: thread.h:255
ptw32_mcs_node_t_
Definition: ptw32_MCS_lock.c:97