my_pthread.h 26 KB
Newer Older
Marc Alff's avatar
Marc Alff committed
1
/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
unknown's avatar
unknown committed
2 3 4

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
unknown's avatar
unknown committed
6 7

   This program is distributed in the hope that it will be useful,
unknown's avatar
unknown committed
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
unknown's avatar
unknown committed
9 10 11 12 13 14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
unknown's avatar
unknown committed
15 16 17 18 19 20 21

/* Defines to make different thread packages compatible */

#ifndef _my_pthread_h
#define _my_pthread_h

#ifndef ETIME
22
#define ETIME ETIMEDOUT				/* For FreeBSD */
unknown's avatar
unknown committed
23 24
#endif

unknown's avatar
unknown committed
25
#ifdef  __cplusplus
26
#define EXTERNC extern "C"
27
extern "C" {
28
#else
29
#define EXTERNC
unknown's avatar
unknown committed
30 31
#endif /* __cplusplus */ 

32
#if defined(__WIN__)
unknown's avatar
unknown committed
33
typedef CRITICAL_SECTION pthread_mutex_t;
34
typedef DWORD		 pthread_t;
unknown's avatar
unknown committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
typedef struct thread_attr {
    DWORD dwStackSize ;
    DWORD dwCreatingFlag ;
} pthread_attr_t ;

typedef struct { int dummy; } pthread_condattr_t;

/* Implementation of posix conditions */

typedef struct st_pthread_link {
  DWORD thread_id;
  struct st_pthread_link *next;
} pthread_link;

typedef struct {
  uint32 waiting;
51 52 53 54 55 56 57 58 59 60 61
  CRITICAL_SECTION lock_waiting;
 
  enum {
    SIGNAL= 0,
    BROADCAST= 1,
    MAX_EVENTS= 2
  } EVENTS;

  HANDLE events[MAX_EVENTS];
  HANDLE broadcast_block_event;

unknown's avatar
unknown committed
62 63 64
} pthread_cond_t;


65
typedef int pthread_mutexattr_t;
66
#define pthread_self() GetCurrentThreadId()
67
#define pthread_handler_t EXTERNC void * __cdecl
68
typedef void * (__cdecl *pthread_handler)(void *);
unknown's avatar
unknown committed
69

70 71 72 73 74
typedef volatile LONG my_pthread_once_t;
#define MY_PTHREAD_ONCE_INIT  0
#define MY_PTHREAD_ONCE_INPROGRESS 1
#define MY_PTHREAD_ONCE_DONE 2

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
/*
  Struct and macros to be used in combination with the
  windows implementation of pthread_cond_timedwait
*/

/*
   Declare a union to make sure FILETIME is properly aligned
   so it can be used directly as a 64 bit value. The value
   stored is in 100ns units.
 */
 union ft64 {
  FILETIME ft;
  __int64 i64;
 };
struct timespec {
90
  union ft64 tv;
91
  /* The max timeout value in millisecond for pthread_cond_timedwait */
92
  long max_timeout_msec;
93 94
};
#define set_timespec(ABSTIME,SEC) { \
95 96 97
  GetSystemTimeAsFileTime(&((ABSTIME).tv.ft)); \
  (ABSTIME).tv.i64+= (__int64)(SEC)*10000000; \
  (ABSTIME).max_timeout_msec= (long)((SEC)*1000); \
98 99
}
#define set_timespec_nsec(ABSTIME,NSEC) { \
100 101 102
  GetSystemTimeAsFileTime(&((ABSTIME).tv.ft)); \
  (ABSTIME).tv.i64+= (__int64)(NSEC)/100; \
  (ABSTIME).max_timeout_msec= (long)((NSEC)/1000000); \
103 104
}

105 106 107 108 109 110 111 112 113 114 115 116 117
/**
   Compare two timespec structs.

   @retval  1 If TS1 ends after TS2.

   @retval  0 If TS1 is equal to TS2.

   @retval -1 If TS1 ends before TS2.
*/
#define cmp_timespec(TS1, TS2) \
  ((TS1.tv.i64 > TS2.tv.i64) ? 1 : \
   ((TS1.tv.i64 < TS2.tv.i64) ? -1 : 0))

118

119
int win_pthread_mutex_trylock(pthread_mutex_t *mutex);
Marc Alff's avatar
Marc Alff committed
120
int pthread_create(pthread_t *, const pthread_attr_t *, pthread_handler, void *);
unknown's avatar
unknown committed
121 122 123 124 125 126 127 128 129 130
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
			   struct timespec *abstime);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_attr_init(pthread_attr_t *connect_att);
int pthread_attr_setstacksize(pthread_attr_t *connect_att,DWORD stack);
int pthread_attr_destroy(pthread_attr_t *connect_att);
131
int my_pthread_once(my_pthread_once_t *once_control,void (*init_routine)(void));
unknown's avatar
unknown committed
132
struct tm *localtime_r(const time_t *timep,struct tm *tmp);
133 134
struct tm *gmtime_r(const time_t *timep,struct tm *tmp);

135 136
void pthread_exit(void *a);
int pthread_join(pthread_t thread, void **value_ptr);
unknown's avatar
unknown committed
137 138 139


#define ETIMEDOUT 145		    /* Win32 doesn't have this */
unknown's avatar
unknown committed
140 141 142
#define HAVE_LOCALTIME_R		1
#define _REENTRANT			1
#define HAVE_PTHREAD_ATTR_SETSTACKSIZE	1
unknown's avatar
unknown committed
143

144

unknown's avatar
unknown committed
145
#undef SAFE_MUTEX				/* This will cause conflicts */
unknown's avatar
unknown committed
146 147
#define pthread_key(T,V)  DWORD V
#define pthread_key_create(A,B) ((*A=TlsAlloc())==0xFFFFFFFF)
148
#define pthread_key_delete(A) TlsFree(A)
149 150
#define my_pthread_setspecific_ptr(T,V) (!TlsSetValue((T),(V)))
#define pthread_setspecific(A,B) (!TlsSetValue((A),(B)))
unknown's avatar
unknown committed
151 152
#define pthread_getspecific(A) (TlsGetValue(A))
#define my_pthread_getspecific(T,A) ((T) TlsGetValue(A))
unknown's avatar
unknown committed
153
#define my_pthread_getspecific_ptr(T,V) ((T) TlsGetValue(V))
unknown's avatar
unknown committed
154 155

#define pthread_equal(A,B) ((A) == (B))
unknown's avatar
unknown committed
156
#define pthread_mutex_init(A,B)  (InitializeCriticalSection(A),0)
unknown's avatar
unknown committed
157
#define pthread_mutex_lock(A)	 (EnterCriticalSection(A),0)
158
#define pthread_mutex_trylock(A) win_pthread_mutex_trylock((A))
Marc Alff's avatar
Marc Alff committed
159 160
#define pthread_mutex_unlock(A)  (LeaveCriticalSection(A), 0)
#define pthread_mutex_destroy(A) (DeleteCriticalSection(A), 0)
161
#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH)
unknown's avatar
unknown committed
162

163

unknown's avatar
unknown committed
164
/* Dummy defines for easier code */
unknown's avatar
unknown committed
165 166 167 168 169
#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
#define pthread_attr_setscope(A,B)
#define pthread_detach_this_thread()
#define pthread_condattr_init(A)
#define pthread_condattr_destroy(A)
170
#define pthread_yield() SwitchToThread()
unknown's avatar
unknown committed
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192

#else /* Normal threads */

#ifdef HAVE_rts_threads
#define sigwait org_sigwait
#include <signal.h>
#undef sigwait
#endif
#include <pthread.h>
#ifndef _REENTRANT
#define _REENTRANT
#endif
#ifdef HAVE_THR_SETCONCURRENCY
#include <thread.h>			/* Probably solaris */
#endif
#ifdef HAVE_SCHED_H
#include <sched.h>
#endif
#ifdef HAVE_SYNCH_H
#include <synch.h>
#endif

193 194 195 196 197
#ifdef __NETWARE__
void my_pthread_exit(void *status);
#define pthread_exit(A) my_pthread_exit(A)
#endif

unknown's avatar
unknown committed
198 199 200 201
#define pthread_key(T,V) pthread_key_t V
#define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,(V))
#define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,(void*) (V))
#define pthread_detach_this_thread()
202
#define pthread_handler_t EXTERNC void *
unknown's avatar
unknown committed
203 204
typedef void *(* pthread_handler)(void *);

205 206 207 208
#define my_pthread_once_t pthread_once_t
#define MY_PTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
#define my_pthread_once(C,F) pthread_once(C,F)

unknown's avatar
unknown committed
209 210 211 212 213 214 215 216 217 218 219 220 221
/* Test first for RTS or FSU threads */

#if defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM)
#define HAVE_rts_threads
extern int my_pthread_create_detached;
#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
#define PTHREAD_CREATE_DETACHED &my_pthread_create_detached
#define PTHREAD_SCOPE_SYSTEM  PTHREAD_SCOPE_GLOBAL
#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_LOCAL
#define USE_ALARM_THREAD
#endif /* defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) */

#if defined(_BSDI_VERSION) && _BSDI_VERSION < 199910
unknown's avatar
unknown committed
222
int sigwait(sigset_t *set, int *sig);
unknown's avatar
unknown committed
223 224 225 226 227
#endif

#ifndef HAVE_NONPOSIX_SIGWAIT
#define my_sigwait(A,B) sigwait((A),(B))
#else
unknown's avatar
unknown committed
228
int my_sigwait(const sigset_t *set,int *sig);
unknown's avatar
unknown committed
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
#endif

#ifdef HAVE_NONPOSIX_PTHREAD_MUTEX_INIT
#ifndef SAFE_MUTEX
#define pthread_mutex_init(a,b) my_pthread_mutex_init((a),(b))
extern int my_pthread_mutex_init(pthread_mutex_t *mp,
				 const pthread_mutexattr_t *attr);
#endif /* SAFE_MUTEX */
#define pthread_cond_init(a,b) my_pthread_cond_init((a),(b))
extern int my_pthread_cond_init(pthread_cond_t *mp,
				const pthread_condattr_t *attr);
#endif /* HAVE_NONPOSIX_PTHREAD_MUTEX_INIT */

#if defined(HAVE_SIGTHREADMASK) && !defined(HAVE_PTHREAD_SIGMASK)
#define pthread_sigmask(A,B,C) sigthreadmask((A),(B),(C))
#endif

246
#if !defined(HAVE_SIGWAIT) && !defined(HAVE_rts_threads) && !defined(sigwait) && !defined(alpha_linux_port) && !defined(HAVE_NONPOSIX_SIGWAIT) && !defined(HAVE_DEC_3_2_THREADS) && !defined(_AIX)
unknown's avatar
unknown committed
247
int sigwait(sigset_t *setp, int *sigp);		/* Use our implemention */
unknown's avatar
unknown committed
248
#endif
249 250 251 252 253 254 255 256 257


/*
  We define my_sigset() and use that instead of the system sigset() so that
  we can favor an implementation based on sigaction(). On some systems, such
  as Mac OS X, sigset() results in flags such as SA_RESTART being set, and
  we want to make sure that no such flags are set.
*/
#if defined(HAVE_SIGACTION) && !defined(my_sigset)
258 259 260 261 262 263 264 265
#define my_sigset(A,B) do { struct sigaction l_s; sigset_t l_set; int l_rc; \
                            DBUG_ASSERT((A) != 0);                          \
                            sigemptyset(&l_set);                            \
                            l_s.sa_handler = (B);                           \
                            l_s.sa_mask   = l_set;                          \
                            l_s.sa_flags   = 0;                             \
                            l_rc= sigaction((A), &l_s, (struct sigaction *) NULL);\
                            DBUG_ASSERT(l_rc == 0);                         \
266 267 268 269 270
                          } while (0)
#elif defined(HAVE_SIGSET) && !defined(my_sigset)
#define my_sigset(A,B) sigset((A),(B))
#elif !defined(my_sigset)
#define my_sigset(A,B) signal((A),(B))
unknown's avatar
unknown committed
271 272 273 274 275 276 277
#endif

#if !defined(HAVE_PTHREAD_ATTR_SETSCOPE) || defined(HAVE_DEC_3_2_THREADS)
#define pthread_attr_setscope(A,B)
#undef	HAVE_GETHOSTBYADDR_R			/* No definition */
#endif

278
#if defined(HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT) && !defined(SAFE_MUTEX)
279 280 281 282 283 284
extern int my_pthread_cond_timedwait(pthread_cond_t *cond,
				     pthread_mutex_t *mutex,
				     struct timespec *abstime);
#define pthread_cond_timedwait(A,B,C) my_pthread_cond_timedwait((A),(B),(C))
#endif

285
#if !defined( HAVE_NONPOSIX_PTHREAD_GETSPECIFIC)
unknown's avatar
unknown committed
286 287 288 289
#define my_pthread_getspecific(A,B) ((A) pthread_getspecific(B))
#else
#define my_pthread_getspecific(A,B) ((A) my_pthread_getspecific_imp(B))
void *my_pthread_getspecific_imp(pthread_key_t key);
290
#endif
unknown's avatar
unknown committed
291 292 293 294 295

#ifndef HAVE_LOCALTIME_R
struct tm *localtime_r(const time_t *clock, struct tm *res);
#endif

296 297 298 299
#ifndef HAVE_GMTIME_R
struct tm *gmtime_r(const time_t *clock, struct tm *res);
#endif

unknown's avatar
unknown committed
300 301 302 303 304 305
#ifdef HAVE_PTHREAD_CONDATTR_CREATE
/* DCE threads on HPUX 10.20 */
#define pthread_condattr_init pthread_condattr_create
#define pthread_condattr_destroy pthread_condattr_delete
#endif

306 307 308 309 310
/* FSU THREADS */
#if !defined(HAVE_PTHREAD_KEY_DELETE) && !defined(pthread_key_delete)
#define pthread_key_delete(A) pthread_dummy(0)
#endif

unknown's avatar
unknown committed
311 312 313 314 315 316 317 318 319 320 321 322 323
#ifdef HAVE_CTHREADS_WRAPPER			/* For MacOSX */
#define pthread_cond_destroy(A) pthread_dummy(0)
#define pthread_mutex_destroy(A) pthread_dummy(0)
#define pthread_attr_delete(A) pthread_dummy(0)
#define pthread_condattr_delete(A) pthread_dummy(0)
#define pthread_attr_setstacksize(A,B) pthread_dummy(0)
#define pthread_equal(A,B) ((A) == (B))
#define pthread_cond_timedwait(a,b,c) pthread_cond_wait((a),(b))
#define pthread_attr_init(A) pthread_attr_create(A)
#define pthread_attr_destroy(A) pthread_attr_delete(A)
#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
#define pthread_create(A,B,C,D) pthread_create((A),*(B),(C),(D))
#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
324
#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH)
unknown's avatar
unknown committed
325 326 327 328
#undef	pthread_detach_this_thread
#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); }
#endif

329
#ifdef HAVE_DARWIN5_THREADS
unknown's avatar
unknown committed
330
#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
331
#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH)
unknown's avatar
unknown committed
332 333 334
#define pthread_condattr_init(A) pthread_dummy(0)
#define pthread_condattr_destroy(A) pthread_dummy(0)
#undef	pthread_detach_this_thread
335
#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(tmp); }
unknown's avatar
unknown committed
336 337
#endif

unknown's avatar
unknown committed
338 339 340 341 342 343 344 345 346 347 348 349 350
#if ((defined(HAVE_PTHREAD_ATTR_CREATE) && !defined(HAVE_SIGWAIT)) || defined(HAVE_DEC_3_2_THREADS)) && !defined(HAVE_CTHREADS_WRAPPER)
/* This is set on AIX_3_2 and Siemens unix (and DEC OSF/1 3.2 too) */
#define pthread_key_create(A,B) \
		pthread_keycreate(A,(B) ?\
				  (pthread_destructor_t) (B) :\
				  (pthread_destructor_t) pthread_dummy)
#define pthread_attr_init(A) pthread_attr_create(A)
#define pthread_attr_destroy(A) pthread_attr_delete(A)
#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
#define pthread_create(A,B,C,D) pthread_create((A),*(B),(C),(D))
#ifndef pthread_sigmask
#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
#endif
351
#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH)
unknown's avatar
unknown committed
352 353
#undef	pthread_detach_this_thread
#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); }
354
#elif !defined(__NETWARE__) /* HAVE_PTHREAD_ATTR_CREATE && !HAVE_SIGWAIT */
unknown's avatar
unknown committed
355 356 357 358 359
#define HAVE_PTHREAD_KILL
#endif

#endif /* defined(__WIN__) */

unknown's avatar
unknown committed
360
#if defined(HPUX10) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS)
361
#undef pthread_cond_timedwait
unknown's avatar
unknown committed
362
#define pthread_cond_timedwait(a,b,c) my_pthread_cond_timedwait((a),(b),(c))
unknown's avatar
unknown committed
363 364
int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
			      struct timespec *abstime);
365 366
#endif

unknown's avatar
unknown committed
367 368 369
#if defined(HPUX10)
#define pthread_attr_getstacksize(A,B) my_pthread_attr_getstacksize(A,B)
void my_pthread_attr_getstacksize(pthread_attr_t *attrib, size_t *size);
370 371 372 373 374
#endif

#if defined(HAVE_POSIX1003_4a_MUTEX) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS)
#undef pthread_mutex_trylock
#define pthread_mutex_trylock(a) my_pthread_mutex_trylock((a))
unknown's avatar
unknown committed
375
int my_pthread_mutex_trylock(pthread_mutex_t *mutex);
unknown's avatar
unknown committed
376 377
#endif

Marc Alff's avatar
Marc Alff committed
378 379 380 381 382 383 384 385 386 387 388
#if !defined(HAVE_PTHREAD_YIELD_ONE_ARG) && !defined(HAVE_PTHREAD_YIELD_ZERO_ARG)
/* no pthread_yield() available */
#ifdef HAVE_SCHED_YIELD
#define pthread_yield() sched_yield()
#elif defined(HAVE_PTHREAD_YIELD_NP) /* can be Mac OS X */
#define pthread_yield() pthread_yield_np()
#elif defined(HAVE_THR_YIELD)
#define pthread_yield() thr_yield()
#endif
#endif

389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
/*
  The defines set_timespec and set_timespec_nsec should be used
  for calculating an absolute time at which
  pthread_cond_timedwait should timeout
*/
#ifdef HAVE_TIMESPEC_TS_SEC
#ifndef set_timespec
#define set_timespec(ABSTIME,SEC) \
{ \
  (ABSTIME).ts_sec=time(0) + (time_t) (SEC); \
  (ABSTIME).ts_nsec=0; \
}
#endif /* !set_timespec */
#ifndef set_timespec_nsec
#define set_timespec_nsec(ABSTIME,NSEC) \
{ \
  ulonglong now= my_getsystime() + (NSEC/100); \
  (ABSTIME).ts_sec=  (now / ULL(10000000)); \
  (ABSTIME).ts_nsec= (now % ULL(10000000) * 100 + ((NSEC) % 100)); \
}
#endif /* !set_timespec_nsec */
#else
#ifndef set_timespec
#define set_timespec(ABSTIME,SEC) \
{\
  struct timeval tv;\
  gettimeofday(&tv,0);\
  (ABSTIME).tv_sec=tv.tv_sec+(time_t) (SEC);\
  (ABSTIME).tv_nsec=tv.tv_usec*1000;\
}
#endif /* !set_timespec */
#ifndef set_timespec_nsec
#define set_timespec_nsec(ABSTIME,NSEC) \
{\
  ulonglong now= my_getsystime() + (NSEC/100); \
  (ABSTIME).tv_sec=  (time_t) (now / ULL(10000000));                  \
  (ABSTIME).tv_nsec= (long) (now % ULL(10000000) * 100 + ((NSEC) % 100)); \
}
#endif /* !set_timespec_nsec */
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
#endif /* HAVE_TIMESPEC_TS_SEC */

/**
   Compare two timespec structs.

   @retval  1 If TS1 ends after TS2.

   @retval  0 If TS1 is equal to TS2.

   @retval -1 If TS1 ends before TS2.
*/
#ifdef HAVE_TIMESPEC_TS_SEC
#ifndef cmp_timespec
#define cmp_timespec(TS1, TS2) \
  ((TS1.ts_sec > TS2.ts_sec || \
    (TS1.ts_sec == TS2.ts_sec && TS1.ts_nsec > TS2.ts_nsec)) ? 1 : \
   ((TS1.ts_sec < TS2.ts_sec || \
     (TS1.ts_sec == TS2.ts_sec && TS1.ts_nsec < TS2.ts_nsec)) ? -1 : 0))
#endif /* !cmp_timespec */
#else
#ifndef cmp_timespec
#define cmp_timespec(TS1, TS2) \
  ((TS1.tv_sec > TS2.tv_sec || \
    (TS1.tv_sec == TS2.tv_sec && TS1.tv_nsec > TS2.tv_nsec)) ? 1 : \
   ((TS1.tv_sec < TS2.tv_sec || \
     (TS1.tv_sec == TS2.tv_sec && TS1.tv_nsec < TS2.tv_nsec)) ? -1 : 0))
#endif /* !cmp_timespec */
455 456
#endif /* HAVE_TIMESPEC_TS_SEC */

457 458
	/* safe_mutex adds checking to mutex for easier debugging */

unknown's avatar
unknown committed
459 460 461 462
#if defined(__NETWARE__) && !defined(SAFE_MUTEX_DETECT_DESTROY)
#define SAFE_MUTEX_DETECT_DESTROY
#endif

463 464 465
typedef struct st_safe_mutex_t
{
  pthread_mutex_t global,mutex;
unknown's avatar
unknown committed
466
  const char *file;
467 468
  uint line,count;
  pthread_t thread;
unknown's avatar
unknown committed
469 470 471
#ifdef SAFE_MUTEX_DETECT_DESTROY
  struct st_safe_mutex_info_t *info;	/* to track destroying of mutexes */
#endif
472 473
} safe_mutex_t;

unknown's avatar
unknown committed
474 475 476 477 478 479 480 481 482 483 484
#ifdef SAFE_MUTEX_DETECT_DESTROY
/*
  Used to track the destroying of mutexes. This needs to be a seperate
  structure because the safe_mutex_t structure could be freed before
  the mutexes are destroyed.
*/

typedef struct st_safe_mutex_info_t
{
  struct st_safe_mutex_info_t *next;
  struct st_safe_mutex_info_t *prev;
unknown's avatar
unknown committed
485
  const char *init_file;
unknown's avatar
unknown committed
486 487 488 489 490 491
  uint32 init_line;
} safe_mutex_info_t;
#endif /* SAFE_MUTEX_DETECT_DESTROY */

int safe_mutex_init(safe_mutex_t *mp, const pthread_mutexattr_t *attr,
                    const char *file, uint line);
492
int safe_mutex_lock(safe_mutex_t *mp, my_bool try_lock, const char *file, uint line);
493 494 495 496 497 498
int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line);
int safe_mutex_destroy(safe_mutex_t *mp,const char *file, uint line);
int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp,const char *file,
		   uint line);
int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp,
			struct timespec *abstime, const char *file, uint line);
unknown's avatar
unknown committed
499 500
void safe_mutex_global_init(void);
void safe_mutex_end(FILE *file);
501 502 503 504 505 506 507 508 509 510

	/* Wrappers if safe mutex is actually used */
#ifdef SAFE_MUTEX
#undef pthread_mutex_init
#undef pthread_mutex_lock
#undef pthread_mutex_unlock
#undef pthread_mutex_destroy
#undef pthread_mutex_wait
#undef pthread_mutex_timedwait
#undef pthread_mutex_t
unknown's avatar
unknown committed
511 512
#undef pthread_cond_wait
#undef pthread_cond_timedwait
unknown's avatar
unknown committed
513
#undef pthread_mutex_trylock
unknown's avatar
unknown committed
514
#define pthread_mutex_init(A,B) safe_mutex_init((A),(B),__FILE__,__LINE__)
515
#define pthread_mutex_lock(A) safe_mutex_lock((A), FALSE, __FILE__, __LINE__)
516 517 518 519
#define pthread_mutex_unlock(A) safe_mutex_unlock((A),__FILE__,__LINE__)
#define pthread_mutex_destroy(A) safe_mutex_destroy((A),__FILE__,__LINE__)
#define pthread_cond_wait(A,B) safe_cond_wait((A),(B),__FILE__,__LINE__)
#define pthread_cond_timedwait(A,B,C) safe_cond_timedwait((A),(B),(C),__FILE__,__LINE__)
520
#define pthread_mutex_trylock(A) safe_mutex_lock((A), TRUE, __FILE__, __LINE__)
521
#define pthread_mutex_t safe_mutex_t
522 523 524 525 526 527
#define safe_mutex_assert_owner(mp) \
          DBUG_ASSERT((mp)->count > 0 && \
                      pthread_equal(pthread_self(), (mp)->thread))
#define safe_mutex_assert_not_owner(mp) \
          DBUG_ASSERT(! (mp)->count || \
                      ! pthread_equal(pthread_self(), (mp)->thread))
528 529
#else
#define safe_mutex_assert_owner(mp)
530
#define safe_mutex_assert_not_owner(mp)
531 532
#endif /* SAFE_MUTEX */

unknown's avatar
unknown committed
533 534 535 536 537
#if defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX)
typedef struct st_my_pthread_fastmutex_t
{
  pthread_mutex_t mutex;
  uint spins;
538
  uint rng_state;
unknown's avatar
unknown committed
539
} my_pthread_fastmutex_t;
540
void fastmutex_global_init(void);
unknown's avatar
unknown committed
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565

int my_pthread_fastmutex_init(my_pthread_fastmutex_t *mp, 
                              const pthread_mutexattr_t *attr);
int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp);

#undef pthread_mutex_init
#undef pthread_mutex_lock
#undef pthread_mutex_unlock
#undef pthread_mutex_destroy
#undef pthread_mutex_wait
#undef pthread_mutex_timedwait
#undef pthread_mutex_t
#undef pthread_cond_wait
#undef pthread_cond_timedwait
#undef pthread_mutex_trylock
#define pthread_mutex_init(A,B) my_pthread_fastmutex_init((A),(B))
#define pthread_mutex_lock(A) my_pthread_fastmutex_lock(A)
#define pthread_mutex_unlock(A) pthread_mutex_unlock(&(A)->mutex)
#define pthread_mutex_destroy(A) pthread_mutex_destroy(&(A)->mutex)
#define pthread_cond_wait(A,B) pthread_cond_wait((A),&(B)->mutex)
#define pthread_cond_timedwait(A,B,C) pthread_cond_timedwait((A),&(B)->mutex,(C))
#define pthread_mutex_trylock(A) pthread_mutex_trylock(&(A)->mutex)
#define pthread_mutex_t my_pthread_fastmutex_t
#endif /* defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX) */

566
	/* READ-WRITE thread locking */
unknown's avatar
unknown committed
567

568 569 570 571 572 573
#ifdef HAVE_BROKEN_RWLOCK			/* For OpenUnix */
#undef HAVE_PTHREAD_RWLOCK_RDLOCK
#undef HAVE_RWLOCK_INIT
#undef HAVE_RWLOCK_T
#endif

unknown's avatar
unknown committed
574 575 576 577 578 579
#if defined(USE_MUTEX_INSTEAD_OF_RW_LOCKS)
/* use these defs for simple mutex locking */
#define rw_lock_t pthread_mutex_t
#define my_rwlock_init(A,B) pthread_mutex_init((A),(B))
#define rw_rdlock(A) pthread_mutex_lock((A))
#define rw_wrlock(A) pthread_mutex_lock((A))
580 581
#define rw_tryrdlock(A) pthread_mutex_trylock((A))
#define rw_trywrlock(A) pthread_mutex_trylock((A))
unknown's avatar
unknown committed
582 583 584 585 586 587 588
#define rw_unlock(A) pthread_mutex_unlock((A))
#define rwlock_destroy(A) pthread_mutex_destroy((A))
#elif defined(HAVE_PTHREAD_RWLOCK_RDLOCK)
#define rw_lock_t pthread_rwlock_t
#define my_rwlock_init(A,B) pthread_rwlock_init((A),(B))
#define rw_rdlock(A) pthread_rwlock_rdlock(A)
#define rw_wrlock(A) pthread_rwlock_wrlock(A)
unknown's avatar
unknown committed
589 590
#define rw_tryrdlock(A) pthread_rwlock_tryrdlock((A))
#define rw_trywrlock(A) pthread_rwlock_trywrlock((A))
unknown's avatar
unknown committed
591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
#define rw_unlock(A) pthread_rwlock_unlock(A)
#define rwlock_destroy(A) pthread_rwlock_destroy(A)
#elif defined(HAVE_RWLOCK_INIT)
#ifdef HAVE_RWLOCK_T				/* For example Solaris 2.6-> */
#define rw_lock_t rwlock_t
#endif
#define my_rwlock_init(A,B) rwlock_init((A),USYNC_THREAD,0)
#else
/* Use our own version of read/write locks */
typedef struct _my_rw_lock_t {
	pthread_mutex_t lock;		/* lock for structure		*/
	pthread_cond_t	readers;	/* waiting readers		*/
	pthread_cond_t	writers;	/* waiting writers		*/
	int		state;		/* -1:writer,0:free,>0:readers	*/
	int		waiters;	/* number of waiting writers	*/
} my_rw_lock_t;

#define rw_lock_t my_rw_lock_t
#define rw_rdlock(A) my_rw_rdlock((A))
#define rw_wrlock(A) my_rw_wrlock((A))
611 612
#define rw_tryrdlock(A) my_rw_tryrdlock((A))
#define rw_trywrlock(A) my_rw_trywrlock((A))
unknown's avatar
unknown committed
613 614 615
#define rw_unlock(A) my_rw_unlock((A))
#define rwlock_destroy(A) my_rwlock_destroy((A))

unknown's avatar
unknown committed
616 617 618 619 620 621 622
extern int my_rwlock_init(my_rw_lock_t *, void *);
extern int my_rwlock_destroy(my_rw_lock_t *);
extern int my_rw_rdlock(my_rw_lock_t *);
extern int my_rw_wrlock(my_rw_lock_t *);
extern int my_rw_unlock(my_rw_lock_t *);
extern int my_rw_tryrdlock(my_rw_lock_t *);
extern int my_rw_trywrlock(my_rw_lock_t *);
unknown's avatar
unknown committed
623 624 625 626 627 628 629 630 631 632 633
#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */

#define GETHOSTBYADDR_BUFF_SIZE 2048

#ifndef HAVE_THR_SETCONCURRENCY
#define thr_setconcurrency(A) pthread_dummy(0)
#endif
#if !defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && ! defined(pthread_attr_setstacksize)
#define pthread_attr_setstacksize(A,B) pthread_dummy(0)
#endif

634
/* Define mutex types, see my_thr_init.c */
635 636 637 638
#define MY_MUTEX_INIT_SLOW   NULL
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
extern pthread_mutexattr_t my_fast_mutexattr;
#define MY_MUTEX_INIT_FAST &my_fast_mutexattr
639 640
#else
#define MY_MUTEX_INIT_FAST   NULL
641
#endif
642 643 644 645 646 647
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
extern pthread_mutexattr_t my_errorcheck_mutexattr;
#define MY_MUTEX_INIT_ERRCHK &my_errorcheck_mutexattr
#else
#define MY_MUTEX_INIT_ERRCHK   NULL
#endif
648

649 650 651 652 653
#ifndef ESRCH
/* Define it to something */
#define ESRCH 1
#endif

unknown's avatar
unknown committed
654 655
typedef ulong my_thread_id;

unknown's avatar
unknown committed
656
extern my_bool my_thread_global_init(void);
Marc Alff's avatar
Marc Alff committed
657 658
extern my_bool my_thread_basic_global_init(void);
extern void my_thread_basic_global_reinit(void);
unknown's avatar
unknown committed
659 660 661
extern void my_thread_global_end(void);
extern my_bool my_thread_init(void);
extern void my_thread_end(void);
662
extern const char *my_thread_name(void);
unknown's avatar
unknown committed
663
extern my_thread_id my_thread_dbug_id(void);
unknown's avatar
unknown committed
664 665 666 667 668 669
extern int pthread_no_free(void *);
extern int pthread_dummy(int);

/* All thread specific variables are in the following struct */

#define THREAD_NAME_SIZE 10
670
#ifndef DEFAULT_THREAD_STACK
unknown's avatar
unknown committed
671
#if SIZEOF_CHARP > 4
unknown's avatar
unknown committed
672 673
/*
  MySQL can survive with 32K, but some glibc libraries require > 128K stack
unknown's avatar
unknown committed
674
  To resolve hostnames. Also recursive stored procedures needs stack.
unknown's avatar
unknown committed
675
*/
676
#define DEFAULT_THREAD_STACK	(256*1024L)
unknown's avatar
unknown committed
677
#else
unknown's avatar
unknown committed
678
#define DEFAULT_THREAD_STACK	(192*1024)
unknown's avatar
unknown committed
679
#endif
680
#endif
unknown's avatar
unknown committed
681

Marc Alff's avatar
Marc Alff committed
682 683 684 685
#include <mysql/psi/mysql_thread.h>

#define INSTRUMENT_ME 0

unknown's avatar
unknown committed
686 687 688
struct st_my_thread_var
{
  int thr_errno;
Marc Alff's avatar
Marc Alff committed
689 690 691 692
  mysql_cond_t suspend;
  mysql_mutex_t mutex;
  mysql_mutex_t * volatile current_mutex;
  mysql_cond_t * volatile current_cond;
unknown's avatar
unknown committed
693
  pthread_t pthread_self;
unknown's avatar
unknown committed
694
  my_thread_id id;
695
  int cmp_length;
unknown's avatar
unknown committed
696
  int volatile abort;
697
  my_bool init;
698 699
  struct st_my_thread_var *next,**prev;
  void *opt_info;
Marc Alff's avatar
Marc Alff committed
700
  void  *stack_ends_here;
unknown's avatar
unknown committed
701
#ifndef DBUG_OFF
702
  void *dbug;
703
  char name[THREAD_NAME_SIZE+1];
unknown's avatar
unknown committed
704 705 706 707
#endif
};

extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const));
708
extern void **my_thread_var_dbug();
unknown's avatar
unknown committed
709
extern uint my_thread_end_wait_time;
unknown's avatar
unknown committed
710 711
#define my_thread_var (_my_thread_var())
#define my_errno my_thread_var->thr_errno
unknown's avatar
unknown committed
712 713 714 715
/*
  Keep track of shutdown,signal, and main threads so that my_end() will not
  report errors with them
*/
716 717 718 719 720 721 722 723 724

/* Which kind of thread library is in use */

#define THD_LIB_OTHER 1
#define THD_LIB_NPTL  2
#define THD_LIB_LT    4

extern uint thd_lib_detected;

725 726 727 728 729 730 731 732 733 734 735 736
/*
  thread_safe_xxx functions are for critical statistic or counters.
  The implementation is guaranteed to be thread safe, on all platforms.
  Note that the calling code should *not* assume the counter is protected
  by the mutex given, as the implementation of these helpers may change
  to use my_atomic operations instead.
*/

/*
  Warning:
  When compiling without threads, this file is not included.
  See the *other* declarations of thread_safe_xxx in include/my_global.h
unknown's avatar
unknown committed
737 738 739

  Second warning:
  See include/config-win.h, for yet another implementation.
740 741
*/
#ifdef THREAD
unknown's avatar
unknown committed
742
#ifndef thread_safe_increment
unknown's avatar
unknown committed
743
#define thread_safe_increment(V,L) \
Marc Alff's avatar
Marc Alff committed
744
        (mysql_mutex_lock((L)), (V)++, mysql_mutex_unlock((L)))
745
#define thread_safe_decrement(V,L) \
Marc Alff's avatar
Marc Alff committed
746
        (mysql_mutex_lock((L)), (V)--, mysql_mutex_unlock((L)))
unknown's avatar
unknown committed
747 748 749
#endif

#ifndef thread_safe_add
750
#define thread_safe_add(V,C,L) \
Marc Alff's avatar
Marc Alff committed
751
        (mysql_mutex_lock((L)), (V)+=(C), mysql_mutex_unlock((L)))
unknown's avatar
unknown committed
752
#define thread_safe_sub(V,C,L) \
Marc Alff's avatar
Marc Alff committed
753
        (mysql_mutex_lock((L)), (V)-=(C), mysql_mutex_unlock((L)))
754
#endif
unknown's avatar
unknown committed
755
#endif
756 757 758 759 760 761 762 763 764 765 766 767

/*
  statistics_xxx functions are for non critical statistic,
  maintained in global variables.
  When compiling with SAFE_STATISTICS:
  - race conditions can not occur.
  - some locking occurs, which may cause performance degradation.

  When compiling without SAFE_STATISTICS:
  - race conditions can occur, making the result slightly inaccurate.
  - the lock given is not honored.
*/
unknown's avatar
unknown committed
768
#ifdef SAFE_STATISTICS
769 770 771 772
#define statistic_increment(V,L) thread_safe_increment((V),(L))
#define statistic_decrement(V,L) thread_safe_decrement((V),(L))
#define statistic_add(V,C,L)     thread_safe_add((V),(C),(L))
#define statistic_sub(V,C,L)     thread_safe_sub((V),(C),(L))
unknown's avatar
unknown committed
773
#else
774
#define statistic_decrement(V,L) (V)--
unknown's avatar
unknown committed
775 776
#define statistic_increment(V,L) (V)++
#define statistic_add(V,C,L)     (V)+=(C)
777
#define statistic_sub(V,C,L)     (V)-=(C)
unknown's avatar
unknown committed
778
#endif /* SAFE_STATISTICS */
779 780 781 782 783 784 785 786

/*
  No locking needed, the counter is owned by the thread
*/
#define status_var_increment(V) (V)++
#define status_var_decrement(V) (V)--
#define status_var_add(V,C)     (V)+=(C)
#define status_var_sub(V,C)     (V)-=(C)
787

unknown's avatar
unknown committed
788
#ifdef  __cplusplus
789 790
}
#endif
unknown's avatar
unknown committed
791
#endif /* _my_ptread_h */