24ddc71998-03-28Henrik Grubbström (Grubba) /*
956f9a2000-07-30Fredrik Hübinette (Hubbe)  * $Id: threads.h,v 1.100 2000/07/30 07:27:51 hubbe Exp $
24ddc71998-03-28Henrik Grubbström (Grubba)  */
07513e1996-10-04Fredrik Hübinette (Hubbe) #ifndef THREADS_H #define THREADS_H #include "machine.h"
a7fef41997-09-03Per Hedbor #include "object.h"
07513e1996-10-04Fredrik Hübinette (Hubbe) #include "error.h"
5923b12000-07-06Fredrik Hübinette (Hubbe) #include "interpret.h"
d978c02000-02-04Henrik Grubbström (Grubba)  /* Needed for the sigset_t typedef, which is needed for * the pthread_sigsetmask() prototype on Solaris 2.x. */ #include <signal.h>
be478c1997-08-30Henrik Grubbström (Grubba) #ifdef HAVE_SYS_TYPES_H /* Needed for pthread_t on OSF/1 */ #include <sys/types.h> #endif /* HAVE_SYS_TYPES_H */
53ffab1999-08-10Martin Stjernholm #ifdef PIKE_THREADS
07513e1996-10-04Fredrik Hübinette (Hubbe) 
b377d72000-07-07Henrik Grubbström (Grubba) /* The fp macro conflicts with Solaris's <pthread.h>. */ #ifdef fp #undef fp #define FRAMEPOINTER_WAS_DEFINED #endif /* fp */
b2a0fb1997-02-06Henrik Grubbström (Grubba) /* * Decide which type of threads to use *
0409001998-02-10Per Hedbor  * UNIX_THREADS : Unix international threads * POSIX_THREADS : POSIX standard threads
b2a0fb1997-02-06Henrik Grubbström (Grubba)  * SGI_SPROC_THREADS : SGI sproc() based threads
0409001998-02-10Per Hedbor  * NT_THREADS : NT threads
b2a0fb1997-02-06Henrik Grubbström (Grubba)  */ #ifdef _UNIX_THREADS
97ffe41997-01-26Per Hedbor #ifdef HAVE_THREAD_H #define UNIX_THREADS #include <thread.h> #undef HAVE_PTHREAD_H #undef HAVE_THREAD_H #endif
b2a0fb1997-02-06Henrik Grubbström (Grubba) #endif /* _UNIX_THREADS */
97ffe41997-01-26Per Hedbor 
b2a0fb1997-02-06Henrik Grubbström (Grubba) #ifdef _MIT_POSIX_THREADS
97ffe41997-01-26Per Hedbor #define POSIX_THREADS
07513e1996-10-04Fredrik Hübinette (Hubbe) #include <pthread.h>
956f9a2000-07-30Fredrik Hübinette (Hubbe)  /* AIX is *STUPID* - Hubbe */ #undef func_data
07513e1996-10-04Fredrik Hübinette (Hubbe) #undef HAVE_PTHREAD_H
b2a0fb1997-02-06Henrik Grubbström (Grubba) #endif /* _MIT_POSIX_THREADS */
07513e1996-10-04Fredrik Hübinette (Hubbe) 
b2a0fb1997-02-06Henrik Grubbström (Grubba) #ifdef _SGI_SPROC_THREADS
5377b91997-02-01Henrik Grubbström (Grubba) /* Not supported yet */
b2a0fb1997-02-06Henrik Grubbström (Grubba) #undef SGI_SPROC_THREADS
5377b91997-02-01Henrik Grubbström (Grubba) #undef HAVE_SPROC
b2a0fb1997-02-06Henrik Grubbström (Grubba) #endif /* _SGI_SPROC_THREADS */
97ffe41997-01-26Per Hedbor 
00b32e2000-07-07Henrik Grubbström (Grubba)  /* Restore the fp macro. */ #ifdef FRAMEPOINTER_WAS_DEFINED #define fp Pike_fp #undef FRAMEPOINTER_WAS_DEFINED #endif /* FRAMEPOINTER_WAS_DEFINED */
07513e1996-10-04Fredrik Hübinette (Hubbe) extern int num_threads;
ef1e931998-03-26Henrik Grubbström (Grubba) extern int live_threads;
6d1a5e1996-10-07Fredrik Hübinette (Hubbe) struct object;
4908871998-08-10Fredrik Hübinette (Hubbe) extern size_t thread_stack_size;
07513e1996-10-04Fredrik Hübinette (Hubbe) 
0542ef1999-11-17Fredrik Hübinette (Hubbe) #define DEFINE_MUTEX(X) PIKE_MUTEX_T X
97ffe41997-01-26Per Hedbor  #ifdef POSIX_THREADS
71ac9e1999-08-29Fredrik Hübinette (Hubbe)  #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
97ffe41997-01-26Per Hedbor #define THREAD_T pthread_t
0542ef1999-11-17Fredrik Hübinette (Hubbe) #define PIKE_MUTEX_T pthread_mutex_t
07513e1996-10-04Fredrik Hübinette (Hubbe) #define mt_init(X) pthread_mutex_init((X),0) #define mt_lock(X) pthread_mutex_lock(X) #define mt_trylock(X) pthread_mutex_trylock(X) #define mt_unlock(X) pthread_mutex_unlock(X) #define mt_destroy(X) pthread_mutex_destroy(X)
97ffe41997-01-26Per Hedbor /* 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. */ #define th_setconcurrency(X)
5377b91997-02-01Henrik Grubbström (Grubba) #ifdef HAVE_PTHREAD_YIELD #define th_yield() pthread_yield() #else
97ffe41997-01-26Per Hedbor #define th_yield()
5377b91997-02-01Henrik Grubbström (Grubba) #endif /* HAVE_PTHREAD_YIELD */
864d3c1998-01-29Fredrik Hübinette (Hubbe) extern pthread_attr_t pattr; extern pthread_attr_t small_pattr;
07513e1996-10-04Fredrik Hübinette (Hubbe)  #define th_create(ID,fun,arg) pthread_create(ID,&pattr,fun,arg)
864d3c1998-01-29Fredrik Hübinette (Hubbe) #define th_create_small(ID,fun,arg) pthread_create(ID,&small_pattr,fun,arg)
07513e1996-10-04Fredrik Hübinette (Hubbe) #define th_exit(foo) pthread_exit(foo)
a70bd01996-12-15Niels Möller #define th_self() pthread_self()
ae7def1998-08-17Per Hedbor #define th_kill(ID,sig) pthread_kill((ID),(sig))
6a64c31998-09-05Henrik Grubbström (Grubba) #define th_join(ID,res) pthread_join((ID),(res))
5377b91997-02-01Henrik Grubbström (Grubba) #ifdef HAVE_PTHREAD_COND_INIT
07513e1996-10-04Fredrik Hübinette (Hubbe) #define COND_T pthread_cond_t
5377b91997-02-01Henrik Grubbström (Grubba) 
7435291998-08-31Henrik Grubbström (Grubba) #ifdef HAVE_PTHREAD_CONDATTR_DEFAULT_AIX /* AIX wants the & ... */
6e678f1998-08-06Henrik Grubbström (Grubba) #define co_init(X) pthread_cond_init((X), &pthread_condattr_default)
7435291998-08-31Henrik Grubbström (Grubba) #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 */
07513e1996-10-04Fredrik Hübinette (Hubbe) #define co_init(X) pthread_cond_init((X), 0)
5377b91997-02-01Henrik Grubbström (Grubba) #endif /* HAVE_PTHREAD_CONDATTR_DEFAULT */
7435291998-08-31Henrik Grubbström (Grubba) #endif /* HAVE_PTHREAD_CONDATTR_DEFAULT_AIX */
5377b91997-02-01Henrik Grubbström (Grubba) 
07513e1996-10-04Fredrik Hübinette (Hubbe) #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) #define co_destroy(X) pthread_cond_destroy(X)
5377b91997-02-01Henrik Grubbström (Grubba) #else #error No way to make cond-vars #endif /* HAVE_PTHREAD_COND_INIT */ #endif /* POSIX_THREADS */
97ffe41997-01-26Per Hedbor  #ifdef UNIX_THREADS #define THREAD_T thread_t #define PTHREAD_MUTEX_INITIALIZER DEFAULTMUTEX
0542ef1999-11-17Fredrik Hübinette (Hubbe) #define PIKE_MUTEX_T mutex_t
97ffe41997-01-26Per Hedbor #define mt_init(X) mutex_init((X),USYNC_THREAD,0) #define mt_lock(X) mutex_lock(X) #define mt_trylock(X) mutex_trylock(X) #define mt_unlock(X) mutex_unlock(X) #define mt_destroy(X) mutex_destroy(X) #define th_setconcurrency(X) thr_setconcurrency(X)
4908871998-08-10Fredrik Hübinette (Hubbe) #define th_create(ID,fun,arg) thr_create(NULL,thread_stack_size,fun,arg,THR_DAEMON|THR_DETACHED,ID)
26cd941999-05-07Fredrik Hübinette (Hubbe) #define th_create_small(ID,fun,arg) thr_create(NULL,8192*sizeof(char *),fun,arg,THR_DAEMON|THR_DETACHED,ID)
97ffe41997-01-26Per Hedbor #define th_exit(foo) thr_exit(foo) #define th_self() thr_self()
ae7def1998-08-17Per Hedbor #define th_kill(ID,sig) thr_kill((ID),(sig))
97ffe41997-01-26Per Hedbor #define th_yield() thr_yield()
6a64c31998-09-05Henrik Grubbström (Grubba) #define th_join(ID,res) thr_join((ID), NULL, (res))
97ffe41997-01-26Per Hedbor  #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)
5377b91997-02-01Henrik Grubbström (Grubba)  #endif /* UNIX_THREADS */
b2a0fb1997-02-06Henrik Grubbström (Grubba) #ifdef SGI_SPROC_THREADS
5377b91997-02-01Henrik Grubbström (Grubba)  /* * Not fully supported yet */ #define THREAD_T int
0542ef1999-11-17Fredrik Hübinette (Hubbe) #define PIKE_MUTEX_T ulock_t
5377b91997-02-01Henrik Grubbström (Grubba) #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)
864d3c1998-01-29Fredrik Hübinette (Hubbe) #define th_create_small(ID, fun, arg) (((*(ID)) = sproc(fun, PIKE_SPROC_FLAGS, arg)) == -1)
5377b91997-02-01Henrik Grubbström (Grubba) #define th_exit(X) exit(X) #define th_self() getpid() #define th_yield() sginap(0)
6a64c31998-09-05Henrik Grubbström (Grubba) #define th_join(ID,res) /*********/
d213271998-02-28Fredrik Hübinette (Hubbe) #define th_equal(X,Y) ((X)==(Y)) #define th_hash(X) ((unsigned INT32)(X))
5377b91997-02-01Henrik Grubbström (Grubba)  /* * No cond_vars yet */
b2a0fb1997-02-06Henrik Grubbström (Grubba) #endif /* SGI_SPROC_THREADS */
97ffe41997-01-26Per Hedbor 
a2db6b1998-01-02Fredrik Hübinette (Hubbe)  #ifdef NT_THREADS #include <process.h>
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) #include <windows.h>
a2db6b1998-01-02Fredrik Hübinette (Hubbe) 
26cd941999-05-07Fredrik Hübinette (Hubbe) #define THREAD_T unsigned
a2db6b1998-01-02Fredrik Hübinette (Hubbe) #define th_setconcurrency(X)
cd67ac1999-05-11Fredrik Hübinette (Hubbe) #define th_create(ID,fun,arg) low_nt_create_thread(2*1024*1024,fun, arg,ID) #define th_create_small(ID,fun,arg) low_nt_create_thread(8192*sizeof(char *), fun,arg,ID)
26cd941999-05-07Fredrik Hübinette (Hubbe) #define TH_RETURN_TYPE unsigned __stdcall
cd67ac1999-05-11Fredrik Hübinette (Hubbe) #define TH_STDCALL __stdcall #define th_exit(foo) _endthreadex(foo)
6a64c31998-09-05Henrik Grubbström (Grubba) #define th_join(ID,res) /******************* FIXME! ****************/
26cd941999-05-07Fredrik Hübinette (Hubbe) #define th_self() GetCurrentThreadId()
dc7cc91998-01-14Fredrik Hübinette (Hubbe) #define th_destroy(X)
e42eaf1998-01-02Fredrik Hübinette (Hubbe) #define th_yield() Sleep(0)
d213271998-02-28Fredrik Hübinette (Hubbe) #define th_equal(X,Y) ((X)==(Y))
26cd941999-05-07Fredrik Hübinette (Hubbe) #define th_hash(X) (X)
e42eaf1998-01-02Fredrik Hübinette (Hubbe) 
0542ef1999-11-17Fredrik Hübinette (Hubbe) #define PIKE_MUTEX_T HANDLE
dc7cc91998-01-14Fredrik Hübinette (Hubbe) #define mt_init(X) CheckValidHandle((*(X)=CreateMutex(NULL, 0, NULL)))
cd67ac1999-05-11Fredrik Hübinette (Hubbe) #define mt_lock(X) WaitForSingleObject(CheckValidHandle(*(X)), INFINITE) #define mt_trylock(X) WaitForSingleObject(CheckValidHandle(*(X)), 0) #define mt_unlock(X) ReleaseMutex(CheckValidHandle(*(X))) #define mt_destroy(X) CloseHandle(CheckValidHandle(*(X)))
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  #define EVENT_T HANDLE
dc7cc91998-01-14Fredrik Hübinette (Hubbe) #define event_init(X) CheckValidHandle(*(X)=CreateEvent(NULL, 1, 0, NULL))
cd67ac1999-05-11Fredrik Hübinette (Hubbe) #define event_signal(X) SetEvent(CheckValidHandle(*(X))) #define event_destroy(X) CloseHandle(CheckValidHandle(*(X))) #define event_wait(X) WaitForSingleObject(CheckValidHandle(*(X)), INFINITE)
a2db6b1998-01-02Fredrik Hübinette (Hubbe)  #endif
e42eaf1998-01-02Fredrik Hübinette (Hubbe) 
0542ef1999-11-17Fredrik Hübinette (Hubbe) #if !defined(COND_T) && defined(EVENT_T) && defined(PIKE_MUTEX_T)
e42eaf1998-01-02Fredrik Hübinette (Hubbe)  #define SIMULATE_COND_WITH_EVENT struct cond_t_queue { struct cond_t_queue *next; EVENT_T event; };
b1f4eb1998-01-13Fredrik Hübinette (Hubbe) typedef struct cond_t_s
e42eaf1998-01-02Fredrik Hübinette (Hubbe) {
0542ef1999-11-17Fredrik Hübinette (Hubbe)  PIKE_MUTEX_T lock;
b1f4eb1998-01-13Fredrik Hübinette (Hubbe)  struct cond_t_queue *head, *tail;
e42eaf1998-01-02Fredrik Hübinette (Hubbe) } COND_T; #define COND_T struct cond_t_s
dc7cc91998-01-14Fredrik Hübinette (Hubbe) #define co_init(X) do { mt_init(& (X)->lock), (X)->head=(X)->tail=0; }while(0)
e42eaf1998-01-02Fredrik Hübinette (Hubbe) 
0542ef1999-11-17Fredrik Hübinette (Hubbe) int co_wait(COND_T *c, PIKE_MUTEX_T *m);
e42eaf1998-01-02Fredrik Hübinette (Hubbe) int co_signal(COND_T *c); int co_broadcast(COND_T *c); int co_destroy(COND_T *c); #endif
b32ef12000-04-19Martin Stjernholm extern int th_running;
e42eaf1998-01-02Fredrik Hübinette (Hubbe) 
0542ef1999-11-17Fredrik Hübinette (Hubbe) extern PIKE_MUTEX_T interpreter_lock;
97ffe41997-01-26Per Hedbor 
c91f892000-04-19Martin Stjernholm #if defined(PIKE_DEBUG) && !defined(__NT__) /* This is a debug wrapper to enable checks that the interpreter lock * is hold by the current thread. */ extern THREAD_T debug_locking_thread; #define SET_LOCKING_THREAD (debug_locking_thread = th_self(), 0) #define mt_lock_interpreter() (mt_lock(&interpreter_lock) || SET_LOCKING_THREAD) #define mt_trylock_interpreter() (mt_trylock(&interpreter_lock) || SET_LOCKING_THREAD) #define mt_unlock_interpreter() (mt_unlock(&interpreter_lock)) #define co_wait_interpreter(COND) \ do {co_wait((COND), &interpreter_lock); SET_LOCKING_THREAD;} while (0) #define CHECK_INTERPRETER_LOCK() do { \ if (th_running) { \ THREAD_T self; \ if (!mt_trylock(&interpreter_lock)) \ fatal("Interpreter is not locked.\n"); \ self = th_self(); \ if (!th_equal(debug_locking_thread, self)) \ fatal("Interpreter is not locked by this thread.\n"); \ } \ } while (0) #else #define mt_lock_interpreter() (mt_lock(&interpreter_lock)) #define mt_trylock_interpreter() (mt_trylock(&interpreter_lock)) #define mt_unlock_interpreter() (mt_unlock(&interpreter_lock)) #define co_wait_interpreter(COND) do {co_wait((COND), &interpreter_lock);} while (0) #endif
ef1e931998-03-26Henrik Grubbström (Grubba) extern COND_T live_threads_change; /* Used by _disable_threads */ extern COND_T threads_disabled_change; /* Used by _disable_threads */
07513e1996-10-04Fredrik Hübinette (Hubbe)  struct svalue;
4218011999-01-31Fredrik Hübinette (Hubbe) struct pike_frame;
07513e1996-10-04Fredrik Hübinette (Hubbe) 
0542ef1999-11-17Fredrik Hübinette (Hubbe) extern PIKE_MUTEX_T interleave_lock;
a91ca01998-07-10Henrik Grubbström (Grubba)  struct interleave_mutex { struct interleave_mutex *next; struct interleave_mutex *prev;
0542ef1999-11-17Fredrik Hübinette (Hubbe)  PIKE_MUTEX_T lock;
a91ca01998-07-10Henrik Grubbström (Grubba) }; #define IMUTEX_T struct interleave_mutex #define DEFINE_IMUTEX(name) IMUTEX_T name /* If threads are disabled, we already hold the lock. */ #define LOCK_IMUTEX(im) do { \ if (!threads_disabled) { \ THREADS_FPRINTF(0, (stderr, "Locking IMutex 0x%08p...\n", (im))); \ THREADS_ALLOW(); \ mt_lock(&((im)->lock)); \ THREADS_DISALLOW(); \ } \ } while(0) /* If threads are disabled, the lock will be released later. */ #define UNLOCK_IMUTEX(im) do { \ if (!threads_disabled) { \ THREADS_FPRINTF(0, (stderr, "Unlocking IMutex 0x%08p...\n", (im))); \ mt_unlock(&((im)->lock)); \ } \ } while(0)
5740881998-01-01Fredrik Hübinette (Hubbe) #define THREAD_NOT_STARTED -1 #define THREAD_RUNNING 0 #define THREAD_EXITED 1
5923b12000-07-06Fredrik Hübinette (Hubbe) struct thread_state { struct Pike_interpreter state; char swapped; char status; COND_T status_change; THREAD_T id; struct mapping *thread_local; struct thread_state *hashlink, **backlink;
b377d72000-07-07Henrik Grubbström (Grubba) #ifdef PROFILING long long time_base; #endif /* PROFILING */
5923b12000-07-06Fredrik Hübinette (Hubbe) };
e132001998-11-19Fredrik Hübinette (Hubbe) 
07513e1996-10-04Fredrik Hübinette (Hubbe) 
26cd941999-05-07Fredrik Hübinette (Hubbe) #ifndef TH_RETURN_TYPE #define TH_RETURN_TYPE void * #endif
cd67ac1999-05-11Fredrik Hübinette (Hubbe) #ifndef TH_STDCALL #define TH_STDCALL #endif
e42eaf1998-01-02Fredrik Hübinette (Hubbe) #ifndef th_destroy #define th_destroy(X) #endif #ifndef th_yield #define th_yield() #endif
d213271998-02-28Fredrik Hübinette (Hubbe) #ifndef th_equal
ce31941998-03-10Marcus Comstedt #define th_equal(X,Y) (!MEMCMP(&(X),&(Y),sizeof(THREAD_T)))
d213271998-02-28Fredrik Hübinette (Hubbe) #endif #ifndef th_hash
9f2dc01998-03-12Henrik Grubbström (Grubba) #define th_hash(X) hashmem((unsigned char *)&(X),sizeof(THREAD_T), 16)
d213271998-02-28Fredrik Hübinette (Hubbe) #endif
60e6a61997-09-03Henrik Grubbström (Grubba) /* Define to get a debug-trace of some of the threads operations. */
a91ca01998-07-10Henrik Grubbström (Grubba) /* #define VERBOSE_THREADS_DEBUG 0 */ /* Some debug */ /* #define VERBOSE_THREADS_DEBUG 1 */ /* Lots of debug */
60e6a61997-09-03Henrik Grubbström (Grubba)  #ifndef VERBOSE_THREADS_DEBUG
a91ca01998-07-10Henrik Grubbström (Grubba) #define THREADS_FPRINTF(L,X)
60e6a61997-09-03Henrik Grubbström (Grubba) #else
a91ca01998-07-10Henrik Grubbström (Grubba) #define THREADS_FPRINTF(L,X) do { \ if ((VERBOSE_THREADS_DEBUG + 0) >= (L)) fprintf X; \ } while(0)
60e6a61997-09-03Henrik Grubbström (Grubba) #endif /* VERBOSE_THREADS_DEBUG */
78112c1998-04-13Henrik Grubbström (Grubba) #ifdef THREAD_TRACE
1f21332000-07-28Fredrik Hübinette (Hubbe) extern int t_flag; #define SWAP_OUT_TRACE(_tmp) do { (_tmp)->status.t_flag = t_flag; } while(0) #define SWAP_IN_TRACE(_tmp) do { t_flag = (_tmp)->status.t_flag; } while(0)
78112c1998-04-13Henrik Grubbström (Grubba) #else /* !THREAD_TRACE */ #define SWAP_OUT_TRACE(_tmp) #define SWAP_IN_TRACE(_tmp) #endif /* THREAD_TRACE */
e132001998-11-19Fredrik Hübinette (Hubbe) #if defined(PROFILING) && defined(HAVE_GETHRTIME)
2dbefd1998-11-20Fredrik Hübinette (Hubbe) #define DO_IF_PROFILING(X) X
e132001998-11-19Fredrik Hübinette (Hubbe) #else #define DO_IF_PROFILING(X) #endif
5923b12000-07-06Fredrik Hübinette (Hubbe) #define SWAP_OUT_THREAD(_tmp) do { \ (_tmp)->state=Pike_interpreter; \ (_tmp)->swapped=1; \ DO_IF_PROFILING( (_tmp)->time_base += gethrtime() ; ) \
a7fef41997-09-03Per Hedbor  } while(0)
5923b12000-07-06Fredrik Hübinette (Hubbe) #define SWAP_IN_THREAD(_tmp) do { \ (_tmp)->swapped=0; \ Pike_interpreter=(_tmp)->state; \ DO_IF_PROFILING( Pike_interpreter.time_base -= gethrtime();) \
a7fef41997-09-03Per Hedbor  } while(0)
2d9cbe1997-09-08Fredrik Hübinette (Hubbe) #define SWAP_OUT_CURRENT_THREAD() \ do {\
5923b12000-07-06Fredrik Hübinette (Hubbe)  struct thread_state *_tmp=OBJ2THREAD(Pike_interpreter.thread_id); \
2d9cbe1997-09-08Fredrik Hübinette (Hubbe)  SWAP_OUT_THREAD(_tmp); \
a91ca01998-07-10Henrik Grubbström (Grubba)  THREADS_FPRINTF(1, (stderr, "SWAP_OUT_CURRENT_THREAD() %s:%d t:%08x\n", \ __FILE__, __LINE__, (unsigned int)_tmp->thread_id)) \
2d9cbe1997-09-08Fredrik Hübinette (Hubbe)  #define SWAP_IN_CURRENT_THREAD() \
a91ca01998-07-10Henrik Grubbström (Grubba)  THREADS_FPRINTF(1, (stderr, "SWAP_IN_CURRENT_THREAD() %s:%d ... t:%08x\n", \ __FILE__, __LINE__, (unsigned int)_tmp->thread_id)); \
2d9cbe1997-09-08Fredrik Hübinette (Hubbe)  SWAP_IN_THREAD(_tmp);\ } while(0)
71f3a21998-11-22Fredrik Hübinette (Hubbe) #if defined(PIKE_DEBUG) && ! defined(DONT_HIDE_GLOBALS)
d818601997-10-21Henrik Grubbström (Grubba) /* 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. */ #define HIDE_GLOBAL_VARIABLES() do { \
5923b12000-07-06Fredrik Hübinette (Hubbe)  int Pike_interpreter =0; \
0e6f4b2000-02-20Fredrik Hübinette (Hubbe)  int pop_n_elems = 0; \
a91ca01998-07-10Henrik Grubbström (Grubba)  int push_sp_mark = 0, pop_sp_mark = 0, threads_disabled = 1
d818601997-10-21Henrik Grubbström (Grubba) 
602f691997-10-25Henrik Grubbström (Grubba) /* Note that the semi-colon below is needed to add an empty statement * in case there is a label before the macro. */ #define REVEAL_GLOBAL_VARIABLES() ; } while(0)
71f3a21998-11-22Fredrik Hübinette (Hubbe) #else /* PIKE_DEBUG */
d818601997-10-21Henrik Grubbström (Grubba) #define HIDE_GLOBAL_VARIABLES() #define REVEAL_GLOBAL_VARIABLES()
71f3a21998-11-22Fredrik Hübinette (Hubbe) #endif /* PIKE_DEBUG */
9b92d31999-01-31Fredrik Hübinette (Hubbe)  #define OBJ2THREAD(X) \
5923b12000-07-06Fredrik Hübinette (Hubbe)  ((struct thread_state *)((X)->storage+thread_storage_offset))
2d9cbe1997-09-08Fredrik Hübinette (Hubbe) 
5923b12000-07-06Fredrik Hübinette (Hubbe) #define THREADSTATE2OBJ(X) ((X)->state.thread_id)
26cd941999-05-07Fredrik Hübinette (Hubbe) 
1f21332000-07-28Fredrik Hübinette (Hubbe) extern int Pike_in_gc;
602f691997-10-25Henrik Grubbström (Grubba) #define THREADS_ALLOW() do { \
5923b12000-07-06Fredrik Hübinette (Hubbe)  struct thread_state *_tmp=OBJ2THREAD(Pike_interpreter.thread_id); \
6bc62b2000-04-14Martin Stjernholm  DO_IF_DEBUG({ \
5923b12000-07-06Fredrik Hübinette (Hubbe)  if(thread_for_id(th_self()) != Pike_interpreter.thread_id) \
b377d72000-07-07Henrik Grubbström (Grubba)  fatal("thread_for_id() (or Pike_interpreter.thread_id) failed!" \ " %p != %p\n", \ thread_for_id(th_self()), Pike_interpreter.thread_id); \
6a22d02000-06-10Martin Stjernholm  if (Pike_in_gc > 50 && Pike_in_gc < 300) \
6bc62b2000-04-14Martin Stjernholm  fatal("Threads allowed during garbage collection.\n"); \ }) \
07513e1996-10-04Fredrik Hübinette (Hubbe)  if(num_threads > 1 && !threads_disabled) { \
a7fef41997-09-03Per Hedbor  SWAP_OUT_THREAD(_tmp); \
a91ca01998-07-10Henrik Grubbström (Grubba)  THREADS_FPRINTF(1, (stderr, "THREADS_ALLOW() %s:%d t:%08x(#%d)\n", \ __FILE__, __LINE__, \ (unsigned int)_tmp->thread_id, live_threads)); \
c91f892000-04-19Martin Stjernholm  mt_unlock_interpreter(); \
602f691997-10-25Henrik Grubbström (Grubba)  } else {} \ HIDE_GLOBAL_VARIABLES()
07513e1996-10-04Fredrik Hübinette (Hubbe)  #define THREADS_DISALLOW() \
d818601997-10-21Henrik Grubbström (Grubba)  REVEAL_GLOBAL_VARIABLES(); \
a7fef41997-09-03Per Hedbor  if(_tmp->swapped) { \
c91f892000-04-19Martin Stjernholm  mt_lock_interpreter(); \
a91ca01998-07-10Henrik Grubbström (Grubba)  THREADS_FPRINTF(1, (stderr, "THREADS_DISALLOW() %s:%d t:%08x(#%d)\n", \ __FILE__, __LINE__, \ (unsigned int)_tmp->thread_id, live_threads)); \
ef1e931998-03-26Henrik Grubbström (Grubba)  while (threads_disabled) { \
a91ca01998-07-10Henrik Grubbström (Grubba)  THREADS_FPRINTF(1, (stderr, \ "THREADS_DISALLOW(): Threads disabled\n")); \
c91f892000-04-19Martin Stjernholm  co_wait_interpreter(&threads_disabled_change); \
ef1e931998-03-26Henrik Grubbström (Grubba)  } \
a7fef41997-09-03Per Hedbor  SWAP_IN_THREAD(_tmp);\
07513e1996-10-04Fredrik Hübinette (Hubbe)  } \
5923b12000-07-06Fredrik Hübinette (Hubbe)  DO_IF_DEBUG( if(thread_for_id(th_self()) != Pike_interpreter.thread_id) \ fatal("thread_for_id() (or Pike_interpreter.thread_id) failed! %p != %p\n",thread_for_id(th_self()),Pike_interpreter.thread_id) ; ) \
07513e1996-10-04Fredrik Hübinette (Hubbe)  } while(0)
ef1e931998-03-26Henrik Grubbström (Grubba) #define THREADS_ALLOW_UID() do { \
5923b12000-07-06Fredrik Hübinette (Hubbe)  struct thread_state *_tmp_uid=OBJ2THREAD(Pike_interpreter.thread_id); \
6bc62b2000-04-14Martin Stjernholm  DO_IF_DEBUG({ \
5923b12000-07-06Fredrik Hübinette (Hubbe)  if(thread_for_id(th_self()) != Pike_interpreter.thread_id) \ fatal("thread_for_id() (or Pike_interpreter.thread_id) failed! %p != %p\n",thread_for_id(th_self()),Pike_interpreter.thread_id); \
6a22d02000-06-10Martin Stjernholm  if (Pike_in_gc > 50 && Pike_in_gc < 300) \
6bc62b2000-04-14Martin Stjernholm  fatal("Threads allowed during garbage collection.\n"); \ }) \
ef1e931998-03-26Henrik Grubbström (Grubba)  if(num_threads > 1 && !threads_disabled) { \ SWAP_OUT_THREAD(_tmp_uid); \ live_threads++; \
a91ca01998-07-10Henrik Grubbström (Grubba)  THREADS_FPRINTF(1, (stderr, "THREADS_ALLOW_UID() %s:%d t:%08x(#%d)\n", \ __FILE__, __LINE__, \ (unsigned int)_tmp_uid->thread_id, live_threads)); \
c91f892000-04-19Martin Stjernholm  mt_unlock_interpreter(); \
ef1e931998-03-26Henrik Grubbström (Grubba)  } else {} \ HIDE_GLOBAL_VARIABLES() #define THREADS_DISALLOW_UID() \ REVEAL_GLOBAL_VARIABLES(); \ if(_tmp_uid->swapped) { \
c91f892000-04-19Martin Stjernholm  mt_lock_interpreter(); \
ef1e931998-03-26Henrik Grubbström (Grubba)  live_threads--; \
a91ca01998-07-10Henrik Grubbström (Grubba)  THREADS_FPRINTF(1, (stderr, \ "THREADS_DISALLOW_UID() %s:%d t:%08x(#%d)\n", \ __FILE__, __LINE__, \ (unsigned int)_tmp_uid->thread_id, live_threads)); \
72fdae1998-07-05Henrik Grubbström (Grubba)  co_broadcast(&live_threads_change); \
ef1e931998-03-26Henrik Grubbström (Grubba)  while (threads_disabled) { \
a91ca01998-07-10Henrik Grubbström (Grubba)  THREADS_FPRINTF(1, (stderr, "THREADS_DISALLOW_UID(): Wait...\n")); \
c91f892000-04-19Martin Stjernholm  co_wait_interpreter(&threads_disabled_change); \
ef1e931998-03-26Henrik Grubbström (Grubba)  } \ SWAP_IN_THREAD(_tmp_uid);\ } \ } while(0)
db40ab1999-04-15Fredrik Hübinette (Hubbe) #define SWAP_IN_THREAD_IF_REQUIRED() do { \
5923b12000-07-06Fredrik Hübinette (Hubbe)  struct thread_state *_tmp=thread_state_for_id(th_self()); \
db40ab1999-04-15Fredrik Hübinette (Hubbe)  HIDE_GLOBAL_VARIABLES(); \ THREADS_DISALLOW() #ifdef PIKE_DEBUG
b32ef12000-04-19Martin Stjernholm #define ASSERT_THREAD_SWAPPED_IN() do { \
5923b12000-07-06Fredrik Hübinette (Hubbe)  struct thread_state *_tmp=thread_state_for_id(th_self()); \
b32ef12000-04-19Martin Stjernholm  if(_tmp->swapped) fatal("Thread is not swapped in!\n"); \
db40ab1999-04-15Fredrik Hübinette (Hubbe)  }while(0) #else #define ASSERT_THREAD_SWAPPED_IN() #endif
07513e1996-10-04Fredrik Hübinette (Hubbe) /* Prototypes begin here */
a2ad152000-02-16Fredrik Hübinette (Hubbe) int low_nt_create_thread(unsigned Pike_stack_size,
cd67ac1999-05-11Fredrik Hübinette (Hubbe)  unsigned (TH_STDCALL *func)(void *), void *arg, unsigned *id);
6d1a5e1996-10-07Fredrik Hübinette (Hubbe) struct thread_starter;
cd67ac1999-05-11Fredrik Hübinette (Hubbe) struct thread_local; void low_init_threads_disable(void); void init_threads_disable(struct object *o); void exit_threads_disable(struct object *o); void init_interleave_mutex(IMUTEX_T *im); void exit_interleave_mutex(IMUTEX_T *im); void thread_table_init(void); unsigned INT32 thread_table_hash(THREAD_T *tid); void thread_table_insert(struct object *o); void thread_table_delete(struct object *o);
5923b12000-07-06Fredrik Hübinette (Hubbe) struct thread_state *thread_state_for_id(THREAD_T tid);
cd67ac1999-05-11Fredrik Hübinette (Hubbe) struct object *thread_for_id(THREAD_T tid); void f_all_threads(INT32 args);
56ac102000-03-29Fredrik Hübinette (Hubbe) int count_pike_threads(void);
26cd941999-05-07Fredrik Hübinette (Hubbe) TH_RETURN_TYPE new_thread_func(void * data);
07513e1996-10-04Fredrik Hübinette (Hubbe) void f_thread_create(INT32 args);
dc7cc91998-01-14Fredrik Hübinette (Hubbe) void f_thread_set_concurrency(INT32 args);
a29e021996-10-15Fredrik Hübinette (Hubbe) void f_this_thread(INT32 args);
6d1a5e1996-10-07Fredrik Hübinette (Hubbe) struct mutex_storage; struct key_storage;
07513e1996-10-04Fredrik Hübinette (Hubbe) void f_mutex_lock(INT32 args); void f_mutex_trylock(INT32 args); void init_mutex_obj(struct object *o); void exit_mutex_obj(struct object *o); void init_mutex_key_obj(struct object *o); void exit_mutex_key_obj(struct object *o); void f_cond_wait(INT32 args); void f_cond_signal(INT32 args); void f_cond_broadcast(INT32 args); void init_cond_obj(struct object *o); void exit_cond_obj(struct object *o);
dc7cc91998-01-14Fredrik Hübinette (Hubbe) void f_thread_backtrace(INT32 args); void f_thread_id_status(INT32 args); void init_thread_obj(struct object *o); void exit_thread_obj(struct object *o);
cd67ac1999-05-11Fredrik Hübinette (Hubbe) void f_thread_local(INT32 args); void f_thread_local_get(INT32 args); void f_thread_local_set(INT32 args);
a91ca01998-07-10Henrik Grubbström (Grubba) void low_th_init(void);
cd67ac1999-05-11Fredrik Hübinette (Hubbe) void th_init(void);
be478c1997-08-30Henrik Grubbström (Grubba) void th_cleanup(void);
cd67ac1999-05-11Fredrik Hübinette (Hubbe) int th_num_idle_farmers(void); int th_num_farmers(); void th_farm(void (*fun)(void *), void *here);
07513e1996-10-04Fredrik Hübinette (Hubbe) /* Prototypes end here */ #else
1994251999-09-06Fredrik Hübinette (Hubbe)  #define th_atfork(X,Y,Z) #define th_atfork_prepare() #define th_atfork_parent() #define th_atfork_child()
97ffe41997-01-26Per Hedbor #define th_setconcurrency(X)
419ede1996-11-13Fredrik Hübinette (Hubbe) #define DEFINE_MUTEX(X)
a91ca01998-07-10Henrik Grubbström (Grubba) #define DEFINE_IMUTEX(X) #define init_interleave_mutex(X) #define LOCK_IMUTEX(X) #define UNLOCK_IMUTEX(X)
0516881996-10-04David Hedbor #define mt_init(X) #define mt_lock(X) #define mt_unlock(X)
419ede1996-11-13Fredrik Hübinette (Hubbe) #define mt_destroy(X)
3b44f82000-07-11David Hedbor #define THREADS_ALLOW()
07513e1996-10-04Fredrik Hübinette (Hubbe) #define THREADS_DISALLOW()
a1ad421998-03-27Fredrik Hübinette (Hubbe) #define THREADS_ALLOW_UID() #define THREADS_DISALLOW_UID()
43306a1997-10-21Henrik Grubbström (Grubba) #define HIDE_GLOBAL_VARIABLES() #define REVEAL_GLOBAL_VARIABLES()
db40ab1999-04-15Fredrik Hübinette (Hubbe) #define ASSERT_THREAD_SWAPPED_IN() #define SWAP_IN_THREAD_IF_REQUIRED()
07513e1996-10-04Fredrik Hübinette (Hubbe) #define th_init()
a91ca01998-07-10Henrik Grubbström (Grubba) #define low_th_init()
6d1a5e1996-10-07Fredrik Hübinette (Hubbe) #define th_cleanup()
07513e1996-10-04Fredrik Hübinette (Hubbe) #define th_init_programs()
fc33451997-10-02Fredrik Hübinette (Hubbe) #define th_self() ((void*)0)
2bfcfe1998-03-27Fredrik Hübinette (Hubbe) #define co_signal(X)
a872b21998-04-30Fredrik Hübinette (Hubbe) #define co_broadcast(X)
98759d1998-06-25Henrik Grubbström (Grubba) 
f328f11998-07-17Henrik Grubbström (Grubba) #define low_init_threads_disable()
98759d1998-06-25Henrik Grubbström (Grubba) #define init_threads_disable(X) #define exit_threads_disable(X)
b377d72000-07-07Henrik Grubbström (Grubba) 
53ffab1999-08-10Martin Stjernholm #endif /* PIKE_THREADS */
07513e1996-10-04Fredrik Hübinette (Hubbe) 
e8b82a2000-04-26Martin Stjernholm #ifndef CHECK_INTERPRETER_LOCK #define CHECK_INTERPRETER_LOCK() do {} while (0) #endif
dc7cc91998-01-14Fredrik Hübinette (Hubbe) #ifdef __NT__
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifndef PIKE_DEBUG
cd67ac1999-05-11Fredrik Hübinette (Hubbe) #define CheckValidHandle(X) (X)
dc7cc91998-01-14Fredrik Hübinette (Hubbe) #else
cd67ac1999-05-11Fredrik Hübinette (Hubbe) HANDLE CheckValidHandle(HANDLE h);
dc7cc91998-01-14Fredrik Hübinette (Hubbe) #endif #endif
0516881996-10-04David Hedbor 
07513e1996-10-04Fredrik Hübinette (Hubbe) extern int threads_disabled;
9b92d31999-01-31Fredrik Hübinette (Hubbe) extern int thread_storage_offset;
5377b91997-02-01Henrik Grubbström (Grubba) 
0542ef1999-11-17Fredrik Hübinette (Hubbe) #ifndef NO_PIKE_SHORTHAND #define MUTEX_T PIKE_MUTEX_T #endif
d3015d2000-04-18Jonas Wallden  /* Initializer macros for static mutex and condition variables */ #ifdef PTHREAD_MUTEX_INITIALIZER #define STATIC_MUTEX_INIT = PTHREAD_MUTEX_INITIALIZER #else #define STATIC_MUTEX_INIT #endif #ifdef PTHREAD_COND_INITIALIZER #define STATIC_COND_INIT = PTHREAD_COND_INITIALIZER #else #define STATIC_COND_INIT #endif
ec2bab2000-06-24Fredrik Hübinette (Hubbe) /* for compatibility */ #include "interpret.h"
d3015d2000-04-18Jonas Wallden 
5377b91997-02-01Henrik Grubbström (Grubba) #endif /* THREADS_H */