~drizzle-trunk/drizzle/development

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