e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
1b10db2002-10-08Martin Nilsson 
45637c2001-04-07Fredrik Hübinette (Hubbe) #ifndef PIKE_THREADLIB_H #define PIKE_THREADLIB_H /* * This file is for the low-level thread interface functions * 'threads.h' is for anything that concerns the object interface * for pike threads. */
22549b2006-08-02Martin Stjernholm #include "global.h"
1a26b22004-12-30Henrik Grubbström (Grubba) #include "pike_embed.h"
b2630d2004-05-20Henrik Grubbström (Grubba) #include "pike_rusage.h"
092f1a2003-04-02Martin Stjernholm 
45637c2001-04-07Fredrik Hübinette (Hubbe) /* Needed for the sigset_t typedef, which is needed for * the pthread_sigsetmask() prototype on Solaris 2.x. */ #include <signal.h> #ifdef PIKE_THREADS /* The fp macro conflicts with Solaris's <pthread.h>. */ #ifdef fp #undef fp #define FRAMEPOINTER_WAS_DEFINED #endif /* fp */ /* * Decide which type of threads to use * * UNIX_THREADS : Unix international threads * POSIX_THREADS : POSIX standard threads * SGI_SPROC_THREADS : SGI sproc() based threads * NT_THREADS : NT threads */ #ifdef _UNIX_THREADS #ifdef HAVE_THREAD_H #define UNIX_THREADS #include <thread.h> #undef HAVE_PTHREAD_H #undef HAVE_THREAD_H #endif #endif /* _UNIX_THREADS */ #ifdef _MIT_POSIX_THREADS #define POSIX_THREADS #include <pthread.h> /* AIX is *STUPID* - Hubbe */ #undef func_data
8d89962003-03-31Marcus Comstedt /* So is OSF/1 - Marcus */ #undef try #undef except #undef finally #undef leave
45637c2001-04-07Fredrik Hübinette (Hubbe) #undef HAVE_PTHREAD_H #endif /* _MIT_POSIX_THREADS */ #ifdef _SGI_SPROC_THREADS /* Not supported yet */ #undef SGI_SPROC_THREADS #undef HAVE_SPROC #endif /* _SGI_SPROC_THREADS */
ed6cff2001-11-02Martin Stjernholm #ifdef HAVE_THREAD_H #include <thread.h> #endif
8d92312009-03-13Martin Stjernholm #ifdef HAVE_SCHED_H #include <sched.h> #endif
45637c2001-04-07Fredrik Hübinette (Hubbe) 
e7561b2012-04-04Bill Welliver #ifdef USE_DARWIN_THREADS_WITHOUT_MACH /* OSX Threads don't get along with mach headers! */ #else
0da3f72003-11-26Henrik Grubbström (Grubba) #ifdef HAVE_MACH_TASK_INFO_H #include <mach/task_info.h> #endif #ifdef HAVE_MACH_TASK_H #include <mach/task.h> #endif #ifdef HAVE_MACH_MACH_INIT_H #include <mach/mach_init.h> #endif
e7561b2012-04-04Bill Welliver #endif /* USE_DARWIN_THREADS_WITHOUT_MACH */
0da3f72003-11-26Henrik Grubbström (Grubba) 
45637c2001-04-07Fredrik Hübinette (Hubbe) /* Restore the fp macro. */ #ifdef FRAMEPOINTER_WAS_DEFINED #define fp Pike_fp #undef FRAMEPOINTER_WAS_DEFINED #endif /* FRAMEPOINTER_WAS_DEFINED */
91518c2009-03-15Martin Stjernholm PMOD_EXPORT extern int threads_disabled;
fb7d862015-06-01Henrik Grubbström (Grubba) PMOD_EXPORT extern cpu_time_t threads_disabled_acc_time; PMOD_EXPORT extern cpu_time_t threads_disabled_start;
91518c2009-03-15Martin Stjernholm PMOD_EXPORT extern ptrdiff_t thread_storage_offset; PMOD_EXPORT extern struct program *thread_id_prog;
a5a3342006-07-05Martin Stjernholm PMOD_EXPORT extern int num_threads;
45637c2001-04-07Fredrik Hübinette (Hubbe) PMOD_EXPORT extern size_t thread_stack_size;
c432f72003-05-02Henrik Grubbström (Grubba) PMOD_EXPORT void thread_low_error (int errcode, const char *cmd, const char *fname, int lineno);
01185d2003-04-01Martin Stjernholm  #define LOW_THREAD_CHECK_NONZERO_ERROR(CALL) do { \ int thread_errcode_ = (CALL); \
a4b73b2003-05-02Henrik Grubbström (Grubba)  if (thread_errcode_) \
c432f72003-05-02Henrik Grubbström (Grubba)  thread_low_error(thread_errcode_, TOSTR(CALL), \ __FILE__, __LINE__); \
01185d2003-04-01Martin Stjernholm  } while (0)
7d7b022003-04-02Martin Stjernholm #ifdef CONFIGURE_TEST #define USE_ERRORCHECK_MUTEX 1 #else #define USE_ERRORCHECK_MUTEX (debug_options & ERRORCHECK_MUTEXES) #endif
45637c2001-04-07Fredrik Hübinette (Hubbe) #define DEFINE_MUTEX(X) PIKE_MUTEX_T X #ifdef POSIX_THREADS #ifdef HAVE_PTHREAD_ATFORK #define th_atfork(X,Y,Z) pthread_atfork((X),(Y),(Z)) #define th_atfork_prepare() #define th_atfork_parent() #define th_atfork_child() #else int th_atfork(void (*)(void),void (*)(void),void (*)(void)); void th_atfork_prepare(void); void th_atfork_parent(void); void th_atfork_child(void); #endif #define THREAD_T pthread_t #define PIKE_MUTEX_T pthread_mutex_t
01185d2003-04-01Martin Stjernholm #ifdef PIKE_MUTEX_ERRORCHECK #define mt_init(X) do { \
7d7b022003-04-02Martin Stjernholm  if (USE_ERRORCHECK_MUTEX) { \
01185d2003-04-01Martin Stjernholm  pthread_mutexattr_t attr; \ pthread_mutexattr_init(&attr); \ pthread_mutexattr_settype(&attr, PIKE_MUTEX_ERRORCHECK); \ pthread_mutex_init((X), &attr); \ } \ else \ pthread_mutex_init((X),0); \ } while (0) #define DO_IF_PIKE_MUTEX_ERRORCHECK(X) X #else #define mt_init(X) pthread_mutex_init((X),0) #define DO_IF_PIKE_MUTEX_ERRORCHECK(X)
45637c2001-04-07Fredrik Hübinette (Hubbe) #endif
01185d2003-04-01Martin Stjernholm #ifdef PIKE_MUTEX_RECURSIVE
45637c2001-04-07Fredrik Hübinette (Hubbe) #define mt_init_recursive(X) \ do{ \ pthread_mutexattr_t attr; \ pthread_mutexattr_init(&attr); \
01185d2003-04-01Martin Stjernholm  pthread_mutexattr_settype( \ &attr, \ PIKE_MUTEX_RECURSIVE \ DO_IF_PIKE_MUTEX_ERRORCHECK (| PIKE_MUTEX_ERRORCHECK)); \
45637c2001-04-07Fredrik Hübinette (Hubbe)  pthread_mutex_init((X), &attr); \ }while(0) #endif
01185d2003-04-01Martin Stjernholm #define mt_lock(X) LOW_THREAD_CHECK_NONZERO_ERROR (pthread_mutex_lock(X))
45637c2001-04-07Fredrik Hübinette (Hubbe) #define mt_trylock(X) pthread_mutex_trylock(X)
01185d2003-04-01Martin Stjernholm #define mt_unlock(X) LOW_THREAD_CHECK_NONZERO_ERROR (pthread_mutex_unlock(X)) #define mt_destroy(X) LOW_THREAD_CHECK_NONZERO_ERROR (pthread_mutex_destroy(X))
45637c2001-04-07Fredrik Hübinette (Hubbe)  /* SIGH! No setconcurrency in posix threads. This is more or less * needed to make usable multi-threaded programs on solaris machines * with only one CPU. Otherwise, only systemcalls are actually * threaded. */
13670c2015-05-25Martin Nilsson #define th_setconcurrency(X)
8d92312009-03-13Martin Stjernholm #ifdef HAVE_SCHED_YIELD #define low_th_yield() sched_yield() #elif defined (HAVE_PTHREAD_YIELD)
0f65e12002-09-14Martin Stjernholm #define low_th_yield() pthread_yield()
8d92312009-03-13Martin Stjernholm #elif defined (HAVE_PTHREAD_YIELD_NP)
ab91942003-11-25Jonas Wallden /* Some pthread libs define yield as non-portable function. */ #define low_th_yield() pthread_yield_np()
8d92312009-03-13Martin Stjernholm #endif
f031fc2011-05-11Henrik Grubbström (Grubba) PMOD_EXPORT extern pthread_attr_t pattr; PMOD_EXPORT extern pthread_attr_t small_pattr;
45637c2001-04-07Fredrik Hübinette (Hubbe)  #define th_create(ID,fun,arg) pthread_create(ID,&pattr,fun,arg) #define th_create_small(ID,fun,arg) pthread_create(ID,&small_pattr,fun,arg) #define th_exit(foo) pthread_exit(foo) #define th_self() pthread_self() #define TH_KEY_T pthread_key_t #define th_key_create pthread_key_create #define th_setspecific pthread_setspecific #define th_getspecific pthread_getspecific #ifdef HAVE_PTHREAD_KILL
01185d2003-04-01Martin Stjernholm #define th_kill(ID,sig) LOW_THREAD_CHECK_NONZERO_ERROR (pthread_kill((ID),(sig)))
45637c2001-04-07Fredrik Hübinette (Hubbe) #else /* !HAVE_PTHREAD_KILL */
183e1c2004-03-13Jonas Wallden /* MacOS X (aka Darwin) prior to 10.2 doesn't have pthread_kill. */
45637c2001-04-07Fredrik Hübinette (Hubbe) #define th_kill(ID,sig) #endif /* HAVE_PTHREAD_KILL */ #ifdef HAVE_PTHREAD_COND_INIT #define COND_T pthread_cond_t #ifdef HAVE_PTHREAD_CONDATTR_DEFAULT_AIX /* AIX wants the & ... */ #define co_init(X) pthread_cond_init((X), &pthread_condattr_default) #else /* !HAVE_PTHREAD_CONDATTR_DEFAULT_AIX */ #ifdef HAVE_PTHREAD_CONDATTR_DEFAULT /* ... while FreeBSD doesn't. */ #define co_init(X) pthread_cond_init((X), pthread_condattr_default) #else /* !HAVE_PTHREAD_CONDATTR_DEFAULT */ #define co_init(X) pthread_cond_init((X), 0) #endif /* HAVE_PTHREAD_CONDATTR_DEFAULT */ #endif /* HAVE_PTHREAD_CONDATTR_DEFAULT_AIX */ #define co_wait(COND, MUTEX) pthread_cond_wait((COND), (MUTEX)) #define co_signal(X) pthread_cond_signal(X) #define co_broadcast(X) pthread_cond_broadcast(X)
01185d2003-04-01Martin Stjernholm #define co_destroy(X) LOW_THREAD_CHECK_NONZERO_ERROR (pthread_cond_destroy(X))
45637c2001-04-07Fredrik Hübinette (Hubbe) #else #error No way to make cond-vars #endif /* HAVE_PTHREAD_COND_INIT */ #endif /* POSIX_THREADS */ #ifdef UNIX_THREADS
91518c2009-03-15Martin Stjernholm 
45637c2001-04-07Fredrik Hübinette (Hubbe) #define THREAD_T thread_t #define PTHREAD_MUTEX_INITIALIZER DEFAULTMUTEX #define PIKE_MUTEX_T mutex_t
01185d2003-04-01Martin Stjernholm #define mt_init(X) LOW_THREAD_CHECK_NONZERO_ERROR (mutex_init((X),USYNC_THREAD,0)) #define mt_lock(X) LOW_THREAD_CHECK_NONZERO_ERROR (mutex_lock(X))
45637c2001-04-07Fredrik Hübinette (Hubbe) #define mt_trylock(X) mutex_trylock(X)
01185d2003-04-01Martin Stjernholm #define mt_unlock(X) LOW_THREAD_CHECK_NONZERO_ERROR (mutex_unlock(X)) #define mt_destroy(X) LOW_THREAD_CHECK_NONZERO_ERROR (mutex_destroy(X))
45637c2001-04-07Fredrik Hübinette (Hubbe)  #define th_setconcurrency(X) thr_setconcurrency(X) #define th_create(ID,fun,arg) thr_create(NULL,thread_stack_size,fun,arg,THR_DAEMON|THR_DETACHED,ID) #define th_create_small(ID,fun,arg) thr_create(NULL,8192*sizeof(char *),fun,arg,THR_DAEMON|THR_DETACHED,ID) #define th_exit(foo) thr_exit(foo) #define th_self() thr_self() #define th_kill(ID,sig) thr_kill((ID),(sig))
0f65e12002-09-14Martin Stjernholm #define low_th_yield() thr_yield()
45637c2001-04-07Fredrik Hübinette (Hubbe)  #define COND_T cond_t #define co_init(X) cond_init((X),USYNC_THREAD,0) #define co_wait(COND, MUTEX) cond_wait((COND), (MUTEX)) #define co_signal(X) cond_signal(X) #define co_broadcast(X) cond_broadcast(X) #define co_destroy(X) cond_destroy(X) #endif /* UNIX_THREADS */
91518c2009-03-15Martin Stjernholm 
45637c2001-04-07Fredrik Hübinette (Hubbe) #ifdef SGI_SPROC_THREADS /* * Not fully supported yet */ #define THREAD_T int #define PIKE_MUTEX_T ulock_t #define mt_init(X) (usinitlock(((*X) = usnewlock(/*********/)))) #define mt_lock(X) ussetlock(*X) #define mt_unlock(X) usunsetlock(*X) #define mt_destroy(X) usfreelock((*X), /*******/) #define th_setconcurrency(X) /*******/ #define PIKE_SPROC_FLAGS (PR_SADDR|PR_SFDS|PR_SDIR|PS_SETEXITSIG) #define th_create(ID, fun, arg) (((*(ID)) = sproc(fun, PIKE_SPROC_FLAGS, arg)) == -1) #define th_create_small(ID, fun, arg) (((*(ID)) = sproc(fun, PIKE_SPROC_FLAGS, arg)) == -1) #define th_exit(X) exit(X) #define th_self() getpid()
0f65e12002-09-14Martin Stjernholm #define low_th_yield() sginap(0)
45637c2001-04-07Fredrik Hübinette (Hubbe) #define th_equal(X,Y) ((X)==(Y)) #define th_hash(X) ((unsigned INT32)(X)) /* * No cond_vars yet */ #endif /* SGI_SPROC_THREADS */ #ifdef NT_THREADS
91518c2009-03-15Martin Stjernholm 
45637c2001-04-07Fredrik Hübinette (Hubbe) #include <process.h>
01185d2003-04-01Martin Stjernholm #define LOW_THREAD_CHECK_ZERO_ERROR(CALL) do { \
a4b73b2003-05-02Henrik Grubbström (Grubba)  if (!(CALL)) \
c432f72003-05-02Henrik Grubbström (Grubba)  thread_low_error(GetLastError(), TOSTR(CALL), \ __FILE__, __LINE__); \
01185d2003-04-01Martin Stjernholm  } while (0)
45637c2001-04-07Fredrik Hübinette (Hubbe) #define THREAD_T unsigned #define th_setconcurrency(X)
5da06f2003-06-26Tomas Nilsson #define th_create(ID,fun,arg) low_nt_create_thread(thread_stack_size,fun, arg,ID)
45637c2001-04-07Fredrik Hübinette (Hubbe) #define th_create_small(ID,fun,arg) low_nt_create_thread(8192*sizeof(char *), fun,arg,ID) #define TH_RETURN_TYPE unsigned __stdcall #define TH_STDCALL __stdcall #define th_exit(foo) _endthreadex(foo) #define th_self() GetCurrentThreadId() #define th_destroy(X)
0f65e12002-09-14Martin Stjernholm #define low_th_yield() Sleep(0)
45637c2001-04-07Fredrik Hübinette (Hubbe) #define th_equal(X,Y) ((X)==(Y)) #define th_hash(X) (X)
cb06582009-04-25Martin Stjernholm /* FIXME: Check if we can switch to the cheaper CRITICAL_SECTION objects. */
ca39b52010-10-31Martin Stjernholm /* Note that Windows mutexes always allow recursive locking. */
45637c2001-04-07Fredrik Hübinette (Hubbe) #define PIKE_MUTEX_T HANDLE
01185d2003-04-01Martin Stjernholm #define mt_init(X) LOW_THREAD_CHECK_ZERO_ERROR ((*(X)=CreateMutex(NULL, 0, NULL))) #define mt_lock(X) \ LOW_THREAD_CHECK_ZERO_ERROR ( \ WaitForSingleObject(CheckValidHandle(*(X)), INFINITE) == WAIT_OBJECT_0) #define mt_trylock(X) \
c5dfc72010-09-27Henrik Grubbström (Grubba)  (WaitForSingleObject(CheckValidHandle(*(X)), 0) != WAIT_FAILED)
01185d2003-04-01Martin Stjernholm #define mt_unlock(X) LOW_THREAD_CHECK_ZERO_ERROR (ReleaseMutex(CheckValidHandle(*(X)))) #define mt_destroy(X) LOW_THREAD_CHECK_ZERO_ERROR (CloseHandle(CheckValidHandle(*(X))))
45637c2001-04-07Fredrik Hübinette (Hubbe)  #define EVENT_T HANDLE
01185d2003-04-01Martin Stjernholm #define event_init(X) LOW_THREAD_CHECK_ZERO_ERROR (*(X)=CreateEvent(NULL, 1, 0, NULL)) #define event_signal(X) LOW_THREAD_CHECK_ZERO_ERROR (SetEvent(CheckValidHandle(*(X)))) #define event_destroy(X) LOW_THREAD_CHECK_ZERO_ERROR (CloseHandle(CheckValidHandle(*(X)))) #define event_wait(X) \ LOW_THREAD_CHECK_ZERO_ERROR ( \ WaitForSingleObject(CheckValidHandle(*(X)), INFINITE) == WAIT_OBJECT_0)
e7f7052009-01-26Henrik Grubbström (Grubba) #define event_wait_msec(X, MSEC) \ WaitForSingleObject(CheckValidHandle(*(X)), (MSEC))
45637c2001-04-07Fredrik Hübinette (Hubbe) 
12f88f2001-09-20Fredrik Hübinette (Hubbe) /* No fork -- no atfork */ #define th_atfork(X,Y,Z) #define th_atfork_prepare() #define th_atfork_parent() #define th_atfork_child()
cb06582009-04-25Martin Stjernholm /* FIXME: Use windows condition variables if running on Vista or * Windows Server 2008. */
91518c2009-03-15Martin Stjernholm #endif /* NT_THREADS */
45637c2001-04-07Fredrik Hübinette (Hubbe)  #if !defined(COND_T) && defined(EVENT_T) && defined(PIKE_MUTEX_T) #define SIMULATE_COND_WITH_EVENT struct cond_t_queue { struct cond_t_queue *next; EVENT_T event; }; typedef struct cond_t_s { PIKE_MUTEX_T lock; struct cond_t_queue *head, *tail; } COND_T; #define COND_T struct cond_t_s
b810192003-04-02Martin Stjernholm #define co_init(X) do { mt_init(& (X)->lock); (X)->head=(X)->tail=0; }while(0)
45637c2001-04-07Fredrik Hübinette (Hubbe)  PMOD_EXPORT int co_wait(COND_T *c, PIKE_MUTEX_T *m); PMOD_EXPORT int co_signal(COND_T *c); PMOD_EXPORT int co_broadcast(COND_T *c); PMOD_EXPORT int co_destroy(COND_T *c);
91518c2009-03-15Martin Stjernholm #endif /* !COND_T && EVENT_T && PIKE_MUTEX_T */
45637c2001-04-07Fredrik Hübinette (Hubbe) 
83b1842003-02-08Martin Stjernholm #ifndef TH_RETURN_TYPE #define TH_RETURN_TYPE void * #endif #ifndef TH_STDCALL #define TH_STDCALL #endif #ifndef th_destroy #define th_destroy(X) #endif #ifndef low_th_yield #ifdef HAVE_THR_YIELD #define low_th_yield() thr_yield() #else #define low_th_yield() 0 #define HAVE_NO_YIELD #endif #endif #ifndef th_equal
67074e2014-09-03Martin Nilsson #define th_equal(X,Y) (!memcmp(&(X),&(Y),sizeof(THREAD_T)))
83b1842003-02-08Martin Stjernholm #endif #ifndef th_hash #define th_hash(X) hashmem((unsigned char *)&(X),sizeof(THREAD_T), 16) #endif
91518c2009-03-15Martin Stjernholm PMOD_EXPORT int co_wait_timeout(COND_T *c, PIKE_MUTEX_T *m, long s, long nanos);
4a5f542009-01-25Henrik Grubbström (Grubba) 
83b1842003-02-08Martin Stjernholm #ifndef CONFIGURE_TEST
ed6cff2001-11-02Martin Stjernholm  struct interleave_mutex { struct interleave_mutex *next; struct interleave_mutex *prev; PIKE_MUTEX_T lock; }; #define IMUTEX_T struct interleave_mutex #define DEFINE_IMUTEX(name) IMUTEX_T name
91518c2009-03-15Martin Stjernholm PMOD_EXPORT void pike_lock_imutex (IMUTEX_T *im COMMA_DLOC_DECL); PMOD_EXPORT void pike_unlock_imutex (IMUTEX_T *im COMMA_DLOC_DECL);
45637c2001-04-07Fredrik Hübinette (Hubbe) 
91518c2009-03-15Martin Stjernholm /* NOTE: Threads are enabled during the locking operation. */ #define LOCK_IMUTEX(IM) pike_lock_imutex ((IM) COMMA_DLOC)
45637c2001-04-07Fredrik Hübinette (Hubbe) 
91518c2009-03-15Martin Stjernholm /* NOTE: MUST be called in a THREADS_DISALLOW() context. */ #define UNLOCK_IMUTEX(IM) pike_unlock_imutex ((IM) COMMA_DLOC)
245f8b2001-11-01Martin Stjernholm 
f2c01e2003-01-08Martin Stjernholm #define THREAD_TABLE_SIZE 127 /* Totally arbitrary prime */ extern PIKE_MUTEX_T thread_table_lock; extern struct thread_state *thread_table_chains[THREAD_TABLE_SIZE]; extern int num_pike_threads; /* Note: thread_table_lock is held while the code is run. */ #define FOR_EACH_THREAD(TSTATE, CODE) \ do { \ INT32 __tt_idx__; \ mt_lock( & thread_table_lock ); \ for(__tt_idx__=0; __tt_idx__<THREAD_TABLE_SIZE; __tt_idx__++) \ for(TSTATE=thread_table_chains[__tt_idx__]; \ TSTATE; \ TSTATE=TSTATE->hashlink) { \ CODE; \ } \ mt_unlock( & thread_table_lock ); \ } while (0)
91518c2009-03-15Martin Stjernholm PMOD_EXPORT void pike_low_lock_interpreter (DLOC_DECL); PMOD_EXPORT void pike_low_wait_interpreter (COND_T *cond COMMA_DLOC_DECL); PMOD_EXPORT int pike_low_timedwait_interpreter (COND_T *cond, long sec, long nsec COMMA_DLOC_DECL); PMOD_EXPORT void pike_lock_interpreter (DLOC_DECL); PMOD_EXPORT void pike_unlock_interpreter (DLOC_DECL); PMOD_EXPORT void pike_wait_interpreter (COND_T *cond COMMA_DLOC_DECL); PMOD_EXPORT int pike_timedwait_interpreter (COND_T *cond, long sec, long nsec COMMA_DLOC_DECL); #define low_mt_lock_interpreter() pike_low_lock_interpreter (DLOC) #define low_co_wait_interpreter(COND) \ pike_low_wait_interpreter (COND COMMA_DLOC) #define low_co_wait_interpreter_timeout(COND, SEC, NSEC) \ pike_low_timedwait_interpreter (COND, SEC, NSEC COMMA_DLOC) #define mt_lock_interpreter() pike_lock_interpreter (DLOC) #define mt_unlock_interpreter() pike_unlock_interpreter (DLOC) #define co_wait_interpreter(COND) pike_wait_interpreter (COND COMMA_DLOC) #define co_wait_interpreter_timeout(COND, SEC, NSEC) \ pike_timedwait_interpreter (COND, SEC, NSEC COMMA_DLOC)
bc21dc2001-11-01Martin Stjernholm 
0f65e12002-09-14Martin Stjernholm #ifdef INTERNAL_PROFILING PMOD_EXPORT extern unsigned long thread_yields; #define th_yield() (thread_yields++, low_th_yield()) #else #define th_yield() low_th_yield() #endif
91518c2009-03-15Martin Stjernholm PMOD_EXPORT void pike_init_thread_state (struct thread_state *ts); #define INIT_THREAD_STATE(TS) pike_init_thread_state (TS)
b867f92003-02-16Martin Stjernholm #define EXIT_THREAD_STATE(_tmp) do { \ DO_IF_DEBUG (Pike_sp = (struct svalue *) (ptrdiff_t) -1); \ } while (0)
91518c2009-03-15Martin Stjernholm PMOD_EXPORT void pike_swap_out_thread (struct thread_state *ts COMMA_DLOC_DECL); PMOD_EXPORT void pike_swap_in_thread (struct thread_state *ts COMMA_DLOC_DECL); PMOD_EXPORT void pike_swap_in_current_thread (struct thread_state *ts COMMA_DLOC_DECL); #define SWAP_OUT_THREAD(TS) pike_swap_out_thread (TS COMMA_DLOC) #define SWAP_IN_THREAD(TS) pike_swap_in_thread (TS COMMA_DLOC) #define SWAP_OUT_CURRENT_THREAD() \ do { \ struct thread_state *cur_ts__ = Pike_interpreter.thread_state; \ pike_swap_out_thread (cur_ts__ COMMA_DLOC); \ { #define SWAP_IN_CURRENT_THREAD() \ ;} \ pike_swap_in_current_thread (cur_ts__ COMMA_DLOC); \ } while (0) #ifdef PIKE_DEBUG PMOD_EXPORT void debug_list_all_threads(void); #endif
45637c2001-04-07Fredrik Hübinette (Hubbe)  #if defined(PIKE_DEBUG) && ! defined(DONT_HIDE_GLOBALS) /* Note that scalar types are used in place of pointers and vice versa * below. This is intended to cause compiler warnings/errors if * there is an attempt to use the global variables in an unsafe * environment. */
1b4b472001-09-04Fredrik Hübinette (Hubbe)  #ifdef __GCC__ #ifdef __i386__ /* This is a rather drastic measure since it * obliterates backtraces, oh well, gcc doesn't work * very well sometimes anyways... -Hubbe */ #define HIDE_PC \
91518c2009-03-15Martin Stjernholm  void *pc_=(((unsigned char **)__builtin_frame_address(0))[1]); \
1b4b472001-09-04Fredrik Hübinette (Hubbe)  (((unsigned char **)__builtin_frame_address(0))[1])=0 #define REVEAL_PC \ (((unsigned char **)__builtin_frame_address(0))[1])=pc_;
91518c2009-03-15Martin Stjernholm  #endif /* __i386__ */ #endif /* __GCC__ */
1b4b472001-09-04Fredrik Hübinette (Hubbe)  #ifndef HIDE_PC #define HIDE_PC #define REVEAL_PC #endif
91518c2009-03-15Martin Stjernholm #define HIDE_GLOBAL_VARIABLES() do { \
d97eb72011-07-10Henrik Grubbström (Grubba)  int Pike_interpreter_pointer =0; \
91518c2009-03-15Martin Stjernholm  int pop_n_elems = 0; \ int push_sp_mark = 0, pop_sp_mark = 0, threads_disabled = 1; \ HIDE_PC; \ {
d62d252003-02-16Martin Stjernholm  /* Note that the semi-colon below is needed to add an empty statement * in case there is a label before the macro. */
91518c2009-03-15Martin Stjernholm #define REVEAL_GLOBAL_VARIABLES() \ ;} \ REVEAL_PC; \ } while (0)
d62d252003-02-16Martin Stjernholm #else /* PIKE_DEBUG */ #define HIDE_GLOBAL_VARIABLES() #define REVEAL_GLOBAL_VARIABLES() #endif /* PIKE_DEBUG */
b867f92003-02-16Martin Stjernholm #ifdef PIKE_DEBUG
91518c2009-03-15Martin Stjernholm PMOD_EXPORT void pike_assert_thread_swapped_in (DLOC_DECL); PMOD_EXPORT void pike_debug_check_thread (DLOC_DECL); #define ASSERT_THREAD_SWAPPED_IN() pike_assert_thread_swapped_in (DLOC) #define DEBUG_CHECK_THREAD() pike_debug_check_thread (DLOC)
b867f92003-02-16Martin Stjernholm #else #define ASSERT_THREAD_SWAPPED_IN() do { } while (0) #define DEBUG_CHECK_THREAD() do { } while (0) #endif
f862942012-06-02Martin Stjernholm /* THREADS_ALLOW and THREADS_DISALLOW unlocks the interpreter lock so * that other threads may run in the pike interpreter. Must be used * around code that might block, and may be used around code that just * takes a lot of time. Note though in the latter case that the * locking overhead is significant - the work should be on the order * of microseconds or else it might even get slower. * * Between THREADS_ALLOW and THREADS_DISALLOW, you may not change any * data structure that might be accessible by other threads, and you * may not access any data they could possibly change. * * The following rules are just some special cases of the preceding * statement: * * o You may not throw pike exceptions, not even if you catch them * yourself. * o You may not create instances of any pike data type, because that * always implicitly modifies global structures (e.g. the doubly * linked lists that link together all arrays, mappings, multisets, * objects, and programs). * o You may not change the refcount of any pike structure, unless * all its other references are from your own code (see also last * item below). * o If you (prior to THREADS_ALLOW) have added your own ref to some * structure, you can assume that it continues to exist. Refs from * your own stack count in this regard, because you know that they * will remain until THREADS_DISALLOW. Note that even objects are * guaranteed to continue to exist, but they may be destructed at * any time. * o Only immutable data in structs you have refs to may be read, and * nothing may be changed. * o If you before THREADS_ALLOW have created your own instance of * some data type, i.e. so that you got the only ref to it, you can * safely change it. But changes that have effect on global * structures are still verboten - that includes freeing any pike * data type, and calling functions like finish_string_builder, * just to name one. */
b57f5c2009-03-13Martin Stjernholm /* The difference between THREADS_ALLOW and THREADS_ALLOW_UID is that * _disable_threads waits for the latter to hold in * THREADS_DISALLOW_UID before returning. Otoh, THREADS_ALLOW sections * might continue to run when threads are officially disabled. That is * fine as long as they don't have any effect on the process state * that is observable from other threads. Iow, THREADS_ALLOW_UID is * necessary when doing any kind of I/O, calling nonreentrant * functions, or similar. */
91518c2009-03-15Martin Stjernholm PMOD_EXPORT void pike_threads_allow (struct thread_state *ts COMMA_DLOC_DECL); PMOD_EXPORT void pike_threads_disallow (struct thread_state *ts COMMA_DLOC_DECL); PMOD_EXPORT void pike_threads_allow_ext (struct thread_state *ts COMMA_DLOC_DECL); PMOD_EXPORT void pike_threads_disallow_ext (struct thread_state *ts COMMA_DLOC_DECL); #define THREADS_ALLOW() do { \ struct thread_state *cur_ts__ = Pike_interpreter.thread_state; \ pike_threads_allow (cur_ts__ COMMA_DLOC); \ HIDE_GLOBAL_VARIABLES(); \ { #define THREADS_DISALLOW() \ ;} \ REVEAL_GLOBAL_VARIABLES(); \ pike_threads_disallow (cur_ts__ COMMA_DLOC); \ } while (0) #define THREADS_ALLOW_UID() do { \ struct thread_state *cur_ts_ext__ = Pike_interpreter.thread_state; \ pike_threads_allow_ext (cur_ts_ext__ COMMA_DLOC); \ HIDE_GLOBAL_VARIABLES(); \ { #define THREADS_DISALLOW_UID() \ ;} \ REVEAL_GLOBAL_VARIABLES(); \ pike_threads_disallow_ext (cur_ts_ext__ COMMA_DLOC); \ } while (0)
45637c2001-04-07Fredrik Hübinette (Hubbe) 
51d8fc2009-06-22Henrik Grubbström (Grubba) /* FIXME! The macro below leaks live_threads! * Avoid if possible! */
91518c2009-03-15Martin Stjernholm #define SWAP_IN_THREAD_IF_REQUIRED() \ pike_threads_disallow (thread_state_for_id(th_self()) COMMA_DLOC)
45637c2001-04-07Fredrik Hübinette (Hubbe) 
83b1842003-02-08Martin Stjernholm #endif /* !CONFIGURE_TEST */
45637c2001-04-07Fredrik Hübinette (Hubbe) #endif /* PIKE_THREADS */ #ifndef PIKE_THREADS #define th_atfork(X,Y,Z) #define th_atfork_prepare() #define th_atfork_parent() #define th_atfork_child() #define th_setconcurrency(X) #define DEFINE_MUTEX(X) #define DEFINE_IMUTEX(X) #define init_interleave_mutex(X)
d394b62015-07-30Henrik Grubbström (Grubba) #define exit_interleave_mutex(X)
45637c2001-04-07Fredrik Hübinette (Hubbe) #define LOCK_IMUTEX(X) #define UNLOCK_IMUTEX(X) #define mt_init(X) #define mt_lock(X) #define mt_unlock(X) #define mt_destroy(X) #define THREADS_ALLOW() #define THREADS_DISALLOW() #define THREADS_ALLOW_UID() #define THREADS_DISALLOW_UID() #define HIDE_GLOBAL_VARIABLES() #define REVEAL_GLOBAL_VARIABLES() #define ASSERT_THREAD_SWAPPED_IN() #define SWAP_IN_THREAD_IF_REQUIRED() #define th_init() #define low_th_init() #define th_cleanup() #define th_init_programs()
d2361e2003-06-30Martin Stjernholm #define th_self() NULL
bc21dc2001-11-01Martin Stjernholm #define co_wait(X,Y)
4a5f542009-01-25Henrik Grubbström (Grubba) #define co_wait_timeout(X,Y,S,N)
45637c2001-04-07Fredrik Hübinette (Hubbe) #define co_signal(X) #define co_broadcast(X)
bc21dc2001-11-01Martin Stjernholm #define co_destroy(X)
45637c2001-04-07Fredrik Hübinette (Hubbe)  #define low_init_threads_disable() #define init_threads_disable(X) #define exit_threads_disable(X) #endif /* PIKE_THREADS */ #ifndef CHECK_INTERPRETER_LOCK #define CHECK_INTERPRETER_LOCK() do {} while (0) #endif #ifdef __NT__
c171602003-04-01Martin Stjernholm #if !defined (PIKE_DEBUG) || defined (CONFIGURE_TEST)
45637c2001-04-07Fredrik Hübinette (Hubbe) #define CheckValidHandle(X) (X) #else PMOD_EXPORT HANDLE CheckValidHandle(HANDLE h); #endif #endif /* Initializer macros for static mutex and condition variables */ #ifdef PTHREAD_MUTEX_INITIALIZER
7338cb2008-09-08Martin Stjernholm #define HAS_STATIC_MUTEX_INIT
45637c2001-04-07Fredrik Hübinette (Hubbe) #define STATIC_MUTEX_INIT = PTHREAD_MUTEX_INITIALIZER #else #define STATIC_MUTEX_INIT #endif #ifdef PTHREAD_COND_INITIALIZER
7338cb2008-09-08Martin Stjernholm #define HAS_STATIC_COND_INIT
45637c2001-04-07Fredrik Hübinette (Hubbe) #define STATIC_COND_INIT = PTHREAD_COND_INITIALIZER #else #define STATIC_COND_INIT #endif
40fb6d2003-01-05Henrik Grubbström (Grubba) #ifndef THREAD_T_TO_PTR #ifdef PIKE_THREAD_T_IS_POINTER #define THREAD_T_TO_PTR(X) ((void *)(X)) #else /* !PIKE_THREAD_T_IS_POINTER */ #define THREAD_T_TO_PTR(X) ((void *)(ptrdiff_t)(X)) #endif /* PIKE_THREAD_T_IS_POINTER */ #endif /* !THREAD_T_TO_PTR */
45637c2001-04-07Fredrik Hübinette (Hubbe)  #endif /* PIKE_THREADLIB_H */