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 void *(*tds_thread_proc)(void *arg);
82 #define TDS_THREAD_PROC_DECLARE(name, arg) \
83  void *name(void *arg)
84 
85 static inline int tds_thread_create(tds_thread *ret, tds_thread_proc proc, void *arg)
86 {
87  return pthread_create(ret, NULL, proc, arg);
88 }
89 
90 static inline int tds_thread_join(tds_thread th, void **ret)
91 {
92  return pthread_join(th, ret);
93 }
94 
95 #include <freetds/popvis.h>
96 
97 #elif defined(_WIN32)
98 
99 struct ptw32_mcs_node_t_;
100 
101 typedef struct {
102  struct ptw32_mcs_node_t_ *lock;
103  LONG done;
104  CRITICAL_SECTION crit;
105 } tds_raw_mutex;
106 
107 #define TDS_RAW_MUTEX_INITIALIZER { NULL, 0 }
108 
109 static inline int
110 tds_raw_mutex_init(tds_raw_mutex *mtx)
111 {
112  mtx->lock = NULL;
113  mtx->done = 0;
114  return 0;
115 }
116 
117 void tds_win_mutex_lock(tds_raw_mutex *mutex);
118 
119 static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
120 {
121  if ((mtx)->done)
122  EnterCriticalSection(&(mtx)->crit);
123  else
124  tds_win_mutex_lock(mtx);
125 }
126 
127 int tds_raw_mutex_trylock(tds_raw_mutex *mtx);
128 
129 static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
130 {
131  LeaveCriticalSection(&(mtx)->crit);
132 }
133 
134 static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
135 {
136  if ((mtx)->done) {
137  DeleteCriticalSection(&(mtx)->crit);
138  (mtx)->done = 0;
139  }
140 }
141 
142 #define TDS_HAVE_MUTEX 1
143 
144 /* easy way, only single signal supported */
145 typedef void *TDS_CONDITION_VARIABLE;
146 typedef union {
147  HANDLE ev;
148  TDS_CONDITION_VARIABLE cv;
149 } tds_condition;
150 
151 extern int (*tds_raw_cond_init)(tds_condition *cond);
152 extern int (*tds_raw_cond_destroy)(tds_condition *cond);
153 extern int (*tds_raw_cond_signal)(tds_condition *cond);
154 extern int (*tds_raw_cond_timedwait)(tds_condition *cond, tds_raw_mutex *mtx, int timeout_sec);
155 static inline int tds_raw_cond_wait(tds_condition *cond, tds_raw_mutex *mtx)
156 {
157  return tds_raw_cond_timedwait(cond, mtx, -1);
158 }
159 
160 typedef HANDLE tds_thread;
161 typedef void *(WINAPI *tds_thread_proc)(void *arg);
162 #define TDS_THREAD_PROC_DECLARE(name, arg) \
163  void *WINAPI name(void *arg)
164 
165 static inline int tds_thread_create(tds_thread *ret, tds_thread_proc proc, void *arg)
166 {
167  *ret = CreateThread(NULL, 0, (DWORD (WINAPI *)(void*)) proc, arg, 0, NULL);
168  return *ret != NULL ? 0 : 11 /* EAGAIN */;
169 }
170 
171 static inline int tds_thread_join(tds_thread th, void **ret)
172 {
173  if (WaitForSingleObject(th, INFINITE) == WAIT_OBJECT_0) {
174  DWORD r;
175  if (ret && GetExitCodeThread(th, &r))
176  *ret = (void*) (((char*)0) + r);
177 
178  CloseHandle(th);
179  return 0;
180  }
181  CloseHandle(th);
182  return 22 /* EINVAL */;
183 }
184 
185 #else
186 
187 /* define noops as "successful" */
188 typedef struct {
189 } tds_raw_mutex;
190 
191 #define TDS_RAW_MUTEX_INITIALIZER {}
192 
193 static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
194 {
195 }
196 
197 static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
198 {
199  return 0;
200 }
201 
202 static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
203 {
204 }
205 
206 static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
207 {
208  return 0;
209 }
210 
211 static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
212 {
213 }
214 
215 typedef struct {
216 } tds_condition;
217 
218 static inline int tds_raw_cond_init(tds_condition *cond)
219 {
220  return 0;
221 }
222 static inline int tds_raw_cond_destroy(tds_condition *cond)
223 {
224  return 0;
225 }
226 #define tds_raw_cond_signal(cond) \
227  FreeTDS_Condition_not_compiled
228 
229 #define tds_raw_cond_wait(cond, mtx) \
230  FreeTDS_Condition_not_compiled
231 
232 #define tds_raw_cond_timedwait(cond, mtx, timeout_sec) \
233  FreeTDS_Condition_not_compiled
234 
235 typedef struct {
236 } tds_thread;
237 
238 typedef void *(*tds_thread_proc)(void *arg);
239 #define TDS_THREAD_PROC_DECLARE(name, arg) \
240  void *name(void *arg)
241 
242 #define tds_thread_create(ret, proc, arg) \
243  FreeTDS_Thread_not_compiled
244 
245 #define tds_thread_join(th, ret) \
246  FreeTDS_Thread_not_compiled
247 
248 #endif
249 
250 #ifdef TDS_HAVE_MUTEX
251 # define tds_cond_init tds_raw_cond_init
252 # define tds_cond_destroy tds_raw_cond_destroy
253 # define tds_cond_signal tds_raw_cond_signal
254 # if !ENABLE_EXTRA_CHECKS
255 # define TDS_MUTEX_INITIALIZER TDS_RAW_MUTEX_INITIALIZER
256 # define tds_mutex tds_raw_mutex
257 # define tds_mutex_lock tds_raw_mutex_lock
258 # define tds_mutex_trylock tds_raw_mutex_trylock
259 # define tds_mutex_unlock tds_raw_mutex_unlock
260 # define tds_mutex_init tds_raw_mutex_init
261 # define tds_mutex_free tds_raw_mutex_free
262 # define tds_cond_wait tds_raw_cond_wait
263 # define tds_cond_timedwait tds_raw_cond_timedwait
264 # else
265 # include <assert.h>
266 
267 typedef struct tds_mutex
268 {
269  tds_raw_mutex mtx;
270  volatile int locked;
271 } tds_mutex;
272 
273 # define TDS_MUTEX_INITIALIZER { TDS_RAW_MUTEX_INITIALIZER, 0 }
274 
275 static inline void tds_mutex_lock(tds_mutex *mtx)
276 {
277  assert(mtx);
278  tds_raw_mutex_lock(&mtx->mtx);
279  assert(!mtx->locked);
280  mtx->locked = 1;
281 }
282 
283 static inline int tds_mutex_trylock(tds_mutex *mtx)
284 {
285  int ret;
286  assert(mtx);
287  ret = tds_raw_mutex_trylock(&mtx->mtx);
288  if (!ret) {
289  assert(!mtx->locked);
290  mtx->locked = 1;
291  }
292  return ret;
293 }
294 
295 static inline void tds_mutex_unlock(tds_mutex *mtx)
296 {
297  assert(mtx && mtx->locked);
298  mtx->locked = 0;
299  tds_raw_mutex_unlock(&mtx->mtx);
300 }
301 
302 static inline int tds_mutex_init(tds_mutex *mtx)
303 {
304  mtx->locked = 0;
305  return tds_raw_mutex_init(&mtx->mtx);
306 }
307 
308 static inline void tds_mutex_free(tds_mutex *mtx)
309 {
310  assert(mtx && !mtx->locked);
311  tds_raw_mutex_free(&mtx->mtx);
312 }
313 
314 static inline int tds_cond_wait(tds_condition *cond, tds_mutex *mtx)
315 {
316  int ret;
317  assert(mtx && mtx->locked);
318  mtx->locked = 0;
319  ret = tds_raw_cond_wait(cond, &mtx->mtx);
320  mtx->locked = 1;
321  return ret;
322 }
323 
324 static inline int tds_cond_timedwait(tds_condition *cond, tds_mutex *mtx, int timeout_sec)
325 {
326  int ret;
327  assert(mtx && mtx->locked);
328  mtx->locked = 0;
329  ret = tds_raw_cond_timedwait(cond, &mtx->mtx, timeout_sec);
330  mtx->locked = 1;
331  return ret;
332 }
333 
334 # endif
335 #endif
336 
337 #endif
Definition: ptw32_MCS_lock.c:97
Definition: thread.h:215
Definition: thread.h:235
Definition: thread.h:188