00001
00002
00003
00004
00005
00006
00007
00008 #ifndef PIKE_THREADLIB_H
00009 #define PIKE_THREADLIB_H
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef CONFIGURE_TEST
00019 #include "machine.h"
00020 #include "pike_embed.h"
00021 #include "pike_rusage.h"
00022 #endif
00023
00024
00025
00026
00027 #include <signal.h>
00028
00029 #ifdef HAVE_SYS_TYPES_H
00030
00031 #include <sys/types.h>
00032 #endif
00033
00034 extern int threads_disabled;
00035 PMOD_EXPORT extern ptrdiff_t thread_storage_offset;
00036 PMOD_EXPORT extern struct program *thread_id_prog;
00037
00038 #ifdef PIKE_THREADS
00039
00040
00041 #ifdef fp
00042 #undef fp
00043 #define FRAMEPOINTER_WAS_DEFINED
00044 #endif
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 #ifdef _UNIX_THREADS
00056 #ifdef HAVE_THREAD_H
00057 #define UNIX_THREADS
00058 #include <thread.h>
00059 #undef HAVE_PTHREAD_H
00060 #undef HAVE_THREAD_H
00061 #endif
00062 #endif
00063
00064 #ifdef _MIT_POSIX_THREADS
00065 #define POSIX_THREADS
00066 #include <pthread.h>
00067
00068
00069 #undef func_data
00070
00071
00072 #undef try
00073 #undef except
00074 #undef finally
00075 #undef leave
00076
00077 #undef HAVE_PTHREAD_H
00078 #endif
00079
00080 #ifdef _SGI_SPROC_THREADS
00081
00082 #undef SGI_SPROC_THREADS
00083 #undef HAVE_SPROC
00084 #endif
00085
00086 #ifdef HAVE_THREAD_H
00087 #include <thread.h>
00088 #endif
00089
00090 #ifdef HAVE_MACH_TASK_INFO_H
00091 #include <mach/task_info.h>
00092 #endif
00093 #ifdef HAVE_MACH_TASK_H
00094 #include <mach/task.h>
00095 #endif
00096 #ifdef HAVE_MACH_MACH_INIT_H
00097 #include <mach/mach_init.h>
00098 #endif
00099
00100
00101
00102 #ifdef FRAMEPOINTER_WAS_DEFINED
00103 #define fp Pike_fp
00104 #undef FRAMEPOINTER_WAS_DEFINED
00105 #endif
00106
00107
00108 extern int num_threads;
00109 PMOD_EXPORT extern int live_threads, disallow_live_threads;
00110 struct object;
00111 PMOD_EXPORT extern size_t thread_stack_size;
00112
00113 PMOD_EXPORT void thread_low_error (int errcode, const char *cmd,
00114 const char *fname, int lineno);
00115
00116 #define LOW_THREAD_CHECK_NONZERO_ERROR(CALL) do { \
00117 int thread_errcode_ = (CALL); \
00118 if (thread_errcode_) \
00119 thread_low_error(thread_errcode_, TOSTR(CALL), \
00120 __FILE__, __LINE__); \
00121 } while (0)
00122
00123 #ifdef CONFIGURE_TEST
00124 #define USE_ERRORCHECK_MUTEX 1
00125 #else
00126 #define USE_ERRORCHECK_MUTEX (debug_options & ERRORCHECK_MUTEXES)
00127 #endif
00128
00129 #define DEFINE_MUTEX(X) PIKE_MUTEX_T X
00130
00131
00132 #ifdef POSIX_THREADS
00133
00134 #ifdef HAVE_PTHREAD_ATFORK
00135 #define th_atfork(X,Y,Z) pthread_atfork((X),(Y),(Z))
00136 #define th_atfork_prepare()
00137 #define th_atfork_parent()
00138 #define th_atfork_child()
00139 #else
00140 int th_atfork(void (*)(void),void (*)(void),void (*)(void));
00141 void th_atfork_prepare(void);
00142 void th_atfork_parent(void);
00143 void th_atfork_child(void);
00144 #endif
00145
00146 #define THREAD_T pthread_t
00147 #define PIKE_MUTEX_T pthread_mutex_t
00148
00149 #ifdef PIKE_MUTEX_ERRORCHECK
00150 #define mt_init(X) do { \
00151 if (USE_ERRORCHECK_MUTEX) { \
00152 pthread_mutexattr_t attr; \
00153 pthread_mutexattr_init(&attr); \
00154 pthread_mutexattr_settype(&attr, PIKE_MUTEX_ERRORCHECK); \
00155 pthread_mutex_init((X), &attr); \
00156 } \
00157 else \
00158 pthread_mutex_init((X),0); \
00159 } while (0)
00160 #define DO_IF_PIKE_MUTEX_ERRORCHECK(X) X
00161 #else
00162 #define mt_init(X) pthread_mutex_init((X),0)
00163 #define DO_IF_PIKE_MUTEX_ERRORCHECK(X)
00164 #endif
00165
00166 #ifdef PIKE_MUTEX_RECURSIVE
00167 #define mt_init_recursive(X) \
00168 do{ \
00169 pthread_mutexattr_t attr; \
00170 pthread_mutexattr_init(&attr); \
00171 pthread_mutexattr_settype( \
00172 &attr, \
00173 PIKE_MUTEX_RECURSIVE \
00174 DO_IF_PIKE_MUTEX_ERRORCHECK (| PIKE_MUTEX_ERRORCHECK)); \
00175 pthread_mutex_init((X), &attr); \
00176 }while(0)
00177 #endif
00178
00179 #define mt_lock(X) LOW_THREAD_CHECK_NONZERO_ERROR (pthread_mutex_lock(X))
00180 #define mt_trylock(X) pthread_mutex_trylock(X)
00181 #define mt_unlock(X) LOW_THREAD_CHECK_NONZERO_ERROR (pthread_mutex_unlock(X))
00182 #define mt_destroy(X) LOW_THREAD_CHECK_NONZERO_ERROR (pthread_mutex_destroy(X))
00183
00184
00185
00186
00187
00188
00189 #define th_setconcurrency(X)
00190 #ifdef HAVE_PTHREAD_YIELD
00191 #define low_th_yield() pthread_yield()
00192 #else
00193 #ifdef HAVE_PTHREAD_YIELD_NP
00194
00195 #define low_th_yield() pthread_yield_np()
00196 #endif
00197 #endif
00198 extern pthread_attr_t pattr;
00199 extern pthread_attr_t small_pattr;
00200
00201 #define th_create(ID,fun,arg) pthread_create(ID,&pattr,fun,arg)
00202 #define th_create_small(ID,fun,arg) pthread_create(ID,&small_pattr,fun,arg)
00203 #define th_exit(foo) pthread_exit(foo)
00204 #define th_self() pthread_self()
00205
00206 #define TH_KEY_T pthread_key_t
00207 #define th_key_create pthread_key_create
00208 #define th_setspecific pthread_setspecific
00209 #define th_getspecific pthread_getspecific
00210
00211
00212 #ifdef HAVE_PTHREAD_KILL
00213 #define th_kill(ID,sig) LOW_THREAD_CHECK_NONZERO_ERROR (pthread_kill((ID),(sig)))
00214 #else
00215
00216 #define th_kill(ID,sig)
00217 #endif
00218 #ifdef HAVE_PTHREAD_COND_INIT
00219 #define COND_T pthread_cond_t
00220
00221 #ifdef HAVE_PTHREAD_CONDATTR_DEFAULT_AIX
00222
00223 #define co_init(X) pthread_cond_init((X), &pthread_condattr_default)
00224 #else
00225 #ifdef HAVE_PTHREAD_CONDATTR_DEFAULT
00226
00227 #define co_init(X) pthread_cond_init((X), pthread_condattr_default)
00228 #else
00229 #define co_init(X) pthread_cond_init((X), 0)
00230 #endif
00231 #endif
00232
00233 #define co_wait(COND, MUTEX) pthread_cond_wait((COND), (MUTEX))
00234 #define co_signal(X) pthread_cond_signal(X)
00235 #define co_broadcast(X) pthread_cond_broadcast(X)
00236 #define co_destroy(X) LOW_THREAD_CHECK_NONZERO_ERROR (pthread_cond_destroy(X))
00237 #else
00238 #error No way to make cond-vars
00239 #endif
00240
00241 #endif
00242
00243
00244
00245
00246 #ifdef UNIX_THREADS
00247 #define THREAD_T thread_t
00248 #define PTHREAD_MUTEX_INITIALIZER DEFAULTMUTEX
00249 #define PIKE_MUTEX_T mutex_t
00250 #define mt_init(X) LOW_THREAD_CHECK_NONZERO_ERROR (mutex_init((X),USYNC_THREAD,0))
00251 #define mt_lock(X) LOW_THREAD_CHECK_NONZERO_ERROR (mutex_lock(X))
00252 #define mt_trylock(X) mutex_trylock(X)
00253 #define mt_unlock(X) LOW_THREAD_CHECK_NONZERO_ERROR (mutex_unlock(X))
00254 #define mt_destroy(X) LOW_THREAD_CHECK_NONZERO_ERROR (mutex_destroy(X))
00255
00256 #define th_setconcurrency(X) thr_setconcurrency(X)
00257
00258 #define th_create(ID,fun,arg) thr_create(NULL,thread_stack_size,fun,arg,THR_DAEMON|THR_DETACHED,ID)
00259 #define th_create_small(ID,fun,arg) thr_create(NULL,8192*sizeof(char *),fun,arg,THR_DAEMON|THR_DETACHED,ID)
00260 #define th_exit(foo) thr_exit(foo)
00261 #define th_self() thr_self()
00262 #define th_kill(ID,sig) thr_kill((ID),(sig))
00263 #define low_th_yield() thr_yield()
00264
00265 #define COND_T cond_t
00266 #define co_init(X) cond_init((X),USYNC_THREAD,0)
00267 #define co_wait(COND, MUTEX) cond_wait((COND), (MUTEX))
00268 #define co_signal(X) cond_signal(X)
00269 #define co_broadcast(X) cond_broadcast(X)
00270 #define co_destroy(X) cond_destroy(X)
00271
00272
00273 #endif
00274
00275 #ifdef SGI_SPROC_THREADS
00276
00277
00278
00279
00280 #define THREAD_T int
00281
00282 #define PIKE_MUTEX_T ulock_t
00283 #define mt_init(X) (usinitlock(((*X) = usnewlock())))
00284 #define mt_lock(X) ussetlock(*X)
00285 #define mt_unlock(X) usunsetlock(*X)
00286 #define mt_destroy(X) usfreelock((*X), )
00287
00288 #define th_setconcurrency(X)
00289
00290 #define PIKE_SPROC_FLAGS (PR_SADDR|PR_SFDS|PR_SDIR|PS_SETEXITSIG)
00291 #define th_create(ID, fun, arg) (((*(ID)) = sproc(fun, PIKE_SPROC_FLAGS, arg)) == -1)
00292 #define th_create_small(ID, fun, arg) (((*(ID)) = sproc(fun, PIKE_SPROC_FLAGS, arg)) == -1)
00293 #define th_exit(X) exit(X)
00294 #define th_self() getpid()
00295 #define low_th_yield() sginap(0)
00296 #define th_equal(X,Y) ((X)==(Y))
00297 #define th_hash(X) ((unsigned INT32)(X))
00298
00299
00300
00301
00302
00303 #endif
00304
00305
00306 #ifdef NT_THREADS
00307 #include <process.h>
00308 #include <windows.h>
00309
00310 #define LOW_THREAD_CHECK_ZERO_ERROR(CALL) do { \
00311 if (!(CALL)) \
00312 thread_low_error(GetLastError(), TOSTR(CALL), \
00313 __FILE__, __LINE__); \
00314 } while (0)
00315
00316 #define THREAD_T unsigned
00317 #define th_setconcurrency(X)
00318 #define th_create(ID,fun,arg) low_nt_create_thread(thread_stack_size,fun, arg,ID)
00319 #define th_create_small(ID,fun,arg) low_nt_create_thread(8192*sizeof(char *), fun,arg,ID)
00320 #define TH_RETURN_TYPE unsigned __stdcall
00321 #define TH_STDCALL __stdcall
00322 #define th_exit(foo) _endthreadex(foo)
00323 #define th_self() GetCurrentThreadId()
00324 #define th_destroy(X)
00325 #define low_th_yield() Sleep(0)
00326 #define th_equal(X,Y) ((X)==(Y))
00327 #define th_hash(X) (X)
00328
00329 #define PIKE_MUTEX_T HANDLE
00330 #define mt_init(X) LOW_THREAD_CHECK_ZERO_ERROR ((*(X)=CreateMutex(NULL, 0, NULL)))
00331 #define mt_lock(X) \
00332 LOW_THREAD_CHECK_ZERO_ERROR ( \
00333 WaitForSingleObject(CheckValidHandle(*(X)), INFINITE) == WAIT_OBJECT_0)
00334 #define mt_trylock(X) \
00335 LOW_THREAD_CHECK_ZERO_ERROR ( \
00336 WaitForSingleObject(CheckValidHandle(*(X)), 0) != WAIT_FAILED)
00337 #define mt_unlock(X) LOW_THREAD_CHECK_ZERO_ERROR (ReleaseMutex(CheckValidHandle(*(X))))
00338 #define mt_destroy(X) LOW_THREAD_CHECK_ZERO_ERROR (CloseHandle(CheckValidHandle(*(X))))
00339
00340 #define EVENT_T HANDLE
00341 #define event_init(X) LOW_THREAD_CHECK_ZERO_ERROR (*(X)=CreateEvent(NULL, 1, 0, NULL))
00342 #define event_signal(X) LOW_THREAD_CHECK_ZERO_ERROR (SetEvent(CheckValidHandle(*(X))))
00343 #define event_destroy(X) LOW_THREAD_CHECK_ZERO_ERROR (CloseHandle(CheckValidHandle(*(X))))
00344 #define event_wait(X) \
00345 LOW_THREAD_CHECK_ZERO_ERROR ( \
00346 WaitForSingleObject(CheckValidHandle(*(X)), INFINITE) == WAIT_OBJECT_0)
00347
00348
00349 #define th_atfork(X,Y,Z)
00350 #define th_atfork_prepare()
00351 #define th_atfork_parent()
00352 #define th_atfork_child()
00353
00354 #endif
00355
00356
00357 #if !defined(COND_T) && defined(EVENT_T) && defined(PIKE_MUTEX_T)
00358
00359 #define SIMULATE_COND_WITH_EVENT
00360
00361 struct cond_t_queue
00362 {
00363 struct cond_t_queue *next;
00364 EVENT_T event;
00365 };
00366
00367 typedef struct cond_t_s
00368 {
00369 PIKE_MUTEX_T lock;
00370 struct cond_t_queue *head, *tail;
00371 } COND_T;
00372
00373 #define COND_T struct cond_t_s
00374
00375 #define co_init(X) do { mt_init(& (X)->lock); (X)->head=(X)->tail=0; }while(0)
00376
00377 PMOD_EXPORT int co_wait(COND_T *c, PIKE_MUTEX_T *m);
00378 PMOD_EXPORT int co_signal(COND_T *c);
00379 PMOD_EXPORT int co_broadcast(COND_T *c);
00380 PMOD_EXPORT int co_destroy(COND_T *c);
00381
00382 #endif
00383
00384 #ifndef TH_RETURN_TYPE
00385 #define TH_RETURN_TYPE void *
00386 #endif
00387
00388 #ifndef TH_STDCALL
00389 #define TH_STDCALL
00390 #endif
00391
00392 #ifndef th_destroy
00393 #define th_destroy(X)
00394 #endif
00395
00396 #ifndef low_th_yield
00397 #ifdef HAVE_THR_YIELD
00398 #define low_th_yield() thr_yield()
00399 #else
00400 #define low_th_yield() 0
00401 #define HAVE_NO_YIELD
00402 #endif
00403 #endif
00404
00405 #ifndef th_equal
00406 #define th_equal(X,Y) (!MEMCMP(&(X),&(Y),sizeof(THREAD_T)))
00407 #endif
00408
00409 #ifndef th_hash
00410 #define th_hash(X) hashmem((unsigned char *)&(X),sizeof(THREAD_T), 16)
00411 #endif
00412
00413 #ifndef CONFIGURE_TEST
00414
00415 struct interleave_mutex
00416 {
00417 struct interleave_mutex *next;
00418 struct interleave_mutex *prev;
00419 PIKE_MUTEX_T lock;
00420 };
00421
00422 #define IMUTEX_T struct interleave_mutex
00423
00424 #define DEFINE_IMUTEX(name) IMUTEX_T name
00425
00426
00427
00428
00429
00430 #define LOCK_IMUTEX(im) do { \
00431 if (!threads_disabled) { \
00432 THREADS_FPRINTF(0, (stderr, "Locking IMutex 0x%p...\n", (im))); \
00433 THREADS_ALLOW(); \
00434 mt_lock(&((im)->lock)); \
00435 THREADS_DISALLOW(); \
00436 } \
00437 } while(0)
00438
00439
00440
00441
00442
00443 #define UNLOCK_IMUTEX(im) do { \
00444 if (!threads_disabled) { \
00445 THREADS_FPRINTF(0, (stderr, "Unlocking IMutex 0x%p...\n", (im))); \
00446 mt_unlock(&((im)->lock)); \
00447 } \
00448 } while(0)
00449
00450 extern int th_running;
00451
00452 PMOD_EXPORT extern PIKE_MUTEX_T interpreter_lock;
00453
00454 PMOD_EXPORT extern COND_T live_threads_change;
00455 PMOD_EXPORT extern COND_T threads_disabled_change;
00456
00457 #define THREAD_TABLE_SIZE 127
00458
00459 extern PIKE_MUTEX_T thread_table_lock;
00460 extern struct thread_state *thread_table_chains[THREAD_TABLE_SIZE];
00461 extern int num_pike_threads;
00462
00463
00464 #define FOR_EACH_THREAD(TSTATE, CODE) \
00465 do { \
00466 INT32 __tt_idx__; \
00467 mt_lock( & thread_table_lock ); \
00468 for(__tt_idx__=0; __tt_idx__<THREAD_TABLE_SIZE; __tt_idx__++) \
00469 for(TSTATE=thread_table_chains[__tt_idx__]; \
00470 TSTATE; \
00471 TSTATE=TSTATE->hashlink) { \
00472 CODE; \
00473 } \
00474 mt_unlock( & thread_table_lock ); \
00475 } while (0)
00476
00477 #if !defined(HAVE_GETHRTIME) && \
00478 !(defined(HAVE_MACH_TASK_INFO_H) && defined(TASK_THREAD_TIMES_INFO)) && \
00479 defined(HAVE_CLOCK) && \
00480 !defined(HAVE_NO_YIELD)
00481 #ifdef HAVE_TIME_H
00482 #include <time.h>
00483 #endif
00484 PMOD_EXPORT extern clock_t thread_start_clock;
00485 #define USE_CLOCK_FOR_SLICES
00486 #define DO_IF_USE_CLOCK_FOR_SLICES(X) X
00487 #else
00488 #define DO_IF_USE_CLOCK_FOR_SLICES(X)
00489 #endif
00490
00491
00492
00493
00494
00495 #ifndef VERBOSE_THREADS_DEBUG
00496 #define THREADS_FPRINTF(L,X)
00497 #else
00498 #include <errno.h>
00499 #define THREADS_FPRINTF(L,X) do { \
00500 if ((VERBOSE_THREADS_DEBUG + 0) >= (L)) { \
00501 \
00502 \
00503 int saved_errno__ = errno; \
00504 fprintf X; \
00505 errno = saved_errno__; \
00506 } \
00507 } while(0)
00508 #endif
00509
00510 #if defined(PIKE_DEBUG) && !defined(__NT__)
00511
00512
00513
00514
00515 extern THREAD_T debug_locking_thread;
00516 #define SET_LOCKING_THREAD (debug_locking_thread = th_self(), 0)
00517
00518 #define low_mt_lock_interpreter() \
00519 do {mt_lock(&interpreter_lock); SET_LOCKING_THREAD;} while (0)
00520 #define low_mt_trylock_interpreter() \
00521 (mt_trylock(&interpreter_lock) || SET_LOCKING_THREAD)
00522 #define low_co_wait_interpreter(COND) \
00523 do {co_wait((COND), &interpreter_lock); SET_LOCKING_THREAD;} while (0)
00524
00525 PMOD_EXPORT extern const char msg_ip_not_locked[];
00526 PMOD_EXPORT extern const char msg_ip_not_locked_this_thr[];
00527
00528 #define CHECK_INTERPRETER_LOCK() do { \
00529 if (th_running) { \
00530 THREAD_T self; \
00531 if (!mt_trylock(&interpreter_lock)) \
00532 Pike_fatal(msg_ip_not_locked); \
00533 self = th_self(); \
00534 if (!th_equal(debug_locking_thread, self)) \
00535 Pike_fatal(msg_ip_not_locked_this_thr); \
00536 } \
00537 } while (0)
00538
00539 #else
00540
00541 #define low_mt_lock_interpreter() do {mt_lock(&interpreter_lock);} while (0)
00542 #define low_mt_trylock_interpreter() (mt_trylock(&interpreter_lock))
00543 #define low_co_wait_interpreter(COND) do {co_wait((COND), &interpreter_lock);} while (0)
00544
00545 #endif
00546
00547 static INLINE int threads_disabled_wait(void)
00548 {
00549 do {
00550 THREADS_FPRINTF(1, (stderr, "Thread %d: Wait on threads_disabled\n",
00551 (int) th_self()));
00552 low_co_wait_interpreter(&threads_disabled_change);
00553 } while (threads_disabled);
00554 THREADS_FPRINTF(1, (stderr, "Thread %d: Continue after threads_disabled\n",
00555 (int) th_self()));
00556 return 0;
00557 }
00558
00559 #define mt_lock_interpreter() do { \
00560 low_mt_lock_interpreter(); \
00561 (threads_disabled && threads_disabled_wait()); \
00562 } while (0)
00563 #define mt_trylock_interpreter() \
00564 (low_mt_trylock_interpreter() || (threads_disabled && threads_disabled_wait()))
00565 #define mt_unlock_interpreter() do { \
00566 mt_unlock(&interpreter_lock); \
00567 } while (0)
00568 #define co_wait_interpreter(COND) do { \
00569 low_co_wait_interpreter(COND); \
00570 if (threads_disabled) threads_disabled_wait(); \
00571 } while (0)
00572
00573 #ifdef INTERNAL_PROFILING
00574 PMOD_EXPORT extern unsigned long thread_yields;
00575 #define th_yield() (thread_yields++, low_th_yield())
00576 #else
00577 #define th_yield() low_th_yield()
00578 #endif
00579
00580 #ifdef PIKE_DEBUG
00581 PMOD_EXPORT extern THREAD_T threads_disabled_thread;
00582 #endif
00583
00584 #define INIT_THREAD_STATE(_tmp) do { \
00585 struct thread_state *_th_state = (_tmp); \
00586 Pike_interpreter.thread_state = _th_state; \
00587 _th_state->state = Pike_interpreter; \
00588 _th_state->id = th_self(); \
00589 _th_state->status = THREAD_RUNNING; \
00590 _th_state->swapped = 0; \
00591 DO_IF_DEBUG(_th_state->debug_flags = 0;) \
00592 DO_IF_USE_CLOCK_FOR_SLICES (thread_start_clock = 0); \
00593 } while (0)
00594
00595 #define EXIT_THREAD_STATE(_tmp) do { \
00596 DO_IF_DEBUG (Pike_sp = (struct svalue *) (ptrdiff_t) -1); \
00597 } while (0)
00598
00599 #define SWAP_OUT_THREAD(_tmp) do { \
00600 struct thread_state *_th_state = (_tmp); \
00601 _th_state->state=Pike_interpreter; \
00602 DO_IF_PROFILING({ \
00603 if (!_th_state->swapped) { \
00604 cpu_time_t now = get_cpu_time(); \
00605 DO_IF_PROFILING_DEBUG({ \
00606 fprintf(stderr, "%p: Swap out at: %" PRINT_CPU_TIME \
00607 " unlocked: %" PRINT_CPU_TIME "\n", \
00608 _th_state, now, _th_state->state.unlocked_time); \
00609 }); \
00610 _th_state->state.unlocked_time -= now; \
00611 } \
00612 }); \
00613 _th_state->swapped=1; \
00614 DO_IF_DEBUG ( \
00615 \
00616 Pike_sp = (struct svalue *) (ptrdiff_t) -1; \
00617 Pike_fp = (struct pike_frame *) (ptrdiff_t) -1; \
00618 ); \
00619 \
00620 Pike_interpreter.thread_state = \
00621 (struct thread_state *) (ptrdiff_t) -1; \
00622 } while(0)
00623
00624 PMOD_EXPORT extern const char msg_thr_swapped_over[];
00625
00626 #define SWAP_IN_THREAD(_tmp) do { \
00627 struct thread_state *_th_state = (_tmp); \
00628 DO_IF_DEBUG ( \
00629 if (Pike_sp != (struct svalue *) (ptrdiff_t) -1) \
00630 Pike_fatal (msg_thr_swapped_over, \
00631 (unsigned int) _th_state->id, \
00632 Pike_interpreter.thread_state ? \
00633 (unsigned int) Pike_interpreter.thread_state->id : 0); \
00634 ); \
00635 DO_IF_PROFILING({ \
00636 if (_th_state->swapped) { \
00637 cpu_time_t now = get_cpu_time(); \
00638 DO_IF_DEBUG({ \
00639 DO_IF_PROFILING_DEBUG({ \
00640 fprintf(stderr, "%p: Swap in at: %" PRINT_CPU_TIME \
00641 " unlocked: %" PRINT_CPU_TIME "\n", \
00642 _th_state, now, _th_state->state.unlocked_time); \
00643 }); \
00644 if (now < -Pike_interpreter.unlocked_time) { \
00645 Pike_fatal("Time at swap in is before time at swap out."\
00646 " %" PRINT_CPU_TIME " < %" PRINT_CPU_TIME \
00647 "\n", now, -Pike_interpreter.unlocked_time); \
00648 } \
00649 }); \
00650 _th_state->state.unlocked_time += now; \
00651 } \
00652 }); \
00653 _th_state->swapped=0; \
00654 Pike_interpreter=_th_state->state; \
00655 DO_IF_USE_CLOCK_FOR_SLICES (thread_start_clock = 0); \
00656 } while(0)
00657
00658 #define SWAP_OUT_CURRENT_THREAD() \
00659 do {\
00660 struct thread_state *_tmp = Pike_interpreter.thread_state; \
00661 SWAP_OUT_THREAD(_tmp); \
00662 THREADS_FPRINTF(1, (stderr, "SWAP_OUT_CURRENT_THREAD() %s:%d t:%08x\n", \
00663 __FILE__, __LINE__, (unsigned int)_tmp->id))
00664
00665 extern void debug_list_all_threads(void);
00666 extern void dumpmem(const char *desc, void *x, int size);
00667
00668 PMOD_EXPORT extern const char msg_saved_thread_id[];
00669 PMOD_EXPORT extern const char msg_swap_in_cur_thr_failed[];
00670
00671 #define SWAP_IN_CURRENT_THREAD() \
00672 THREADS_FPRINTF(1, (stderr, "SWAP_IN_CURRENT_THREAD() %s:%d ... t:%08x\n", \
00673 __FILE__, __LINE__, (unsigned int)_tmp->id)); \
00674 SWAP_IN_THREAD(_tmp); \
00675 DO_IF_DEBUG( \
00676 { \
00677 THREAD_T self=th_self(); \
00678 if(MEMCMP( & _tmp->id, &self, sizeof(self))) \
00679 { \
00680 dumpmem(msg_saved_thread_id,&self,sizeof(self)); \
00681 debug_list_all_threads(); \
00682 Pike_fatal(msg_swap_in_cur_thr_failed); \
00683 } \
00684 }) \
00685 } while(0)
00686
00687 #if defined(PIKE_DEBUG) && ! defined(DONT_HIDE_GLOBALS)
00688
00689
00690
00691
00692
00693
00694
00695 #ifdef __GCC__
00696 #ifdef __i386__
00697
00698
00699
00700
00701
00702 #define HIDE_PC \
00703 ;void *pc_=(((unsigned char **)__builtin_frame_address(0))[1]); \
00704 (((unsigned char **)__builtin_frame_address(0))[1])=0
00705 #define REVEAL_PC \
00706 (((unsigned char **)__builtin_frame_address(0))[1])=pc_;
00707 #endif
00708 #endif
00709
00710 #ifndef HIDE_PC
00711 #define HIDE_PC
00712 #define REVEAL_PC
00713 #endif
00714
00715 #define HIDE_GLOBAL_VARIABLES() do { \
00716 int Pike_interpreter =0; \
00717 int pop_n_elems = 0; \
00718 int push_sp_mark = 0, pop_sp_mark = 0, threads_disabled = 1 \
00719 HIDE_PC
00720
00721
00722
00723
00724 #define REVEAL_GLOBAL_VARIABLES() ; REVEAL_PC } while(0)
00725 #else
00726 #define HIDE_GLOBAL_VARIABLES()
00727 #define REVEAL_GLOBAL_VARIABLES()
00728 #endif
00729
00730 #ifdef PIKE_DEBUG
00731
00732 PMOD_EXPORT extern const char msg_thr_not_swapped_in[];
00733 PMOD_EXPORT extern const char msg_cur_thr_not_bound[];
00734 PMOD_EXPORT extern const char msg_thr_states_mixed[];
00735
00736 #define ASSERT_THREAD_SWAPPED_IN() do { \
00737 struct thread_state *_tmp=thread_state_for_id(th_self()); \
00738 if(_tmp->swapped) Pike_fatal(msg_thr_not_swapped_in); \
00739 if (_tmp->debug_flags & THREAD_DEBUG_LOOSE) { \
00740 Pike_fatal(msg_cur_thr_not_bound); \
00741 } \
00742 }while(0)
00743 #define DEBUG_CHECK_THREAD() do { \
00744 struct thread_state *_tmp=thread_state_for_id(th_self()); \
00745 if (_tmp->debug_flags & THREAD_DEBUG_LOOSE) { \
00746 Pike_fatal(msg_cur_thr_not_bound); \
00747 } \
00748 if(_tmp != Pike_interpreter.thread_state) { \
00749 debug_list_all_threads(); \
00750 Pike_fatal(msg_thr_states_mixed); \
00751 } \
00752 } while (0)
00753 #else
00754 #define ASSERT_THREAD_SWAPPED_IN() do { } while (0)
00755 #define DEBUG_CHECK_THREAD() do { } while (0)
00756 #endif
00757
00758 #define THREADSTATE2OBJ(X) ((X)->thread_obj)
00759
00760 #ifdef PIKE_DEBUG
00761 PMOD_EXPORT extern const char msg_thr_allow_in_gc[];
00762 PMOD_EXPORT extern const char msg_thr_allow_in_disabled[];
00763 PMOD_EXPORT extern const char msg_global_dynbuf_in_use[];
00764 extern dynamic_buffer pike_global_buffer;
00765 #if defined(__ia64) && defined(__xlc__)
00766
00767 #define DO_IF_NOT_XLC_IA64(X)
00768 #else
00769 #define DO_IF_NOT_XLC_IA64(X) X
00770 #endif
00771 #endif
00772
00773 PMOD_EXPORT extern int Pike_in_gc;
00774 #define THREADS_ALLOW() do { \
00775 struct thread_state *_tmp = Pike_interpreter.thread_state; \
00776 DO_IF_PIKE_CLEANUP ( \
00777 \
00778 if (_tmp) {) \
00779 DEBUG_CHECK_THREAD(); \
00780 DO_IF_DEBUG({ \
00781 if (Pike_in_gc > 50 && Pike_in_gc < 300) \
00782 Pike_fatal(msg_thr_allow_in_gc, Pike_in_gc); \
00783 if (pike_global_buffer.s.str) \
00784 Pike_fatal(msg_global_dynbuf_in_use); \
00785 }) \
00786 if(num_threads > 1 && !threads_disabled) { \
00787 SWAP_OUT_THREAD(_tmp); \
00788 THREADS_FPRINTF(1, (stderr, "THREADS_ALLOW() %s:%d t:%08x(#%d)\n", \
00789 __FILE__, __LINE__, \
00790 (unsigned int)_tmp->id, live_threads)); \
00791 mt_unlock_interpreter(); \
00792 } else { \
00793 DO_IF_DEBUG( \
00794 THREAD_T self = th_self(); \
00795 if (threads_disabled && \
00796 !th_equal(threads_disabled_thread, self)) \
00797 DO_IF_NOT_XLC_IA64(Pike_fatal(msg_thr_allow_in_disabled, \
00798 self, \
00799 threads_disabled_thread)); \
00800 ); \
00801 } \
00802 DO_IF_DEBUG(_tmp->debug_flags |= THREAD_DEBUG_LOOSE;) \
00803 DO_IF_PIKE_CLEANUP (}) \
00804 HIDE_GLOBAL_VARIABLES()
00805
00806 #define THREADS_DISALLOW() \
00807 REVEAL_GLOBAL_VARIABLES(); \
00808 DO_IF_PIKE_CLEANUP (if (_tmp) {) \
00809 if(_tmp->swapped) { \
00810 low_mt_lock_interpreter(); \
00811 THREADS_FPRINTF(1, (stderr, "THREADS_DISALLOW() %s:%d t:%08x(#%d)\n", \
00812 __FILE__, __LINE__, \
00813 (unsigned int)_tmp->id, live_threads)); \
00814 if (threads_disabled) threads_disabled_wait(); \
00815 SWAP_IN_THREAD(_tmp);\
00816 } \
00817 DO_IF_DEBUG(_tmp->debug_flags &= ~THREAD_DEBUG_LOOSE;) \
00818 DEBUG_CHECK_THREAD(); \
00819 DO_IF_PIKE_CLEANUP (}) \
00820 } while(0)
00821
00822 #define THREADS_ALLOW_UID() do { \
00823 struct thread_state *_tmp_uid = Pike_interpreter.thread_state; \
00824 DO_IF_PIKE_CLEANUP ( \
00825 \
00826 if (_tmp_uid) {) \
00827 DEBUG_CHECK_THREAD(); \
00828 DO_IF_DEBUG({ \
00829 if ((Pike_in_gc > 50) && (Pike_in_gc < 300)) { \
00830 debug_fatal(msg_thr_allow_in_gc, Pike_in_gc); \
00831 if (pike_global_buffer.s.str) \
00832 Pike_fatal(msg_global_dynbuf_in_use); \
00833 } \
00834 }) \
00835 if(num_threads > 1 && !threads_disabled) { \
00836 SWAP_OUT_THREAD(_tmp_uid); \
00837 while (disallow_live_threads) { \
00838 THREADS_FPRINTF(1, (stderr, "THREADS_ALLOW_UID() %s:%d t:%08x(#%d) " \
00839 "live threads disallowed\n", \
00840 __FILE__, __LINE__, \
00841 (unsigned int)_tmp_uid->id, live_threads)); \
00842 co_wait_interpreter(&threads_disabled_change); \
00843 } \
00844 live_threads++; \
00845 THREADS_FPRINTF(1, (stderr, "THREADS_ALLOW_UID() %s:%d t:%08x(#%d)\n", \
00846 __FILE__, __LINE__, \
00847 (unsigned int)_tmp_uid->id, live_threads)); \
00848 mt_unlock_interpreter(); \
00849 } else { \
00850 DO_IF_DEBUG( \
00851 THREAD_T self = th_self(); \
00852 if (threads_disabled && \
00853 !th_equal(threads_disabled_thread, self)) \
00854 DO_IF_NOT_XLC_IA64(Pike_fatal(msg_thr_allow_in_disabled, \
00855 self, \
00856 threads_disabled_thread)); \
00857 ); \
00858 } \
00859 DO_IF_DEBUG(_tmp_uid->debug_flags |= THREAD_DEBUG_LOOSE;) \
00860 DO_IF_PIKE_CLEANUP (}) \
00861 HIDE_GLOBAL_VARIABLES()
00862
00863 #define THREADS_DISALLOW_UID() \
00864 REVEAL_GLOBAL_VARIABLES(); \
00865 DO_IF_PIKE_CLEANUP (if (_tmp_uid) {) \
00866 if(_tmp_uid->swapped) { \
00867 low_mt_lock_interpreter(); \
00868 live_threads--; \
00869 THREADS_FPRINTF(1, (stderr, \
00870 "THREADS_DISALLOW_UID() %s:%d t:%08x(#%d)\n", \
00871 __FILE__, __LINE__, \
00872 (unsigned int)_tmp_uid->id, live_threads)); \
00873 co_broadcast(&live_threads_change); \
00874 if (threads_disabled) threads_disabled_wait(); \
00875 SWAP_IN_THREAD(_tmp_uid);\
00876 } \
00877 DO_IF_DEBUG(_tmp_uid->debug_flags &= ~THREAD_DEBUG_LOOSE;) \
00878 DEBUG_CHECK_THREAD(); \
00879 DO_IF_PIKE_CLEANUP (}) \
00880 } while(0)
00881
00882 #define SWAP_IN_THREAD_IF_REQUIRED() do { \
00883 struct thread_state *_tmp=thread_state_for_id(th_self()); \
00884 HIDE_GLOBAL_VARIABLES(); \
00885 THREADS_DISALLOW()
00886
00887 #endif
00888
00889 #endif
00890
00891 #ifndef PIKE_THREADS
00892
00893 #define th_atfork(X,Y,Z)
00894 #define th_atfork_prepare()
00895 #define th_atfork_parent()
00896 #define th_atfork_child()
00897
00898 #define th_setconcurrency(X)
00899 #define DEFINE_MUTEX(X)
00900 #define DEFINE_IMUTEX(X)
00901 #define init_interleave_mutex(X)
00902 #define LOCK_IMUTEX(X)
00903 #define UNLOCK_IMUTEX(X)
00904 #define mt_init(X)
00905 #define mt_lock(X)
00906 #define mt_unlock(X)
00907 #define mt_destroy(X)
00908 #define THREADS_ALLOW()
00909 #define THREADS_DISALLOW()
00910 #define THREADS_ALLOW_UID()
00911 #define THREADS_DISALLOW_UID()
00912 #define HIDE_GLOBAL_VARIABLES()
00913 #define REVEAL_GLOBAL_VARIABLES()
00914 #define ASSERT_THREAD_SWAPPED_IN()
00915 #define SWAP_IN_THREAD_IF_REQUIRED()
00916 #define th_init()
00917 #define low_th_init()
00918 #define th_cleanup()
00919 #define th_init_programs()
00920 #define th_self() NULL
00921 #define co_wait(X,Y)
00922 #define co_signal(X)
00923 #define co_broadcast(X)
00924 #define co_destroy(X)
00925
00926 #define low_init_threads_disable()
00927 #define init_threads_disable(X)
00928 #define exit_threads_disable(X)
00929
00930
00931 #endif
00932
00933 #ifndef CHECK_INTERPRETER_LOCK
00934 #define CHECK_INTERPRETER_LOCK() do {} while (0)
00935 #endif
00936
00937 #ifdef __NT__
00938 #if !defined (PIKE_DEBUG) || defined (CONFIGURE_TEST)
00939 #define CheckValidHandle(X) (X)
00940 #else
00941 PMOD_EXPORT HANDLE CheckValidHandle(HANDLE h);
00942 #endif
00943 #endif
00944
00945 #ifndef NO_PIKE_SHORTHAND
00946 #define MUTEX_T PIKE_MUTEX_T
00947 #endif
00948
00949
00950
00951 #ifdef PTHREAD_MUTEX_INITIALIZER
00952 #define STATIC_MUTEX_INIT = PTHREAD_MUTEX_INITIALIZER
00953 #else
00954 #define STATIC_MUTEX_INIT
00955 #endif
00956 #ifdef PTHREAD_COND_INITIALIZER
00957 #define STATIC_COND_INIT = PTHREAD_COND_INITIALIZER
00958 #else
00959 #define STATIC_COND_INIT
00960 #endif
00961
00962 #ifndef THREAD_T_TO_PTR
00963 #ifdef PIKE_THREAD_T_IS_POINTER
00964 #define THREAD_T_TO_PTR(X) ((void *)(X))
00965 #else
00966 #define THREAD_T_TO_PTR(X) ((void *)(ptrdiff_t)(X))
00967 #endif
00968 #endif
00969
00970 #endif