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 #include <windows.h>
120 
121 struct ptw32_mcs_node_t_;
122 
123 typedef struct {
124  struct ptw32_mcs_node_t_ *lock;
125  LONG done;
126  CRITICAL_SECTION crit;
127 } tds_raw_mutex;
128 
129 #define TDS_RAW_MUTEX_INITIALIZER { NULL, 0 }
130 
131 static inline int
132 tds_raw_mutex_init(tds_raw_mutex *mtx)
133 {
134  mtx->lock = NULL;
135  mtx->done = 0;
136  return 0;
137 }
138 
139 void tds_win_mutex_lock(tds_raw_mutex *mutex);
140 
141 static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
142 {
143  if ((mtx)->done)
144  EnterCriticalSection(&(mtx)->crit);
145  else
146  tds_win_mutex_lock(mtx);
147 }
148 
149 int tds_raw_mutex_trylock(tds_raw_mutex *mtx);
150 
151 static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
152 {
153  LeaveCriticalSection(&(mtx)->crit);
154 }
155 
156 static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
157 {
158  if ((mtx)->done) {
159  DeleteCriticalSection(&(mtx)->crit);
160  (mtx)->done = 0;
161  }
162 }
163 
164 #define TDS_HAVE_MUTEX 1
165 
166 /* easy way, only single signal supported */
167 typedef void *TDS_CONDITION_VARIABLE;
168 typedef union {
169  HANDLE ev;
170  TDS_CONDITION_VARIABLE cv;
171 } tds_condition;
172 
173 extern int (*tds_raw_cond_init)(tds_condition *cond);
174 extern int (*tds_raw_cond_destroy)(tds_condition *cond);
175 extern int (*tds_raw_cond_signal)(tds_condition *cond);
176 extern int (*tds_raw_cond_timedwait)(tds_condition *cond, tds_raw_mutex *mtx, int timeout_sec);
177 static inline int tds_raw_cond_wait(tds_condition *cond, tds_raw_mutex *mtx)
178 {
179  return tds_raw_cond_timedwait(cond, mtx, -1);
180 }
181 
182 typedef HANDLE tds_thread;
183 typedef DWORD tds_thread_id;
184 typedef void *(WINAPI *tds_thread_proc)(void *arg);
185 #define TDS_THREAD_PROC_DECLARE(name, arg) \
186  void *WINAPI name(void *arg)
187 
188 static inline int tds_thread_create(tds_thread *ret, tds_thread_proc proc, void *arg)
189 {
190  *ret = CreateThread(NULL, 0, (DWORD (WINAPI *)(void*)) proc, arg, 0, NULL);
191  return *ret != NULL ? 0 : 11 /* EAGAIN */;
192 }
193 
194 static inline int tds_thread_create_detached(tds_thread_proc proc, void *arg)
195 {
196  HANDLE h = CreateThread(NULL, 0, (DWORD (WINAPI *)(void*)) proc, arg, 0, NULL);
197  if (h)
198  return 0;
199  CloseHandle(h);
200  return 11 /* EAGAIN */;
201 }
202 
203 static inline int tds_thread_join(tds_thread th, void **ret)
204 {
205  if (WaitForSingleObject(th, INFINITE) == WAIT_OBJECT_0) {
206  DWORD r;
207  if (ret && GetExitCodeThread(th, &r))
208  *ret = (void*) (((char*)0) + r);
209 
210  CloseHandle(th);
211  return 0;
212  }
213  CloseHandle(th);
214  return 22 /* EINVAL */;
215 }
216 
217 static inline tds_thread_id tds_thread_get_current_id(void)
218 {
219  return GetCurrentThreadId();
220 }
221 
222 static inline int tds_thread_is_current(tds_thread_id th)
223 {
224  return th == GetCurrentThreadId();
225 }
226 
227 #else
228 
229 /* define noops as "successful" */
230 typedef struct {
231 } tds_raw_mutex;
232 
233 #define TDS_RAW_MUTEX_INITIALIZER {}
234 
235 static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
236 {
237 }
238 
239 static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
240 {
241  return 0;
242 }
243 
244 static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
245 {
246 }
247 
248 static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
249 {
250  return 0;
251 }
252 
253 static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
254 {
255 }
256 
257 typedef struct {
258 } tds_condition;
259 
260 static inline int tds_raw_cond_init(tds_condition *cond)
261 {
262  return 0;
263 }
264 static inline int tds_raw_cond_destroy(tds_condition *cond)
265 {
266  return 0;
267 }
268 #define tds_raw_cond_signal(cond) \
269  FreeTDS_Condition_not_compiled
270 
271 #define tds_raw_cond_wait(cond, mtx) \
272  FreeTDS_Condition_not_compiled
273 
274 #define tds_raw_cond_timedwait(cond, mtx, timeout_sec) \
275  FreeTDS_Condition_not_compiled
276 
277 typedef struct {
278 } tds_thread;
279 typedef int tds_thread_id;
280 
281 typedef void *(*tds_thread_proc)(void *arg);
282 #define TDS_THREAD_PROC_DECLARE(name, arg) \
283  void *name(void *arg)
284 
285 #define tds_thread_create(ret, proc, arg) \
286  FreeTDS_Thread_not_compiled
287 
288 #define tds_thread_create_detached(proc, arg) \
289  FreeTDS_Thread_not_compiled
290 
291 #define tds_thread_join(th, ret) \
292  FreeTDS_Thread_not_compiled
293 
294 static inline tds_thread_id tds_thread_get_current_id(void)
295 {
296  return 0;
297 }
298 
299 static inline int tds_thread_is_current(tds_thread_id th)
300 {
301  return 1;
302 }
303 
304 
305 #endif
306 
307 #ifdef TDS_HAVE_MUTEX
308 # define tds_cond_init tds_raw_cond_init
309 # define tds_cond_destroy tds_raw_cond_destroy
310 # define tds_cond_signal tds_raw_cond_signal
311 # if !ENABLE_EXTRA_CHECKS
312 # define TDS_MUTEX_INITIALIZER TDS_RAW_MUTEX_INITIALIZER
313 # define tds_mutex tds_raw_mutex
314 # define tds_mutex_lock tds_raw_mutex_lock
315 # define tds_mutex_trylock tds_raw_mutex_trylock
316 # define tds_mutex_unlock tds_raw_mutex_unlock
317 # define tds_mutex_check_owned(mtx) do {} while(0)
318 # define tds_mutex_init tds_raw_mutex_init
319 # define tds_mutex_free tds_raw_mutex_free
320 # define tds_cond_wait tds_raw_cond_wait
321 # define tds_cond_timedwait tds_raw_cond_timedwait
322 # else
323 # include <assert.h>
324 
325 typedef struct tds_mutex
326 {
327  tds_raw_mutex mtx;
328  volatile int locked;
329  volatile tds_thread_id locked_by;
330 } tds_mutex;
331 
332 # define TDS_MUTEX_INITIALIZER { TDS_RAW_MUTEX_INITIALIZER, 0 }
333 
334 static inline void tds_mutex_lock(tds_mutex *mtx)
335 {
336  assert(mtx);
337  tds_raw_mutex_lock(&mtx->mtx);
338  assert(!mtx->locked);
339  mtx->locked = 1;
340  mtx->locked_by = tds_thread_get_current_id();
341 }
342 
343 static inline int tds_mutex_trylock(tds_mutex *mtx)
344 {
345  int ret;
346  assert(mtx);
347  ret = tds_raw_mutex_trylock(&mtx->mtx);
348  if (!ret) {
349  assert(!mtx->locked);
350  mtx->locked = 1;
351  mtx->locked_by = tds_thread_get_current_id();
352  }
353  return ret;
354 }
355 
356 static inline void tds_mutex_unlock(tds_mutex *mtx)
357 {
358  assert(mtx && mtx->locked);
359  mtx->locked = 0;
360  tds_raw_mutex_unlock(&mtx->mtx);
361 }
362 
363 static inline void tds_mutex_check_owned(tds_mutex *mtx)
364 {
365  int ret;
366  assert(mtx);
367  ret = tds_raw_mutex_trylock(&mtx->mtx);
368  assert(ret);
369  assert(mtx->locked);
370  assert(tds_thread_is_current(mtx->locked_by));
371 }
372 
373 static inline int tds_mutex_init(tds_mutex *mtx)
374 {
375  mtx->locked = 0;
376  return tds_raw_mutex_init(&mtx->mtx);
377 }
378 
379 static inline void tds_mutex_free(tds_mutex *mtx)
380 {
381  assert(mtx && !mtx->locked);
382  tds_raw_mutex_free(&mtx->mtx);
383 }
384 
385 static inline int tds_cond_wait(tds_condition *cond, tds_mutex *mtx)
386 {
387  int ret;
388  assert(mtx && mtx->locked);
389  mtx->locked = 0;
390  ret = tds_raw_cond_wait(cond, &mtx->mtx);
391  mtx->locked = 1;
392  mtx->locked_by = tds_thread_get_current_id();
393  return ret;
394 }
395 
396 static inline int tds_cond_timedwait(tds_condition *cond, tds_mutex *mtx, int timeout_sec)
397 {
398  int ret;
399  assert(mtx && mtx->locked);
400  mtx->locked = 0;
401  ret = tds_raw_cond_timedwait(cond, &mtx->mtx, timeout_sec);
402  mtx->locked = 1;
403  mtx->locked_by = tds_thread_get_current_id();
404  return ret;
405 }
406 
407 # endif
408 #endif
409 
410 #endif
Definition: thread.h:257
Definition: thread.h:230
Definition: ptw32_MCS_lock.c:97
Definition: thread.h:277