FreeTDS API
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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
Definition: thread.h:255
Definition: thread.h:228
Definition: ptw32_MCS_lock.c:97
Definition: thread.h:275