1
by brian
clean slate |
1 |
/* Copyright (C) 2000 MySQL AB
|
2 |
||
3 |
This program is free software; you can redistribute it and/or modify
|
|
4 |
it under the terms of the GNU General Public License as published by
|
|
5 |
the Free Software Foundation; version 2 of the License.
|
|
6 |
||
7 |
This program is distributed in the hope that it will be useful,
|
|
8 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10 |
GNU General Public License for more details.
|
|
11 |
||
12 |
You should have received a copy of the GNU General Public License
|
|
13 |
along with this program; if not, write to the Free Software
|
|
14 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
15 |
||
16 |
/* Defines to make different thread packages compatible */
|
|
17 |
||
18 |
#ifndef _my_pthread_h
|
|
19 |
#define _my_pthread_h
|
|
20 |
||
21 |
#ifndef ETIME
|
|
22 |
#define ETIME ETIMEDOUT /* For FreeBSD */ |
|
23 |
#endif
|
|
24 |
||
25 |
#ifdef __cplusplus
|
|
26 |
#define EXTERNC extern "C"
|
|
27 |
extern "C" { |
|
28 |
#else
|
|
29 |
#define EXTERNC
|
|
30 |
#endif /* __cplusplus */ |
|
31 |
||
32 |
#include <pthread.h> |
|
33 |
#ifndef _REENTRANT
|
|
34 |
#define _REENTRANT
|
|
35 |
#endif
|
|
36 |
#ifdef HAVE_SCHED_H
|
|
37 |
#include <sched.h> |
|
38 |
#endif
|
|
39 |
#ifdef HAVE_SYNCH_H
|
|
40 |
#include <synch.h> |
|
41 |
#endif
|
|
42 |
||
43 |
#define pthread_key(T,V) pthread_key_t V
|
|
44 |
#define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,(V))
|
|
45 |
#define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,(void*) (V))
|
|
46 |
#define pthread_detach_this_thread()
|
|
47 |
#define pthread_handler_t EXTERNC void *
|
|
48 |
typedef void *(* pthread_handler)(void *); |
|
49 |
||
50 |
/* Test first for RTS or FSU threads */
|
|
51 |
||
52 |
#if defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM)
|
|
53 |
#define HAVE_rts_threads
|
|
54 |
extern int my_pthread_create_detached; |
|
55 |
#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
|
|
56 |
#define PTHREAD_CREATE_DETACHED &my_pthread_create_detached
|
|
57 |
#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_GLOBAL
|
|
58 |
#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_LOCAL
|
|
59 |
#define USE_ALARM_THREAD
|
|
60 |
#endif /* defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) */ |
|
61 |
||
62 |
#ifndef HAVE_NONPOSIX_SIGWAIT
|
|
63 |
#define my_sigwait(A,B) sigwait((A),(B))
|
|
64 |
#else
|
|
65 |
int my_sigwait(const sigset_t *set,int *sig); |
|
66 |
#endif
|
|
67 |
||
68 |
#ifdef HAVE_NONPOSIX_PTHREAD_MUTEX_INIT
|
|
69 |
#define pthread_mutex_init(a,b) my_pthread_mutex_init((a),(b))
|
|
70 |
extern int my_pthread_mutex_init(pthread_mutex_t *mp, |
|
71 |
const pthread_mutexattr_t *attr); |
|
72 |
#define pthread_cond_init(a,b) my_pthread_cond_init((a),(b))
|
|
73 |
extern int my_pthread_cond_init(pthread_cond_t *mp, |
|
74 |
const pthread_condattr_t *attr); |
|
75 |
#endif /* HAVE_NONPOSIX_PTHREAD_MUTEX_INIT */ |
|
76 |
||
77 |
#if defined(HAVE_SIGTHREADMASK) && !defined(HAVE_PTHREAD_SIGMASK)
|
|
78 |
#define pthread_sigmask(A,B,C) sigthreadmask((A),(B),(C))
|
|
79 |
#endif
|
|
80 |
||
81 |
#if !defined(HAVE_SIGWAIT) && !defined(HAVE_rts_threads) && !defined(sigwait) && !defined(alpha_linux_port) && !defined(HAVE_NONPOSIX_SIGWAIT)
|
|
82 |
int sigwait(sigset_t *setp, int *sigp); /* Use our implemention */ |
|
83 |
#endif
|
|
84 |
||
85 |
||
86 |
/*
|
|
87 |
We define my_sigset() and use that instead of the system sigset() so that
|
|
88 |
we can favor an implementation based on sigaction(). On some systems, such
|
|
89 |
as Mac OS X, sigset() results in flags such as SA_RESTART being set, and
|
|
90 |
we want to make sure that no such flags are set.
|
|
91 |
*/
|
|
92 |
#if defined(HAVE_SIGACTION) && !defined(my_sigset)
|
|
93 |
#define my_sigset(A,B) do { struct sigaction l_s; sigset_t l_set; int l_rc; \
|
|
94 |
DBUG_ASSERT((A) != 0); \
|
|
95 |
sigemptyset(&l_set); \
|
|
96 |
l_s.sa_handler = (B); \
|
|
97 |
l_s.sa_mask = l_set; \
|
|
98 |
l_s.sa_flags = 0; \
|
|
99 |
l_rc= sigaction((A), &l_s, (struct sigaction *) NULL);\
|
|
100 |
DBUG_ASSERT(l_rc == 0); \
|
|
101 |
} while (0)
|
|
102 |
#elif defined(HAVE_SIGSET) && !defined(my_sigset)
|
|
103 |
#define my_sigset(A,B) sigset((A),(B))
|
|
104 |
#elif !defined(my_sigset)
|
|
105 |
#define my_sigset(A,B) signal((A),(B))
|
|
106 |
#endif
|
|
107 |
||
108 |
#ifndef my_pthread_setprio
|
|
109 |
#if defined(HAVE_PTHREAD_SETPRIO_NP) /* FSU threads */ |
|
110 |
#define my_pthread_setprio(A,B) pthread_setprio_np((A),(B))
|
|
111 |
#elif defined(HAVE_PTHREAD_SETPRIO)
|
|
112 |
#define my_pthread_setprio(A,B) pthread_setprio((A),(B))
|
|
113 |
#else
|
|
114 |
extern void my_pthread_setprio(pthread_t thread_id,int prior); |
|
115 |
#endif
|
|
116 |
#endif
|
|
117 |
||
118 |
#ifndef my_pthread_attr_setprio
|
|
119 |
#ifdef HAVE_PTHREAD_ATTR_SETPRIO
|
|
120 |
#define my_pthread_attr_setprio(A,B) pthread_attr_setprio((A),(B))
|
|
121 |
#else
|
|
122 |
extern void my_pthread_attr_setprio(pthread_attr_t *attr, int priority); |
|
123 |
#endif
|
|
124 |
#endif
|
|
125 |
||
126 |
#if !defined(HAVE_PTHREAD_ATTR_SETSCOPE)
|
|
127 |
#define pthread_attr_setscope(A,B)
|
|
128 |
#endif
|
|
129 |
||
7
by Brian Aker
Further cleanup on pthreads. |
130 |
#if defined(HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT)
|
1
by brian
clean slate |
131 |
extern int my_pthread_cond_timedwait(pthread_cond_t *cond, |
132 |
pthread_mutex_t *mutex, |
|
133 |
struct timespec *abstime); |
|
134 |
#define pthread_cond_timedwait(A,B,C) my_pthread_cond_timedwait((A),(B),(C))
|
|
135 |
#endif
|
|
136 |
||
137 |
/* FSU THREADS */
|
|
138 |
#if !defined(HAVE_PTHREAD_KEY_DELETE) && !defined(pthread_key_delete)
|
|
139 |
#define pthread_key_delete(A) pthread_dummy(0)
|
|
140 |
#endif
|
|
141 |
||
142 |
#ifdef HAVE_CTHREADS_WRAPPER /* For MacOSX */ |
|
143 |
#define pthread_cond_destroy(A) pthread_dummy(0)
|
|
144 |
#define pthread_mutex_destroy(A) pthread_dummy(0)
|
|
145 |
#define pthread_attr_delete(A) pthread_dummy(0)
|
|
146 |
#define pthread_condattr_delete(A) pthread_dummy(0)
|
|
147 |
#define pthread_attr_setstacksize(A,B) pthread_dummy(0)
|
|
148 |
#define pthread_equal(A,B) ((A) == (B))
|
|
149 |
#define pthread_cond_timedwait(a,b,c) pthread_cond_wait((a),(b))
|
|
150 |
#define pthread_attr_init(A) pthread_attr_create(A)
|
|
151 |
#define pthread_attr_destroy(A) pthread_attr_delete(A)
|
|
152 |
#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
|
|
153 |
#define pthread_create(A,B,C,D) pthread_create((A),*(B),(C),(D))
|
|
154 |
#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
|
|
155 |
#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH)
|
|
156 |
#undef pthread_detach_this_thread
|
|
157 |
#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); }
|
|
158 |
#endif
|
|
159 |
||
160 |
#ifdef HAVE_DARWIN5_THREADS
|
|
161 |
#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
|
|
162 |
#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH)
|
|
163 |
#define pthread_condattr_init(A) pthread_dummy(0)
|
|
164 |
#define pthread_condattr_destroy(A) pthread_dummy(0)
|
|
165 |
#undef pthread_detach_this_thread
|
|
166 |
#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(tmp); }
|
|
167 |
#endif
|
|
168 |
||
169 |
#if (defined(HAVE_PTHREAD_ATTR_CREATE) && !defined(HAVE_SIGWAIT))
|
|
170 |
/* This is set on AIX_3_2 and Siemens unix (and DEC OSF/1 3.2 too) */
|
|
171 |
#define pthread_key_create(A,B) \
|
|
172 |
pthread_keycreate(A,(B) ?\
|
|
173 |
(pthread_destructor_t) (B) :\
|
|
174 |
(pthread_destructor_t) pthread_dummy)
|
|
175 |
#define pthread_attr_init(A) pthread_attr_create(A)
|
|
176 |
#define pthread_attr_destroy(A) pthread_attr_delete(A)
|
|
177 |
#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
|
|
178 |
#define pthread_create(A,B,C,D) pthread_create((A),*(B),(C),(D))
|
|
179 |
#ifndef pthread_sigmask
|
|
180 |
#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
|
|
181 |
#endif
|
|
182 |
#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH)
|
|
183 |
#undef pthread_detach_this_thread
|
|
184 |
#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); }
|
|
185 |
#else
|
|
186 |
#define HAVE_PTHREAD_KILL
|
|
187 |
#endif
|
|
188 |
||
189 |
#if defined(HAVE_POSIX1003_4a_MUTEX) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS)
|
|
190 |
#undef pthread_mutex_trylock
|
|
191 |
#define pthread_mutex_trylock(a) my_pthread_mutex_trylock((a))
|
|
192 |
int my_pthread_mutex_trylock(pthread_mutex_t *mutex); |
|
193 |
#endif
|
|
194 |
||
195 |
#if !defined(HAVE_PTHREAD_YIELD_ONE_ARG) && !defined(HAVE_PTHREAD_YIELD_ZERO_ARG)
|
|
196 |
/* no pthread_yield() available */
|
|
197 |
#ifdef HAVE_SCHED_YIELD
|
|
198 |
#define pthread_yield() sched_yield()
|
|
199 |
#elif defined(HAVE_PTHREAD_YIELD_NP) /* can be Mac OS X */ |
|
200 |
#define pthread_yield() pthread_yield_np()
|
|
201 |
#endif
|
|
202 |
#endif
|
|
203 |
||
204 |
/*
|
|
205 |
The defines set_timespec and set_timespec_nsec should be used
|
|
206 |
for calculating an absolute time at which
|
|
207 |
pthread_cond_timedwait should timeout
|
|
208 |
*/
|
|
209 |
#ifdef HAVE_TIMESPEC_TS_SEC
|
|
210 |
#ifndef set_timespec
|
|
211 |
#define set_timespec(ABSTIME,SEC) \
|
|
212 |
{ \
|
|
213 |
(ABSTIME).ts_sec=time(0) + (time_t) (SEC); \
|
|
214 |
(ABSTIME).ts_nsec=0; \
|
|
215 |
}
|
|
216 |
#endif /* !set_timespec */ |
|
217 |
#ifndef set_timespec_nsec
|
|
218 |
#define set_timespec_nsec(ABSTIME,NSEC) \
|
|
219 |
{ \
|
|
220 |
ulonglong now= my_getsystime() + (NSEC/100); \
|
|
80.1.1
by Brian Aker
LL() cleanup |
221 |
(ABSTIME).ts_sec= (now / 10000000ULL); \
|
222 |
(ABSTIME).ts_nsec= (now % 10000000ULL * 100 + ((NSEC) % 100)); \
|
|
1
by brian
clean slate |
223 |
}
|
224 |
#endif /* !set_timespec_nsec */ |
|
225 |
#else
|
|
226 |
#ifndef set_timespec
|
|
227 |
#define set_timespec(ABSTIME,SEC) \
|
|
228 |
{\
|
|
229 |
struct timeval tv;\
|
|
230 |
gettimeofday(&tv,0);\
|
|
231 |
(ABSTIME).tv_sec=tv.tv_sec+(time_t) (SEC);\
|
|
232 |
(ABSTIME).tv_nsec=tv.tv_usec*1000;\
|
|
233 |
}
|
|
234 |
#endif /* !set_timespec */ |
|
235 |
#ifndef set_timespec_nsec
|
|
236 |
#define set_timespec_nsec(ABSTIME,NSEC) \
|
|
237 |
{\
|
|
238 |
ulonglong now= my_getsystime() + (NSEC/100); \
|
|
80.1.1
by Brian Aker
LL() cleanup |
239 |
(ABSTIME).tv_sec= (time_t) (now / 10000000ULL); \
|
240 |
(ABSTIME).tv_nsec= (long) (now % 10000000ULL * 100 + ((NSEC) % 100)); \
|
|
1
by brian
clean slate |
241 |
}
|
242 |
#endif /* !set_timespec_nsec */ |
|
243 |
#endif /* HAVE_TIMESPEC_TS_SEC */ |
|
244 |
||
245 |
/* safe_mutex adds checking to mutex for easier debugging */
|
|
246 |
||
247 |
typedef struct st_safe_mutex_t |
|
248 |
{
|
|
249 |
pthread_mutex_t global,mutex; |
|
250 |
const char *file; |
|
251 |
uint line,count; |
|
252 |
pthread_t thread; |
|
253 |
} safe_mutex_t; |
|
254 |
||
255 |
int safe_mutex_init(safe_mutex_t *mp, const pthread_mutexattr_t *attr, |
|
256 |
const char *file, uint line); |
|
257 |
int safe_mutex_lock(safe_mutex_t *mp, my_bool try_lock, const char *file, uint line); |
|
258 |
int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line); |
|
259 |
int safe_mutex_destroy(safe_mutex_t *mp,const char *file, uint line); |
|
260 |
int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp,const char *file, |
|
261 |
uint line); |
|
262 |
int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp, |
|
263 |
struct timespec *abstime, const char *file, uint line); |
|
264 |
void safe_mutex_global_init(void); |
|
265 |
void safe_mutex_end(FILE *file); |
|
266 |
||
267 |
/* Wrappers if safe mutex is actually used */
|
|
268 |
#define safe_mutex_assert_owner(mp)
|
|
269 |
#define safe_mutex_assert_not_owner(mp)
|
|
270 |
||
7
by Brian Aker
Further cleanup on pthreads. |
271 |
#if defined(MY_PTHREAD_FASTMUTEX)
|
1
by brian
clean slate |
272 |
typedef struct st_my_pthread_fastmutex_t |
273 |
{
|
|
274 |
pthread_mutex_t mutex; |
|
275 |
uint spins; |
|
276 |
} my_pthread_fastmutex_t; |
|
277 |
void fastmutex_global_init(void); |
|
278 |
||
279 |
int my_pthread_fastmutex_init(my_pthread_fastmutex_t *mp, |
|
280 |
const pthread_mutexattr_t *attr); |
|
281 |
int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp); |
|
282 |
||
283 |
#undef pthread_mutex_init
|
|
284 |
#undef pthread_mutex_lock
|
|
285 |
#undef pthread_mutex_unlock
|
|
286 |
#undef pthread_mutex_destroy
|
|
287 |
#undef pthread_mutex_wait
|
|
288 |
#undef pthread_mutex_timedwait
|
|
289 |
#undef pthread_mutex_t
|
|
290 |
#undef pthread_cond_wait
|
|
291 |
#undef pthread_cond_timedwait
|
|
292 |
#undef pthread_mutex_trylock
|
|
293 |
#define pthread_mutex_init(A,B) my_pthread_fastmutex_init((A),(B))
|
|
294 |
#define pthread_mutex_lock(A) my_pthread_fastmutex_lock(A)
|
|
295 |
#define pthread_mutex_unlock(A) pthread_mutex_unlock(&(A)->mutex)
|
|
296 |
#define pthread_mutex_destroy(A) pthread_mutex_destroy(&(A)->mutex)
|
|
297 |
#define pthread_cond_wait(A,B) pthread_cond_wait((A),&(B)->mutex)
|
|
298 |
#define pthread_cond_timedwait(A,B,C) pthread_cond_timedwait((A),&(B)->mutex,(C))
|
|
299 |
#define pthread_mutex_trylock(A) pthread_mutex_trylock(&(A)->mutex)
|
|
300 |
#define pthread_mutex_t my_pthread_fastmutex_t
|
|
7
by Brian Aker
Further cleanup on pthreads. |
301 |
#endif /* defined(MY_PTHREAD_FASTMUTEX) */ |
1
by brian
clean slate |
302 |
|
303 |
/* READ-WRITE thread locking */
|
|
304 |
||
305 |
#ifdef HAVE_BROKEN_RWLOCK /* For OpenUnix */ |
|
306 |
#undef HAVE_PTHREAD_RWLOCK_RDLOCK
|
|
307 |
#undef HAVE_RWLOCK_INIT
|
|
308 |
#undef HAVE_RWLOCK_T
|
|
309 |
#endif
|
|
310 |
||
311 |
#if defined(USE_MUTEX_INSTEAD_OF_RW_LOCKS)
|
|
312 |
/* use these defs for simple mutex locking */
|
|
313 |
#define rw_lock_t pthread_mutex_t
|
|
314 |
#define my_rwlock_init(A,B) pthread_mutex_init((A),(B))
|
|
315 |
#define rw_rdlock(A) pthread_mutex_lock((A))
|
|
316 |
#define rw_wrlock(A) pthread_mutex_lock((A))
|
|
317 |
#define rw_tryrdlock(A) pthread_mutex_trylock((A))
|
|
318 |
#define rw_trywrlock(A) pthread_mutex_trylock((A))
|
|
319 |
#define rw_unlock(A) pthread_mutex_unlock((A))
|
|
320 |
#define rwlock_destroy(A) pthread_mutex_destroy((A))
|
|
321 |
#elif defined(HAVE_PTHREAD_RWLOCK_RDLOCK)
|
|
322 |
#define rw_lock_t pthread_rwlock_t
|
|
323 |
#define my_rwlock_init(A,B) pthread_rwlock_init((A),(B))
|
|
324 |
#define rw_rdlock(A) pthread_rwlock_rdlock(A)
|
|
325 |
#define rw_wrlock(A) pthread_rwlock_wrlock(A)
|
|
326 |
#define rw_tryrdlock(A) pthread_rwlock_tryrdlock((A))
|
|
327 |
#define rw_trywrlock(A) pthread_rwlock_trywrlock((A))
|
|
328 |
#define rw_unlock(A) pthread_rwlock_unlock(A)
|
|
329 |
#define rwlock_destroy(A) pthread_rwlock_destroy(A)
|
|
330 |
#elif defined(HAVE_RWLOCK_INIT)
|
|
331 |
#ifdef HAVE_RWLOCK_T /* For example Solaris 2.6-> */ |
|
332 |
#define rw_lock_t rwlock_t
|
|
333 |
#endif
|
|
334 |
#define my_rwlock_init(A,B) rwlock_init((A),USYNC_THREAD,0)
|
|
335 |
#else
|
|
336 |
/* Use our own version of read/write locks */
|
|
337 |
typedef struct _my_rw_lock_t { |
|
338 |
pthread_mutex_t lock; /* lock for structure */ |
|
339 |
pthread_cond_t readers; /* waiting readers */ |
|
340 |
pthread_cond_t writers; /* waiting writers */ |
|
341 |
int state; /* -1:writer,0:free,>0:readers */ |
|
342 |
int waiters; /* number of waiting writers */ |
|
343 |
} my_rw_lock_t; |
|
344 |
||
345 |
#define rw_lock_t my_rw_lock_t
|
|
346 |
#define rw_rdlock(A) my_rw_rdlock((A))
|
|
347 |
#define rw_wrlock(A) my_rw_wrlock((A))
|
|
348 |
#define rw_tryrdlock(A) my_rw_tryrdlock((A))
|
|
349 |
#define rw_trywrlock(A) my_rw_trywrlock((A))
|
|
350 |
#define rw_unlock(A) my_rw_unlock((A))
|
|
351 |
#define rwlock_destroy(A) my_rwlock_destroy((A))
|
|
352 |
||
353 |
extern int my_rwlock_init(my_rw_lock_t *, void *); |
|
354 |
extern int my_rwlock_destroy(my_rw_lock_t *); |
|
355 |
extern int my_rw_rdlock(my_rw_lock_t *); |
|
356 |
extern int my_rw_wrlock(my_rw_lock_t *); |
|
357 |
extern int my_rw_unlock(my_rw_lock_t *); |
|
358 |
extern int my_rw_tryrdlock(my_rw_lock_t *); |
|
359 |
extern int my_rw_trywrlock(my_rw_lock_t *); |
|
360 |
#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */ |
|
361 |
||
362 |
#ifndef HAVE_THR_SETCONCURRENCY
|
|
363 |
#define thr_setconcurrency(A) pthread_dummy(0)
|
|
364 |
#endif
|
|
365 |
#if !defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && ! defined(pthread_attr_setstacksize)
|
|
366 |
#define pthread_attr_setstacksize(A,B) pthread_dummy(0)
|
|
367 |
#endif
|
|
368 |
||
369 |
/* Define mutex types, see my_thr_init.c */
|
|
370 |
#define MY_MUTEX_INIT_SLOW NULL
|
|
371 |
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
|
|
372 |
extern pthread_mutexattr_t my_fast_mutexattr; |
|
373 |
#define MY_MUTEX_INIT_FAST &my_fast_mutexattr
|
|
374 |
#else
|
|
375 |
#define MY_MUTEX_INIT_FAST NULL
|
|
376 |
#endif
|
|
377 |
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
|
|
378 |
extern pthread_mutexattr_t my_errorcheck_mutexattr; |
|
379 |
#define MY_MUTEX_INIT_ERRCHK &my_errorcheck_mutexattr
|
|
380 |
#else
|
|
381 |
#define MY_MUTEX_INIT_ERRCHK NULL
|
|
382 |
#endif
|
|
383 |
||
384 |
#ifndef ESRCH
|
|
385 |
/* Define it to something */
|
|
386 |
#define ESRCH 1
|
|
387 |
#endif
|
|
388 |
||
389 |
typedef ulong my_thread_id; |
|
390 |
||
391 |
extern my_bool my_thread_global_init(void); |
|
392 |
extern void my_thread_global_end(void); |
|
393 |
extern my_bool my_thread_init(void); |
|
394 |
extern void my_thread_end(void); |
|
395 |
extern const char *my_thread_name(void); |
|
396 |
extern my_thread_id my_thread_dbug_id(void); |
|
397 |
||
398 |
/* All thread specific variables are in the following struct */
|
|
399 |
||
400 |
#define THREAD_NAME_SIZE 10
|
|
401 |
#ifndef DEFAULT_THREAD_STACK
|
|
402 |
#if SIZEOF_CHARP > 4
|
|
403 |
/*
|
|
404 |
MySQL can survive with 32K, but some glibc libraries require > 128K stack
|
|
405 |
To resolve hostnames. Also recursive stored procedures needs stack.
|
|
406 |
*/
|
|
407 |
#define DEFAULT_THREAD_STACK (256*1024L)
|
|
408 |
#else
|
|
409 |
#define DEFAULT_THREAD_STACK (192*1024)
|
|
410 |
#endif
|
|
411 |
#endif
|
|
412 |
||
413 |
struct st_my_thread_var |
|
414 |
{
|
|
415 |
pthread_cond_t suspend; |
|
416 |
pthread_mutex_t mutex; |
|
417 |
pthread_mutex_t * volatile current_mutex; |
|
418 |
pthread_cond_t * volatile current_cond; |
|
419 |
pthread_t pthread_self; |
|
420 |
my_thread_id id; |
|
421 |
int cmp_length; |
|
422 |
int volatile abort; |
|
423 |
my_bool init; |
|
424 |
struct st_my_thread_var *next,**prev; |
|
425 |
void *opt_info; |
|
426 |
#ifndef DBUG_OFF
|
|
427 |
void *dbug; |
|
428 |
char name[THREAD_NAME_SIZE+1]; |
|
429 |
#endif
|
|
430 |
};
|
|
431 |
||
432 |
extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const)); |
|
433 |
extern uint my_thread_end_wait_time; |
|
434 |
#define my_thread_var (_my_thread_var())
|
|
435 |
/*
|
|
436 |
Keep track of shutdown,signal, and main threads so that my_end() will not
|
|
437 |
report errors with them
|
|
438 |
*/
|
|
439 |
||
440 |
/* Which kind of thread library is in use */
|
|
441 |
||
442 |
#define THD_LIB_OTHER 1
|
|
443 |
#define THD_LIB_NPTL 2
|
|
444 |
#define THD_LIB_LT 4
|
|
445 |
||
446 |
extern uint thd_lib_detected; |
|
447 |
||
448 |
/*
|
|
449 |
thread_safe_xxx functions are for critical statistic or counters.
|
|
450 |
The implementation is guaranteed to be thread safe, on all platforms.
|
|
451 |
Note that the calling code should *not* assume the counter is protected
|
|
452 |
by the mutex given, as the implementation of these helpers may change
|
|
453 |
to use my_atomic operations instead.
|
|
454 |
*/
|
|
455 |
||
456 |
#ifndef thread_safe_increment
|
|
457 |
#define thread_safe_increment(V,L) \
|
|
458 |
(pthread_mutex_lock((L)), (V)++, pthread_mutex_unlock((L)))
|
|
459 |
#define thread_safe_decrement(V,L) \
|
|
460 |
(pthread_mutex_lock((L)), (V)--, pthread_mutex_unlock((L)))
|
|
461 |
#endif
|
|
462 |
||
463 |
#ifndef thread_safe_add
|
|
464 |
#define thread_safe_add(V,C,L) \
|
|
465 |
(pthread_mutex_lock((L)), (V)+=(C), pthread_mutex_unlock((L)))
|
|
466 |
#define thread_safe_sub(V,C,L) \
|
|
467 |
(pthread_mutex_lock((L)), (V)-=(C), pthread_mutex_unlock((L)))
|
|
468 |
#endif
|
|
469 |
||
470 |
/*
|
|
471 |
statistics_xxx functions are for non critical statistic,
|
|
472 |
maintained in global variables.
|
|
473 |
- race conditions can occur, making the result slightly inaccurate.
|
|
474 |
- the lock given is not honored.
|
|
475 |
*/
|
|
476 |
#define statistic_decrement(V,L) (V)--
|
|
477 |
#define statistic_increment(V,L) (V)++
|
|
478 |
#define statistic_add(V,C,L) (V)+=(C)
|
|
479 |
#define statistic_sub(V,C,L) (V)-=(C)
|
|
480 |
||
481 |
/*
|
|
482 |
No locking needed, the counter is owned by the thread
|
|
483 |
*/
|
|
484 |
#define status_var_increment(V) (V)++
|
|
485 |
#define status_var_decrement(V) (V)--
|
|
486 |
#define status_var_add(V,C) (V)+=(C)
|
|
487 |
#define status_var_sub(V,C) (V)-=(C)
|
|
488 |
||
489 |
#ifdef __cplusplus
|
|
490 |
}
|
|
491 |
#endif
|
|
492 |
#endif /* _my_ptread_h */ |