e576bb | 2002-10-11 | Martin Nilsson | |
|
1b10db | 2002-10-08 | Martin Nilsson | |
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | #include "global.h"
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | |
|
270295 | 2004-04-21 | Martin Stjernholm | |
|
c7f271 | 2007-06-09 | Martin Stjernholm | | #include "pike_error.h"
|
91518c | 2009-03-15 | Martin Stjernholm | |
|
83b184 | 2003-02-08 | Martin Stjernholm | |
|
d0aa0d | 2011-04-02 | Martin Stjernholm | |
|
91518c | 2009-03-15 | Martin Stjernholm | | #ifndef CONFIGURE_TEST
|
8a2693 | 2014-07-21 | Per Hedbor | | #define IN_THREAD_CODE
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | #include "threads.h"
#include "array.h"
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | #include "mapping.h"
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | #include "object.h"
|
bb55f8 | 1997-03-16 | Fredrik Hübinette (Hubbe) | | #include "pike_macros.h"
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | | #include "callback.h"
|
9c6f7d | 1997-04-15 | Fredrik Hübinette (Hubbe) | | #include "builtin_functions.h"
#include "constants.h"
|
be478c | 1997-08-30 | Henrik Grubbström (Grubba) | | #include "program.h"
|
3f87be | 1999-12-14 | Martin Stjernholm | | #include "program_id.h"
|
c5b96b | 1997-11-11 | Henrik Grubbström (Grubba) | | #include "gc.h"
|
3c0c28 | 1998-01-26 | Fredrik Hübinette (Hubbe) | | #include "main.h"
|
a49ee6 | 1999-04-02 | Fredrik Hübinette (Hubbe) | | #include "module_support.h"
|
52e4c6 | 1999-12-13 | Martin Stjernholm | | #include "pike_types.h"
|
9a0d42 | 2000-02-06 | Martin Stjernholm | | #include "operators.h"
|
7e8ea3 | 2000-08-13 | Henrik Grubbström (Grubba) | | #include "bignum.h"
|
700dac | 2002-02-05 | Martin Stjernholm | | #include "signal_handler.h"
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | #include "backend.h"
|
d5c61f | 2002-12-07 | Henrik Grubbström (Grubba) | | #include "pike_rusage.h"
|
f91994 | 2010-10-17 | Martin Stjernholm | | #include "pike_cpulib.h"
|
d88828 | 2018-02-09 | Martin Nilsson | | #include "pike_compiler.h"
|
67d914 | 2019-05-30 | Henrik Grubbström (Grubba) | | #include "sprintf.h"
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | |
|
cd11fa | 1999-05-13 | Henrik Grubbström (Grubba) | | #include <errno.h>
|
466caa | 2010-10-23 | Martin Stjernholm | | #include <math.h>
|
4dbca3 | 2015-10-18 | Martin Nilsson | | #include <time.h>
|
cd11fa | 1999-05-13 | Henrik Grubbström (Grubba) | |
|
f663a0 | 2003-03-05 | Martin Stjernholm | | #ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#endif /* HAVE_SYS_PRCTL_H */
|
08c53c | 2003-11-25 | Jonas Wallden | | #ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
|
8a2693 | 2014-07-21 | Per Hedbor | |
static struct Pike_interpreter_struct static_pike_interpreter;
|
7a5298 | 2015-09-09 | Henrik Grubbström (Grubba) | | static cpu_time_t thread_quanta = 0;
|
1d1616 | 2014-08-25 | Per Hedbor | | PMOD_EXPORT struct Pike_interpreter_struct *
#if defined(__GNUC__) && __GNUC__ >= 3
__restrict
#endif
Pike_interpreter_pointer = &static_pike_interpreter;
|
8a2693 | 2014-07-21 | Per Hedbor | |
|
3b54e5 | 2014-08-21 | Martin Nilsson | | PMOD_EXPORT struct Pike_interpreter_struct * pike_get_interpreter_pointer(void)
|
84c9d9 | 2014-07-22 | Per Hedbor | | {
return Pike_interpreter_pointer;
}
|
91518c | 2009-03-15 | Martin Stjernholm | | #else /* CONFIGURE_TEST */
#include "pike_threadlib.h"
#endif
|
ef1e93 | 1998-03-26 | Henrik Grubbström (Grubba) | |
|
a58dc8 | 2019-05-01 | Marcus Comstedt | | #ifdef _REENTRANT
|
91518c | 2009-03-15 | Martin Stjernholm | | #ifndef VERBOSE_THREADS_DEBUG
|
7d06ba | 2016-02-07 | Martin Nilsson | | #define THREADS_FPRINTF(LEVEL,...)
|
7d7b02 | 2003-04-02 | Martin Stjernholm | | #else
|
7d06ba | 2016-02-07 | Martin Nilsson | | #define THREADS_FPRINTF(LEVEL,...) do { \
|
91518c | 2009-03-15 | Martin Stjernholm | | if ((VERBOSE_THREADS_DEBUG + 0) >= (LEVEL)) { \
/* E.g. THREADS_DISALLOW is used in numerous places where the */ \
/* value in errno must not be clobbered. */ \
int saved_errno = errno; \
fprintf (stderr, "[%"PRINTSIZET"x] ", (size_t) th_self()); \
|
7d06ba | 2016-02-07 | Martin Nilsson | | fprintf (stderr, __VA_ARGS__); \
|
91518c | 2009-03-15 | Martin Stjernholm | | errno = saved_errno; \
} \
} while(0)
#endif /* VERBOSE_THREADS_DEBUG */
|
7d7b02 | 2003-04-02 | Martin Stjernholm | |
|
e3ee06 | 2005-03-31 | Martin Nilsson | | #ifndef PIKE_THREAD_C_STACK_SIZE
#define PIKE_THREAD_C_STACK_SIZE (256 * 1024)
#endif
PMOD_EXPORT size_t thread_stack_size=PIKE_THREAD_C_STACK_SIZE;
|
c432f7 | 2003-05-02 | Henrik Grubbström (Grubba) | | PMOD_EXPORT void thread_low_error (int errcode, const char *cmd,
const char *fname, int lineno)
|
01185d | 2003-04-01 | Martin Stjernholm | | {
|
c7f271 | 2007-06-09 | Martin Stjernholm | | #ifdef CONFIGURE_TEST
fprintf (stderr, "%s:%d: %s\n"
"Unexpected error from thread function: %d\n",
fname, lineno, cmd, errcode);
abort();
#else
|
91518c | 2009-03-15 | Martin Stjernholm | | debug_fatal ("%s:%d: Fatal error: %s\n"
"Unexpected error from thread function: %d\n",
fname, lineno, cmd, errcode);
|
c7f271 | 2007-06-09 | Martin Stjernholm | | #endif
|
01185d | 2003-04-01 | Martin Stjernholm | | }
|
1f88bf | 2001-09-24 | Henrik Grubbström (Grubba) | |
int __thread_sys_behavior = 1;
|
83b184 | 2003-02-08 | Martin Stjernholm | | #ifndef CONFIGURE_TEST
|
3c5576 | 2001-09-20 | Fredrik Hübinette (Hubbe) | | #if !defined(HAVE_PTHREAD_ATFORK) && !defined(th_atfork)
|
71ac9e | 1999-08-29 | Fredrik Hübinette (Hubbe) | | #include "callback.h"
|
58580c | 2001-11-12 | Martin Stjernholm | | #define PIKE_USE_OWN_ATFORK
|
71ac9e | 1999-08-29 | Fredrik Hübinette (Hubbe) | |
|
3c5576 | 2001-09-20 | Fredrik Hübinette (Hubbe) | |
|
71ac9e | 1999-08-29 | Fredrik Hübinette (Hubbe) | | static struct callback_list atfork_prepare_callback;
static struct callback_list atfork_parent_callback;
static struct callback_list atfork_child_callback;
int th_atfork(void (*prepare)(void),void (*parent)(void),void (*child)(void))
{
if(prepare)
add_to_callback(&atfork_prepare_callback, (callback_func) prepare, 0, 0);
if(parent)
add_to_callback(&atfork_parent_callback, (callback_func) parent, 0, 0);
if(child)
add_to_callback(&atfork_child_callback, (callback_func) child, 0, 0);
return 0;
}
void th_atfork_prepare(void)
{
call_callback(& atfork_prepare_callback, 0);
}
void th_atfork_parent(void)
{
call_callback(& atfork_parent_callback, 0);
}
void th_atfork_child(void)
{
call_callback(& atfork_child_callback, 0);
}
#endif
|
83b184 | 2003-02-08 | Martin Stjernholm | | #endif /* !CONFIGURE_TEST */
|
dc7cc9 | 1998-01-14 | Fredrik Hübinette (Hubbe) | | #ifdef __NT__
|
91518c | 2009-03-15 | Martin Stjernholm | | PMOD_EXPORT int low_nt_create_thread(unsigned Pike_stack_size,
unsigned (TH_STDCALL *fun)(void *),
void *arg,
unsigned *id)
|
cd67ac | 1999-05-11 | Fredrik Hübinette (Hubbe) | | {
|
7965d7 | 2001-01-24 | Fredrik Hübinette (Hubbe) | | HANDLE h = (HANDLE)_beginthreadex(NULL, Pike_stack_size, fun, arg, 0, id);
|
cd67ac | 1999-05-11 | Fredrik Hübinette (Hubbe) | | if(h)
{
CloseHandle(h);
return 0;
}
else
{
|
518245 | 2012-06-28 | Martin Stjernholm | | return errno;
|
cd67ac | 1999-05-11 | Fredrik Hübinette (Hubbe) | | }
}
|
dc7cc9 | 1998-01-14 | Fredrik Hübinette (Hubbe) | | #endif
|
e42eaf | 1998-01-02 | Fredrik Hübinette (Hubbe) | | #ifdef SIMULATE_COND_WITH_EVENT
|
74ea78 | 2016-01-29 | Martin Nilsson | | PMOD_EXPORT int co_wait(COND_T *c, PIKE_MUTEX_T *m)
|
e42eaf | 1998-01-02 | Fredrik Hübinette (Hubbe) | | {
struct cond_t_queue me;
event_init(&me.event);
|
dc7cc9 | 1998-01-14 | Fredrik Hübinette (Hubbe) | | me.next=0;
|
e42eaf | 1998-01-02 | Fredrik Hübinette (Hubbe) | | mt_lock(& c->lock);
|
dc7cc9 | 1998-01-14 | Fredrik Hübinette (Hubbe) | | if(c->tail)
{
c->tail->next=&me;
c->tail=&me;
}else{
c->head=c->tail=&me;
}
|
e42eaf | 1998-01-02 | Fredrik Hübinette (Hubbe) | |
mt_unlock(& c->lock);
mt_unlock(m);
|
cb0658 | 2009-04-25 | Martin Stjernholm | |
|
e42eaf | 1998-01-02 | Fredrik Hübinette (Hubbe) | | event_wait(&me.event);
mt_lock(m);
event_destroy(& me.event);
|
71f3a2 | 1998-11-22 | Fredrik Hübinette (Hubbe) | | #ifdef PIKE_DEBUG
|
dc7cc9 | 1998-01-14 | Fredrik Hübinette (Hubbe) | | if(me.next)
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal("Wait on event return prematurely!!\n");
|
dc7cc9 | 1998-01-14 | Fredrik Hübinette (Hubbe) | | #endif
|
e42eaf | 1998-01-02 | Fredrik Hübinette (Hubbe) | | return 0;
}
|
74ea78 | 2016-01-29 | Martin Nilsson | | PMOD_EXPORT int co_wait_timeout(COND_T *c, PIKE_MUTEX_T *m, long s, long nanos)
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | {
struct cond_t_queue me;
event_init(&me.event);
me.next=0;
mt_lock(& c->lock);
if(c->tail)
{
c->tail->next=&me;
c->tail=&me;
}else{
c->head=c->tail=&me;
}
mt_unlock(& c->lock);
mt_unlock(m);
if (s || nanos) {
|
e7f705 | 2009-01-26 | Henrik Grubbström (Grubba) | | DWORD msec;
if (s >= 4294967) {
msec = INFINITE;
} else {
msec = s*1000 + nanos/1000000;
if (!msec) msec = 1;
}
event_wait_msec(&me.event, msec);
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | } else {
event_wait(&me.event);
}
mt_lock(m);
event_destroy(& me.event);
#ifdef PIKE_DEBUG
if(me.next)
Pike_fatal("Wait on event return prematurely!!\n");
#endif
return 0;
}
|
1f2133 | 2000-07-28 | Fredrik Hübinette (Hubbe) | | PMOD_EXPORT int co_signal(COND_T *c)
|
e42eaf | 1998-01-02 | Fredrik Hübinette (Hubbe) | | {
struct cond_t_queue *t;
mt_lock(& c->lock);
|
dc7cc9 | 1998-01-14 | Fredrik Hübinette (Hubbe) | | if((t=c->head))
|
e42eaf | 1998-01-02 | Fredrik Hübinette (Hubbe) | | {
c->head=t->next;
t->next=0;
if(!c->head) c->tail=0;
}
mt_unlock(& c->lock);
if(t)
event_signal(& t->event);
return 0;
}
|
1f2133 | 2000-07-28 | Fredrik Hübinette (Hubbe) | | PMOD_EXPORT int co_broadcast(COND_T *c)
|
e42eaf | 1998-01-02 | Fredrik Hübinette (Hubbe) | | {
struct cond_t_queue *t,*n;
mt_lock(& c->lock);
n=c->head;
c->head=c->tail=0;
mt_unlock(& c->lock);
while((t=n))
{
n=t->next;
|
dc7cc9 | 1998-01-14 | Fredrik Hübinette (Hubbe) | | t->next=0;
|
e42eaf | 1998-01-02 | Fredrik Hübinette (Hubbe) | | event_signal(& t->event);
}
return 0;
}
|
1f2133 | 2000-07-28 | Fredrik Hübinette (Hubbe) | | PMOD_EXPORT int co_destroy(COND_T *c)
|
e42eaf | 1998-01-02 | Fredrik Hübinette (Hubbe) | | {
struct cond_t_queue *t;
mt_lock(& c->lock);
|
b1f4eb | 1998-01-13 | Fredrik Hübinette (Hubbe) | | t=c->head;
mt_unlock(& c->lock);
if(t) return -1;
mt_destroy(& c->lock);
|
e42eaf | 1998-01-02 | Fredrik Hübinette (Hubbe) | | return 0;
}
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | #else /* !SIMULATE_COND_WITH_EVENT */
|
3d70c5 | 2009-01-25 | Henrik Grubbström (Grubba) | | #ifndef CONFIGURE_TEST
|
91518c | 2009-03-15 | Martin Stjernholm | | PMOD_EXPORT int co_wait_timeout(COND_T *c, PIKE_MUTEX_T *m, long s, long nanos)
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | {
|
f01020 | 2011-11-16 | Tobias S. Josefowitz | | struct timeval ct;
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | #ifdef POSIX_THREADS
struct timespec timeout;
#ifdef HAVE_PTHREAD_COND_RELTIMEDWAIT_NP
timeout.tv_sec = s;
timeout.tv_nsec = nanos;
return pthread_cond_reltimedwait_np(c, m, &timeout);
#else /* !HAVE_PTHREAD_COND_RELTIMEDWAIT_NP */
|
f01020 | 2011-11-16 | Tobias S. Josefowitz | | ACCURATE_GETTIMEOFDAY(&ct);
timeout.tv_sec = ct.tv_sec + s;
timeout.tv_nsec = ct.tv_usec * 1000 + nanos;
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | return pthread_cond_timedwait(c, m, &timeout);
#endif /* HAVE_PTHREAD_COND_RELTIMEDWAIT_NP */
#else /* !POSIX_THREADS */
|
d2a3f0 | 2009-01-25 | Henrik Grubbström (Grubba) | | #error co_wait_timeout does not support this thread model.
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | #endif /* POSIX_THREADS */
}
|
3d70c5 | 2009-01-25 | Henrik Grubbström (Grubba) | | #endif /* !CONFIGURE_TEST */
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | |
#endif /* SIMULATE_COND_WITH_EVENT */
|
e42eaf | 1998-01-02 | Fredrik Hübinette (Hubbe) | |
|
83b184 | 2003-02-08 | Martin Stjernholm | | #ifdef POSIX_THREADS
pthread_attr_t pattr;
pthread_attr_t small_pattr;
#endif
static void really_low_th_init(void)
{
#ifdef SGI_SPROC_THREADS
#error /* Need to specify a filename */
us_cookie = usinit("");
#endif /* SGI_SPROC_THREADS */
#ifdef POSIX_THREADS
#ifdef HAVE_PTHREAD_INIT
pthread_init();
#endif /* HAVE_PTHREAD_INIT */
#endif /* POSIX_THREADS */
#ifdef POSIX_THREADS
pthread_attr_init(&pattr);
#ifndef CONFIGURE_TEST
#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
pthread_attr_setstacksize(&pattr, thread_stack_size);
#endif
#endif
pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
pthread_attr_init(&small_pattr);
#ifdef HAVE_PTHREAD_ATTR_SETSTACKSIZE
pthread_attr_setstacksize(&small_pattr, 4096*sizeof(char *));
#endif
pthread_attr_setdetachstate(&small_pattr, PTHREAD_CREATE_DETACHED);
#endif
}
|
0a14c2 | 2008-08-05 | Martin Stjernholm | | static void cleanup_thread_state (struct thread_state *th);
|
83b184 | 2003-02-08 | Martin Stjernholm | | #ifndef CONFIGURE_TEST
|
e42eaf | 1998-01-02 | Fredrik Hübinette (Hubbe) | |
|
8bfefe | 2014-09-04 | Martin Nilsson | | #if defined (RDTSC) || \
|
59e827 | 2010-10-17 | Martin Stjernholm | | (!defined(HAVE_GETHRTIME) && \
|
8bfefe | 2014-09-04 | Martin Nilsson | | !(defined(HAVE_MACH_TASK_INFO_H) && defined(TASK_THREAD_TIMES_INFO)))
|
91518c | 2009-03-15 | Martin Stjernholm | | static clock_t thread_start_clock = 0;
static THREAD_T last_clocked_thread = 0;
#define USE_CLOCK_FOR_SLICES
|
da6644 | 2010-10-23 | Martin Stjernholm | | #ifdef RDTSC
static int use_tsc_for_slices;
#define TSC_START_INTERVAL 100000
|
e03e2c | 2011-04-02 | Martin Stjernholm | | static INT64 prev_tsc;
|
a771ee | 2010-10-24 | Martin Stjernholm | | static clock_t prev_clock;
|
da6644 | 2010-10-23 | Martin Stjernholm | | #endif
|
91518c | 2009-03-15 | Martin Stjernholm | | #endif
|
17f08c | 2000-07-06 | Fredrik Hübinette (Hubbe) | | #define THIS_THREAD ((struct thread_state *)CURRENT_STORAGE)
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | | static struct callback *threads_evaluator_callback=0;
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | |
|
91518c | 2009-03-15 | Martin Stjernholm | | PMOD_EXPORT int num_threads = 1;
PMOD_EXPORT int threads_disabled = 0;
|
fb7d86 | 2015-06-01 | Henrik Grubbström (Grubba) | | PMOD_EXPORT cpu_time_t threads_disabled_acc_time = 0;
PMOD_EXPORT cpu_time_t threads_disabled_start = 0;
|
91518c | 2009-03-15 | Martin Stjernholm | |
|
c91f89 | 2000-04-19 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
9c4f69 | 2020-07-05 | Henrik Grubbström (Grubba) | |
|
716785 | 2021-05-16 | Henrik Grubbström (Grubba) | | THREAD_T threads_disabled_thread = 0;
|
c91f89 | 2000-04-19 | Martin Stjernholm | | #endif
|
c5f4e2 | 2002-09-14 | Martin Stjernholm | | #ifdef INTERNAL_PROFILING
PMOD_EXPORT unsigned long thread_yields = 0;
#endif
|
91518c | 2009-03-15 | Martin Stjernholm | | static int th_running = 0;
|
74ea78 | 2016-01-29 | Martin Nilsson | | static PIKE_MUTEX_T interpreter_lock;
static PIKE_MUTEX_T interpreter_lock_wanted;
PIKE_MUTEX_T thread_table_lock;
static PIKE_MUTEX_T interleave_lock;
|
5c2f2f | 2018-09-16 | Henrik Grubbström (Grubba) | | static struct program *mutex_program = NULL;
|
91518c | 2009-03-15 | Martin Stjernholm | | static struct program *mutex_key = 0;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | static struct program *rwmutex_program = NULL;
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | static struct program *rwmutex_key_program = NULL;
|
f327f2 | 2018-09-23 | Henrik Grubbström (Grubba) | | static struct program *condition_program = NULL;
|
fa8c69 | 2000-11-30 | Fredrik Hübinette (Hubbe) | | PMOD_EXPORT struct program *thread_id_prog = 0;
|
91518c | 2009-03-15 | Martin Stjernholm | | static struct program *thread_local_prog = 0;
|
89fc4c | 2000-08-10 | Henrik Grubbström (Grubba) | | PMOD_EXPORT ptrdiff_t thread_storage_offset;
|
91518c | 2009-03-15 | Martin Stjernholm | | static int live_threads = 0;
static COND_T live_threads_change;
static COND_T threads_disabled_change;
|
621e75 | 2015-10-19 | Per Hedbor | | struct thread_local_var
|
91518c | 2009-03-15 | Martin Stjernholm | | {
INT32 id;
};
static volatile IMUTEX_T *interleave_list = NULL;
#define THREADSTATE2OBJ(X) ((X)->thread_obj)
|
fcca61 | 2016-02-11 | Martin Nilsson | | #ifdef PIKE_DEBUG
|
91518c | 2009-03-15 | Martin Stjernholm | |
|
ca39b5 | 2010-10-31 | Martin Stjernholm | | * is held by the current thread. */
static int debug_is_locked;
|
91518c | 2009-03-15 | Martin Stjernholm | | static THREAD_T debug_locking_thread;
|
ca39b5 | 2010-10-31 | Martin Stjernholm | | #define SET_LOCKING_THREAD (debug_is_locked = 1, \
debug_locking_thread = th_self())
#define UNSET_LOCKING_THREAD (debug_is_locked = 0)
|
01b921 | 2016-01-12 | Per Hedbor | | static void check_interpreter_lock (DLOC_DECL)
|
91518c | 2009-03-15 | Martin Stjernholm | | {
if (th_running) {
THREAD_T self;
|
ca39b5 | 2010-10-31 | Martin Stjernholm | | if (!debug_is_locked)
|
91518c | 2009-03-15 | Martin Stjernholm | | pike_fatal_dloc ("Interpreter not locked.\n");
self = th_self();
if (!th_equal (debug_locking_thread, self))
pike_fatal_dloc ("Interpreter not locked by this thread.\n");
}
}
|
d55914 | 2017-07-17 | Martin Nilsson | | static UINT64 thread_swaps = 0;
static UINT64 check_threads_calls = 0;
static UINT64 check_threads_yields = 0;
static UINT64 check_threads_swaps = 0;
|
e8989c | 2014-08-22 | Arne Goedeke | | static void f__thread_swaps (INT32 UNUSED(args))
|
15ecdc | 2011-04-02 | Martin Stjernholm | | {push_ulongest (thread_swaps);}
|
e8989c | 2014-08-22 | Arne Goedeke | | static void f__check_threads_calls (INT32 UNUSED(args))
|
15ecdc | 2011-04-02 | Martin Stjernholm | | {push_ulongest (check_threads_calls);}
|
e8989c | 2014-08-22 | Arne Goedeke | | static void f__check_threads_yields (INT32 UNUSED(args))
|
15ecdc | 2011-04-02 | Martin Stjernholm | | {push_ulongest (check_threads_yields);}
|
e8989c | 2014-08-22 | Arne Goedeke | | static void f__check_threads_swaps (INT32 UNUSED(args))
|
15ecdc | 2011-04-02 | Martin Stjernholm | | {push_ulongest (check_threads_swaps);}
|
91518c | 2009-03-15 | Martin Stjernholm | | #else
#define SET_LOCKING_THREAD 0
|
ca39b5 | 2010-10-31 | Martin Stjernholm | | #define UNSET_LOCKING_THREAD 0
|
91518c | 2009-03-15 | Martin Stjernholm | |
|
fcca61 | 2016-02-11 | Martin Nilsson | | #endif /* PIKE_DEBUG */
|
91518c | 2009-03-15 | Martin Stjernholm | |
|
01b921 | 2016-01-12 | Per Hedbor | | PMOD_EXPORT void pike_low_lock_interpreter (DLOC_DECL)
|
91518c | 2009-03-15 | Martin Stjernholm | | {
|
63ba77 | 2010-10-12 | Martin Stjernholm | |
mt_lock (&interpreter_lock_wanted);
|
91518c | 2009-03-15 | Martin Stjernholm | | mt_lock (&interpreter_lock);
|
63ba77 | 2010-10-12 | Martin Stjernholm | | mt_unlock (&interpreter_lock_wanted);
|
91518c | 2009-03-15 | Martin Stjernholm | | SET_LOCKING_THREAD;
|
9a8ddb | 2014-11-16 | Henrik Grubbström (Grubba) | | USE_DLOC_ARGS();
|
a22995 | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF (1, "Got iplock @ %s:%d\n", DLOC_ARGS_OPT);
|
91518c | 2009-03-15 | Martin Stjernholm | | }
|
01b921 | 2016-01-12 | Per Hedbor | | PMOD_EXPORT void pike_low_wait_interpreter (COND_T *cond COMMA_DLOC_DECL)
|
91518c | 2009-03-15 | Martin Stjernholm | | {
|
9a8ddb | 2014-11-16 | Henrik Grubbström (Grubba) | | USE_DLOC_ARGS();
|
a22995 | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF (1, "Waiting on cond %p without iplock @ %s:%d\n",
|
7d06ba | 2016-02-07 | Martin Nilsson | | cond, DLOC_ARGS_OPT);
|
ca39b5 | 2010-10-31 | Martin Stjernholm | | UNSET_LOCKING_THREAD;
|
63ba77 | 2010-10-12 | Martin Stjernholm | |
|
91518c | 2009-03-15 | Martin Stjernholm | | co_wait (cond, &interpreter_lock);
|
63ba77 | 2010-10-12 | Martin Stjernholm | |
|
91518c | 2009-03-15 | Martin Stjernholm | | SET_LOCKING_THREAD;
|
a22995 | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF (1, "Got signal on cond %p with iplock @ %s:%d\n",
|
7d06ba | 2016-02-07 | Martin Nilsson | | cond, DLOC_ARGS_OPT);
|
91518c | 2009-03-15 | Martin Stjernholm | | }
|
01b921 | 2016-01-12 | Per Hedbor | | PMOD_EXPORT int pike_low_timedwait_interpreter (COND_T *cond,
|
91518c | 2009-03-15 | Martin Stjernholm | | long sec, long nsec
COMMA_DLOC_DECL)
{
int res;
|
9a8ddb | 2014-11-16 | Henrik Grubbström (Grubba) | | USE_DLOC_ARGS();
|
a22995 | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF (1, "Waiting on cond %p without iplock @ %s:%d\n",
|
7d06ba | 2016-02-07 | Martin Nilsson | | cond, DLOC_ARGS_OPT);
|
ca39b5 | 2010-10-31 | Martin Stjernholm | | UNSET_LOCKING_THREAD;
|
63ba77 | 2010-10-12 | Martin Stjernholm | |
|
91518c | 2009-03-15 | Martin Stjernholm | | res = co_wait_timeout (cond, &interpreter_lock, sec, nsec);
|
63ba77 | 2010-10-12 | Martin Stjernholm | |
|
91518c | 2009-03-15 | Martin Stjernholm | | SET_LOCKING_THREAD;
|
a22995 | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF (1, "Got signal on cond %p with iplock @ %s:%d\n",
|
7d06ba | 2016-02-07 | Martin Nilsson | | cond, DLOC_ARGS_OPT);
|
91518c | 2009-03-15 | Martin Stjernholm | | return res;
}
static void threads_disabled_wait (DLOC_DECL)
{
assert (threads_disabled);
|
9a8ddb | 2014-11-16 | Henrik Grubbström (Grubba) | | USE_DLOC_ARGS();
|
91518c | 2009-03-15 | Martin Stjernholm | | do {
|
a22995 | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF (1, "Waiting on threads_disabled @ %s:%d\n",
|
7d06ba | 2016-02-07 | Martin Nilsson | | DLOC_ARGS_OPT);
|
ca39b5 | 2010-10-31 | Martin Stjernholm | | UNSET_LOCKING_THREAD;
|
91518c | 2009-03-15 | Martin Stjernholm | | co_wait (&threads_disabled_change, &interpreter_lock);
SET_LOCKING_THREAD;
} while (threads_disabled);
|
a22995 | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF (1, "Continue after threads_disabled @ %s:%d\n",
|
7d06ba | 2016-02-07 | Martin Nilsson | | DLOC_ARGS_OPT);
|
91518c | 2009-03-15 | Martin Stjernholm | | }
|
01b921 | 2016-01-12 | Per Hedbor | | PMOD_EXPORT void pike_lock_interpreter (DLOC_DECL)
|
91518c | 2009-03-15 | Martin Stjernholm | | {
pike_low_lock_interpreter (DLOC_ARGS_OPT);
if (threads_disabled) threads_disabled_wait (DLOC_ARGS_OPT);
}
|
01b921 | 2016-01-12 | Per Hedbor | | PMOD_EXPORT void pike_unlock_interpreter (DLOC_DECL)
|
91518c | 2009-03-15 | Martin Stjernholm | | {
|
9a8ddb | 2014-11-16 | Henrik Grubbström (Grubba) | | USE_DLOC_ARGS();
|
a22995 | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF (1, "Releasing iplock @ %s:%d\n", DLOC_ARGS_OPT);
|
ca39b5 | 2010-10-31 | Martin Stjernholm | | UNSET_LOCKING_THREAD;
|
91518c | 2009-03-15 | Martin Stjernholm | | mt_unlock (&interpreter_lock);
}
|
01b921 | 2016-01-12 | Per Hedbor | | PMOD_EXPORT void pike_wait_interpreter (COND_T *cond COMMA_DLOC_DECL)
|
91518c | 2009-03-15 | Martin Stjernholm | | {
|
8d3d58 | 2013-02-18 | Henrik Grubbström (Grubba) | | int owner = threads_disabled;
|
91518c | 2009-03-15 | Martin Stjernholm | | pike_low_wait_interpreter (cond COMMA_DLOC_ARGS_OPT);
|
1c9388 | 2017-08-10 | Henrik Grubbström (Grubba) | | if (!owner && threads_disabled) {
threads_disabled_wait (DLOC_ARGS_OPT);
}
|
91518c | 2009-03-15 | Martin Stjernholm | | }
|
01b921 | 2016-01-12 | Per Hedbor | | PMOD_EXPORT int pike_timedwait_interpreter (COND_T *cond,
|
91518c | 2009-03-15 | Martin Stjernholm | | long sec, long nsec
COMMA_DLOC_DECL)
{
|
cb0446 | 2013-02-18 | Henrik Grubbström (Grubba) | | int owner = threads_disabled;
|
91518c | 2009-03-15 | Martin Stjernholm | | int res = pike_low_timedwait_interpreter (cond, sec, nsec
COMMA_DLOC_ARGS_OPT);
|
1c9388 | 2017-08-10 | Henrik Grubbström (Grubba) | | if (!owner && threads_disabled) {
threads_disabled_wait (DLOC_ARGS_OPT);
}
|
91518c | 2009-03-15 | Martin Stjernholm | | return res;
}
PMOD_EXPORT void pike_init_thread_state (struct thread_state *ts)
{
|
d97eb7 | 2011-07-10 | Henrik Grubbström (Grubba) | |
|
91518c | 2009-03-15 | Martin Stjernholm | | Pike_interpreter.thread_state = ts;
ts->state = Pike_interpreter;
|
d97eb7 | 2011-07-10 | Henrik Grubbström (Grubba) | | Pike_interpreter_pointer = &ts->state;
|
91518c | 2009-03-15 | Martin Stjernholm | | ts->id = th_self();
ts->status = THREAD_RUNNING;
ts->swapped = 0;
|
7a5298 | 2015-09-09 | Henrik Grubbström (Grubba) | | ts->interval_start = get_real_time();
|
91518c | 2009-03-15 | Martin Stjernholm | | #ifdef PIKE_DEBUG
ts->debug_flags = 0;
|
15ecdc | 2011-04-02 | Martin Stjernholm | | thread_swaps++;
|
91518c | 2009-03-15 | Martin Stjernholm | | #endif
|
7ee4aa | 2002-09-14 | Martin Stjernholm | | #ifdef USE_CLOCK_FOR_SLICES
|
da6644 | 2010-10-23 | Martin Stjernholm | |
|
91518c | 2009-03-15 | Martin Stjernholm | | thread_start_clock = 0;
last_clocked_thread = ts->id;
|
da6644 | 2010-10-23 | Martin Stjernholm | | #ifdef RDTSC
prev_tsc = 0;
#endif
|
d0aa0d | 2011-04-02 | Martin Stjernholm | | #ifdef PROFILE_CHECK_THREADS
|
fa7766 | 2016-02-11 | Martin Nilsson | | WERR("[%d:%f] pike_init_thread_state: tsc reset\n",
getpid(), get_real_time() * (1.0 / CPU_TIME_TICKS));
|
d0aa0d | 2011-04-02 | Martin Stjernholm | | #endif
|
91518c | 2009-03-15 | Martin Stjernholm | | #endif
}
PMOD_EXPORT void pike_swap_out_thread (struct thread_state *ts
COMMA_DLOC_DECL)
{
|
9a8ddb | 2014-11-16 | Henrik Grubbström (Grubba) | | USE_DLOC_ARGS();
|
a22995 | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF (2, "Swap out %sthread %p @ %s:%d\n",
|
7d06ba | 2016-02-07 | Martin Nilsson | | ts == Pike_interpreter.thread_state ? "current " : "",
ts, DLOC_ARGS_OPT);
|
91518c | 2009-03-15 | Martin Stjernholm | |
#ifdef PROFILING
if (!ts->swapped) {
cpu_time_t now = get_cpu_time();
|
ec4131 | 2016-02-11 | Martin Nilsson | | W_PROFILING_DEBUG("%p: Swap out at: %" PRINT_CPU_TIME
" unlocked: %" PRINT_CPU_TIME "\n",
ts, now, ts->state.unlocked_time);
|
91518c | 2009-03-15 | Martin Stjernholm | | ts->state.unlocked_time -= now;
}
|
7ee4aa | 2002-09-14 | Martin Stjernholm | | #endif
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | |
|
91518c | 2009-03-15 | Martin Stjernholm | | ts->swapped=1;
|
d97eb7 | 2011-07-10 | Henrik Grubbström (Grubba) | | Pike_interpreter_pointer = NULL;
|
91518c | 2009-03-15 | Martin Stjernholm | | }
PMOD_EXPORT void pike_swap_in_thread (struct thread_state *ts
COMMA_DLOC_DECL)
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | {
|
a22995 | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF (2, "Swap in thread %p @ %s:%d\n", ts, DLOC_ARGS_OPT);
|
d86cd7 | 1998-08-24 | Marcus Comstedt | |
|
91518c | 2009-03-15 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
d97eb7 | 2011-07-10 | Henrik Grubbström (Grubba) | | if (Pike_interpreter_pointer)
|
91518c | 2009-03-15 | Martin Stjernholm | | pike_fatal_dloc ("Thread %"PRINTSIZET"x swapped in "
"over existing thread %"PRINTSIZET"x.\n",
(size_t) ts->id,
(size_t) (Pike_interpreter.thread_state ?
Pike_interpreter.thread_state->id : 0));
#endif
#ifdef PROFILING
if (ts->swapped) {
cpu_time_t now = get_cpu_time();
|
ec4131 | 2016-02-11 | Martin Nilsson | | W_PROFILING_DEBUG("%p: Swap in at: %" PRINT_CPU_TIME
" unlocked: %" PRINT_CPU_TIME "\n",
ts, now, ts->state.unlocked_time);
|
91518c | 2009-03-15 | Martin Stjernholm | | ts->state.unlocked_time += now;
}
#endif
ts->swapped=0;
|
d97eb7 | 2011-07-10 | Henrik Grubbström (Grubba) | | Pike_interpreter_pointer = &ts->state;
|
15ecdc | 2011-04-02 | Martin Stjernholm | | #ifdef PIKE_DEBUG
thread_swaps++;
#endif
|
91518c | 2009-03-15 | Martin Stjernholm | |
#ifdef USE_CLOCK_FOR_SLICES
if (last_clocked_thread != ts->id) {
thread_start_clock = clock();
last_clocked_thread = ts->id;
|
da6644 | 2010-10-23 | Martin Stjernholm | | #ifdef RDTSC
RDTSC (prev_tsc);
|
a771ee | 2010-10-24 | Martin Stjernholm | | prev_clock = thread_start_clock;
|
da6644 | 2010-10-23 | Martin Stjernholm | | #endif
|
91518c | 2009-03-15 | Martin Stjernholm | | }
#endif
}
PMOD_EXPORT void pike_swap_in_current_thread (struct thread_state *ts
COMMA_DLOC_DECL)
{
#ifdef PIKE_DEBUG
THREAD_T self = th_self();
if (!th_equal (ts->id, self))
pike_fatal_dloc ("Swapped in thread state %p into wrong thread "
"%"PRINTSIZET"x - should be %"PRINTSIZET"x.\n",
ts, th_self(), ts->id);
#endif
pike_swap_in_thread (ts COMMA_DLOC_ARGS_OPT);
}
#ifdef PIKE_DEBUG
PMOD_EXPORT void pike_assert_thread_swapped_in (DLOC_DECL)
{
struct thread_state *ts=thread_state_for_id(th_self());
if(ts->swapped)
pike_fatal_dloc ("Thread is not swapped in.\n");
if (ts->debug_flags & THREAD_DEBUG_LOOSE)
pike_fatal_dloc ("Current thread is not bound to the interpreter. "
"Nested use of ALLOW_THREADS()?\n");
}
PMOD_EXPORT void pike_debug_check_thread (DLOC_DECL)
{
struct thread_state *ts=thread_state_for_id(th_self());
if (ts->debug_flags & THREAD_DEBUG_LOOSE)
pike_fatal_dloc ("Current thread is not bound to the interpreter. "
"Nested use of ALLOW_THREADS()?\n");
if(ts != Pike_interpreter.thread_state) {
debug_list_all_threads();
Pike_fatal ("Thread states mixed up between threads.\n");
}
check_interpreter_lock (DLOC_ARGS_OPT);
}
#endif /* PIKE_DEBUG */
|
7a5298 | 2015-09-09 | Henrik Grubbström (Grubba) | |
|
91518c | 2009-03-15 | Martin Stjernholm | | PMOD_EXPORT void pike_threads_allow (struct thread_state *ts COMMA_DLOC_DECL)
{
|
b2190b | 2017-04-27 | Henrik Grubbström (Grubba) | |
|
91518c | 2009-03-15 | Martin Stjernholm | | if (!ts) return;
|
7a5298 | 2015-09-09 | Henrik Grubbström (Grubba) | | if (UNLIKELY(thread_quanta > 0)) {
cpu_time_t now = get_real_time();
if (UNLIKELY((now - ts->interval_start) > thread_quanta) &&
LIKELY(ts->thread_obj)) {
ref_push_object(ts->thread_obj);
push_int64(now - ts->interval_start);
ts->interval_start = now;
#ifndef LONG_CPU_TIME
push_int(1000000000 / CPU_TIME_TICKS);
o_multiply();
#endif
SAFE_APPLY_MASTER("thread_quanta_exceeded", 2);
pop_stack();
}
}
|
91518c | 2009-03-15 | Martin Stjernholm | | #ifdef PIKE_DEBUG
pike_debug_check_thread (DLOC_ARGS_OPT);
if (Pike_in_gc > 50 && Pike_in_gc < 300)
pike_fatal_dloc ("Threads allowed during garbage collection (pass %d).\n",
Pike_in_gc);
ts->debug_flags |= THREAD_DEBUG_LOOSE;
#endif
if (num_threads > 1 && !threads_disabled) {
pike_swap_out_thread (ts COMMA_DLOC_ARGS_OPT);
pike_unlock_interpreter (DLOC_ARGS_OPT);
}
|
9d9fa2 | 2016-02-12 | Martin Nilsson | | #if defined (PIKE_DEBUG)
|
91518c | 2009-03-15 | Martin Stjernholm | | else {
THREAD_T self = th_self();
if (threads_disabled && !th_equal(threads_disabled_thread, self))
pike_fatal_dloc ("Threads allowed from a different thread "
"while threads are disabled. "
"(self: %"PRINTSIZET"x, disabler: %"PRINTSIZET"x)\n",
(size_t) self, (size_t) threads_disabled_thread);
}
#endif
}
PMOD_EXPORT void pike_threads_disallow (struct thread_state *ts COMMA_DLOC_DECL)
{
|
b2190b | 2017-04-27 | Henrik Grubbström (Grubba) | |
|
91518c | 2009-03-15 | Martin Stjernholm | | if (!ts) return;
if (ts->swapped) {
pike_lock_interpreter (DLOC_ARGS_OPT);
pike_swap_in_thread (ts COMMA_DLOC_ARGS_OPT);
}
|
7a5298 | 2015-09-09 | Henrik Grubbström (Grubba) | | if (UNLIKELY(thread_quanta)) {
ts->interval_start = get_real_time();
}
|
91518c | 2009-03-15 | Martin Stjernholm | | #ifdef PIKE_DEBUG
ts->debug_flags &= ~THREAD_DEBUG_LOOSE;
pike_debug_check_thread (DLOC_ARGS_OPT);
#endif
}
PMOD_EXPORT void pike_threads_allow_ext (struct thread_state *ts
COMMA_DLOC_DECL)
{
#ifdef DO_PIKE_CLEANUP
if (!ts) return;
#endif
|
7a5298 | 2015-09-09 | Henrik Grubbström (Grubba) | | if (UNLIKELY(thread_quanta > 0)) {
cpu_time_t now = get_real_time();
if (UNLIKELY((now - ts->interval_start) > thread_quanta) &&
LIKELY(ts->thread_obj)) {
ref_push_object(ts->thread_obj);
push_int64(now - ts->interval_start);
ts->interval_start = now;
#ifndef LONG_CPU_TIME
push_int(1000000000 / CPU_TIME_TICKS);
o_multiply();
#endif
SAFE_APPLY_MASTER("thread_quanta_exceeded", 2);
pop_stack();
}
}
|
91518c | 2009-03-15 | Martin Stjernholm | | #ifdef PIKE_DEBUG
pike_debug_check_thread (DLOC_ARGS_OPT);
if (Pike_in_gc > 50 && Pike_in_gc < 300)
pike_fatal_dloc ("Threads allowed during garbage collection (pass %d).\n",
Pike_in_gc);
ts->debug_flags |= THREAD_DEBUG_LOOSE;
#endif
if (num_threads > 1 && !threads_disabled) {
pike_swap_out_thread (ts COMMA_DLOC_ARGS_OPT);
live_threads++;
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF (1, "Increased live threads to %d\n", live_threads);
|
91518c | 2009-03-15 | Martin Stjernholm | | pike_unlock_interpreter (DLOC_ARGS_OPT);
}
|
9d9fa2 | 2016-02-12 | Martin Nilsson | | #if defined (PIKE_DEBUG)
|
91518c | 2009-03-15 | Martin Stjernholm | | else {
THREAD_T self = th_self();
if (threads_disabled && !th_equal(threads_disabled_thread, self))
pike_fatal_dloc ("Threads allowed from a different thread "
"while threads are disabled. "
"(self: %"PRINTSIZET"x, disabler: %"PRINTSIZET"x)\n",
(size_t) self, (size_t) threads_disabled_thread);
}
#endif
}
PMOD_EXPORT void pike_threads_disallow_ext (struct thread_state *ts
COMMA_DLOC_DECL)
{
#ifdef DO_PIKE_CLEANUP
if (!ts) return;
#endif
if (ts->swapped) {
pike_low_lock_interpreter (DLOC_ARGS_OPT);
live_threads--;
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF (1, "Decreased live threads to %d\n", live_threads);
|
91518c | 2009-03-15 | Martin Stjernholm | | co_broadcast (&live_threads_change);
if (threads_disabled) threads_disabled_wait (DLOC_ARGS_OPT);
pike_swap_in_thread (ts COMMA_DLOC_ARGS_OPT);
}
|
7a5298 | 2015-09-09 | Henrik Grubbström (Grubba) | | if (UNLIKELY(thread_quanta)) {
ts->interval_start = get_real_time();
}
|
91518c | 2009-03-15 | Martin Stjernholm | | #ifdef PIKE_DEBUG
ts->debug_flags &= ~THREAD_DEBUG_LOOSE;
pike_debug_check_thread (DLOC_ARGS_OPT);
#endif
}
PMOD_EXPORT void pike_lock_imutex (IMUTEX_T *im COMMA_DLOC_DECL)
{
struct thread_state *ts = Pike_interpreter.thread_state;
if (threads_disabled) return;
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "Locking IMutex %p...\n", im);
|
91518c | 2009-03-15 | Martin Stjernholm | | pike_threads_allow (ts COMMA_DLOC_ARGS_OPT);
mt_lock(&((im)->lock));
pike_threads_disallow (ts COMMA_DLOC_ARGS_OPT);
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(1, "Locked IMutex %p\n", im);
|
91518c | 2009-03-15 | Martin Stjernholm | | }
PMOD_EXPORT void pike_unlock_imutex (IMUTEX_T *im COMMA_DLOC_DECL)
{
if (threads_disabled) return;
|
9a8ddb | 2014-11-16 | Henrik Grubbström (Grubba) | | USE_DLOC_ARGS();
|
a22995 | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "Unlocking IMutex %p @ %s:%d\n",
|
7d06ba | 2016-02-07 | Martin Nilsson | | im, DLOC_ARGS_OPT);
|
91518c | 2009-03-15 | Martin Stjernholm | | mt_unlock(&(im->lock));
}
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | |
|
335a55 | 2001-11-02 | Martin Stjernholm | |
|
f328f1 | 1998-07-17 | Henrik Grubbström (Grubba) | | void low_init_threads_disable(void)
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | {
if (!threads_disabled) {
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "low_init_threads_disable(): Locking IM's...\n");
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | |
|
c20c4e | 2018-09-12 | Henrik Grubbström (Grubba) | | lock_pike_compiler();
|
b867f9 | 2003-02-16 | Martin Stjernholm | | if (Pike_interpreter.thread_state) {
|
2f748a | 1999-02-20 | Henrik Grubbström (Grubba) | |
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | IMUTEX_T *im;
THREADS_ALLOW();
mt_lock(&interleave_lock);
im = (IMUTEX_T *)interleave_list;
while(im) {
mt_lock(&(im->lock));
im = im->next;
}
THREADS_DISALLOW();
} else {
|
2f748a | 1999-02-20 | Henrik Grubbström (Grubba) | |
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | IMUTEX_T *im;
mt_lock(&interleave_lock);
im = (IMUTEX_T *)interleave_list;
while(im) {
mt_lock(&(im->lock));
im = im->next;
}
}
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "low_init_threads_disable(): Disabling threads.\n");
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | |
threads_disabled = 1;
|
fb7d86 | 2015-06-01 | Henrik Grubbström (Grubba) | | threads_disabled_start = get_real_time();
|
95c815 | 2001-11-01 | Martin Stjernholm | | #ifdef PIKE_DEBUG
threads_disabled_thread = th_self();
#endif
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | } else {
threads_disabled++;
}
|
f328f1 | 1998-07-17 | Henrik Grubbström (Grubba) | | THREADS_FPRINTF(0,
|
7d06ba | 2016-02-07 | Martin Nilsson | | "low_init_threads_disable(): threads_disabled:%d\n",
threads_disabled);
|
f328f1 | 1998-07-17 | Henrik Grubbström (Grubba) | | }
|
16df70 | 1998-07-16 | Fredrik Hübinette (Hubbe) | |
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | |
335a55 | 2001-11-02 | Martin Stjernholm | | *! This function first posts a notice to all threads that it is time
|
95ed62 | 2016-03-23 | Henrik Grubbström (Grubba) | | *! to halt. It then waits until all threads actually @b{have@} halted,
|
335a55 | 2001-11-02 | Martin Stjernholm | | *! and then then returns a lock object. All other threads will be
*! blocked from running until that object has been freed/destroyed.
*!
*! It's mainly useful to do things that require a temporary uid/gid
|
95ed62 | 2016-03-23 | Henrik Grubbström (Grubba) | | *! change, since on many OSes the effective user and group apply to
|
335a55 | 2001-11-02 | Martin Stjernholm | | *! all threads.
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *!
*! @note
|
335a55 | 2001-11-02 | Martin Stjernholm | | *! You should make sure that the returned object is freed even if
*! some kind of error is thrown. That means in practice that it
*! should only have references (direct or indirect) from function
*! local variables. Also, it shouldn't be referenced from cyclic
*! memory structures, since those are only destructed by the periodic
*! gc. (This advice applies to mutex locks in general, for that
*! matter.)
|
4b9aed | 2015-06-01 | Henrik Grubbström (Grubba) | | *!
*! @seealso
*! @[gethrdtime()]
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | */
|
74dfe8 | 2012-12-30 | Jonas Walldén | | void init_threads_disable(struct object *UNUSED(o))
|
f328f1 | 1998-07-17 | Henrik Grubbström (Grubba) | | {
|
d93787 | 2009-03-13 | Martin Stjernholm | | low_init_threads_disable();
|
f328f1 | 1998-07-17 | Henrik Grubbström (Grubba) | |
if(live_threads) {
SWAP_OUT_CURRENT_THREAD();
while (live_threads) {
|
91518c | 2009-03-15 | Martin Stjernholm | | THREADS_FPRINTF(1,
|
7d06ba | 2016-02-07 | Martin Nilsson | | "_disable_threads(): Waiting for %d threads to finish\n",
live_threads);
|
91518c | 2009-03-15 | Martin Stjernholm | | low_co_wait_interpreter (&live_threads_change);
|
16df70 | 1998-07-16 | Fredrik Hübinette (Hubbe) | | }
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "_disable_threads(): threads now disabled\n");
|
f328f1 | 1998-07-17 | Henrik Grubbström (Grubba) | | SWAP_IN_CURRENT_THREAD();
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | }
}
|
74dfe8 | 2012-12-30 | Jonas Walldén | | void exit_threads_disable(struct object *UNUSED(o))
|
de413f | 1998-03-26 | Per Hedbor | | {
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "exit_threads_disable(): threads_disabled:%d\n",
threads_disabled);
|
40e949 | 1998-07-05 | Henrik Grubbström (Grubba) | | if(threads_disabled) {
if(!--threads_disabled) {
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | IMUTEX_T *im = (IMUTEX_T *)interleave_list;
|
fb7d86 | 2015-06-01 | Henrik Grubbström (Grubba) | | threads_disabled_acc_time += get_real_time() - threads_disabled_start;
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | |
while(im) {
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "exit_threads_disable(): Unlocking IM %p\n", im);
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | mt_unlock(&(im->lock));
im = im->next;
}
|
bc3a9a | 2018-02-09 | Henrik Grubbström (Grubba) | | unlock_pike_compiler();
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | mt_unlock(&interleave_lock);
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "exit_threads_disable(): Wake up!\n");
|
2202fe | 1998-04-23 | Fredrik Hübinette (Hubbe) | | co_broadcast(&threads_disabled_change);
|
95c815 | 2001-11-01 | Martin Stjernholm | | #ifdef PIKE_DEBUG
threads_disabled_thread = 0;
#endif
|
40e949 | 1998-07-05 | Henrik Grubbström (Grubba) | | }
|
71f3a2 | 1998-11-22 | Fredrik Hübinette (Hubbe) | | #ifdef PIKE_DEBUG
|
40e949 | 1998-07-05 | Henrik Grubbström (Grubba) | | } else {
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal("exit_threads_disable() called too many times!\n");
|
71f3a2 | 1998-11-22 | Fredrik Hübinette (Hubbe) | | #endif /* PIKE_DEBUG */
|
40e949 | 1998-07-05 | Henrik Grubbström (Grubba) | | }
|
de413f | 1998-03-26 | Per Hedbor | | }
|
063fe3 | 1998-03-10 | Per Hedbor | |
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | void init_interleave_mutex(IMUTEX_T *im)
|
063fe3 | 1998-03-10 | Per Hedbor | | {
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | mt_init(&(im->lock));
|
6e1db5 | 1998-07-09 | Henrik Grubbström (Grubba) | |
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "init_interleave_mutex(): init_threads_disable()\n");
|
6e1db5 | 1998-07-09 | Henrik Grubbström (Grubba) | |
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | init_threads_disable(NULL);
|
6e1db5 | 1998-07-09 | Henrik Grubbström (Grubba) | |
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "init_interleave_mutex(): Locking IM %p\n", im);
|
6e1db5 | 1998-07-09 | Henrik Grubbström (Grubba) | |
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | |
mt_lock(&(im->lock));
im->next = (IMUTEX_T *)interleave_list;
if (interleave_list) {
interleave_list->prev = im;
|
6e1db5 | 1998-07-09 | Henrik Grubbström (Grubba) | | }
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | interleave_list = im;
im->prev = NULL;
|
6e1db5 | 1998-07-09 | Henrik Grubbström (Grubba) | |
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "init_interleave_mutex(): exit_threads_disable()\n");
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | |
exit_threads_disable(NULL);
}
void exit_interleave_mutex(IMUTEX_T *im)
{
init_threads_disable(NULL);
if (im->prev) {
im->prev->next = im->next;
} else {
interleave_list = im->next;
}
if (im->next) {
im->next->prev = im->prev;
|
ef1e93 | 1998-03-26 | Henrik Grubbström (Grubba) | | }
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | |
mt_unlock(&(im->lock));
exit_threads_disable(NULL);
|
063fe3 | 1998-03-10 | Per Hedbor | | }
|
eac209 | 1998-02-27 | Marcus Comstedt | |
|
f2c01e | 2003-01-08 | Martin Stjernholm | | struct thread_state *thread_table_chains[THREAD_TABLE_SIZE];
int num_pike_threads=0;
|
eac209 | 1998-02-27 | Marcus Comstedt | |
|
22ca07 | 1998-04-08 | Fredrik Hübinette (Hubbe) | | void thread_table_init(void)
|
eac209 | 1998-02-27 | Marcus Comstedt | | {
INT32 x;
for(x=0; x<THREAD_TABLE_SIZE; x++)
thread_table_chains[x] = NULL;
}
unsigned INT32 thread_table_hash(THREAD_T *tid)
{
|
d21327 | 1998-02-28 | Fredrik Hübinette (Hubbe) | | return th_hash(*tid) % THREAD_TABLE_SIZE;
|
eac209 | 1998-02-27 | Marcus Comstedt | | }
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | | PMOD_EXPORT void thread_table_insert(struct thread_state *s)
|
eac209 | 1998-02-27 | Marcus Comstedt | | {
unsigned INT32 h = thread_table_hash(&s->id);
|
71f3a2 | 1998-11-22 | Fredrik Hübinette (Hubbe) | | #ifdef PIKE_DEBUG
|
939b18 | 1998-07-17 | Fredrik Hübinette (Hubbe) | | if(h>=THREAD_TABLE_SIZE)
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal("thread_table_hash failed miserably!\n");
|
26cd94 | 1999-05-07 | Fredrik Hübinette (Hubbe) | | if(thread_state_for_id(s->id))
|
3be550 | 1999-06-08 | Fredrik Hübinette (Hubbe) | | {
if(thread_state_for_id(s->id) == s)
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal("Registring thread twice!\n");
|
3be550 | 1999-06-08 | Fredrik Hübinette (Hubbe) | | else
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal("Forgot to unregister thread!\n");
|
3be550 | 1999-06-08 | Fredrik Hübinette (Hubbe) | | }
|
939b18 | 1998-07-17 | Fredrik Hübinette (Hubbe) | | #endif
|
eac209 | 1998-02-27 | Marcus Comstedt | | mt_lock( & thread_table_lock );
|
56ac10 | 2000-03-29 | Fredrik Hübinette (Hubbe) | | num_pike_threads++;
|
eac209 | 1998-02-27 | Marcus Comstedt | | if((s->hashlink = thread_table_chains[h]) != NULL)
s->hashlink->backlink = &s->hashlink;
thread_table_chains[h] = s;
s->backlink = &thread_table_chains[h];
|
13670c | 2015-05-25 | Martin Nilsson | | mt_unlock( & thread_table_lock );
|
eac209 | 1998-02-27 | Marcus Comstedt | | }
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | | PMOD_EXPORT void thread_table_delete(struct thread_state *s)
|
eac209 | 1998-02-27 | Marcus Comstedt | | {
mt_lock( & thread_table_lock );
|
56ac10 | 2000-03-29 | Fredrik Hübinette (Hubbe) | | num_pike_threads--;
|
eac209 | 1998-02-27 | Marcus Comstedt | | if(s->hashlink != NULL)
s->hashlink->backlink = s->backlink;
*(s->backlink) = s->hashlink;
mt_unlock( & thread_table_lock );
}
|
1f2133 | 2000-07-28 | Fredrik Hübinette (Hubbe) | | PMOD_EXPORT struct thread_state *thread_state_for_id(THREAD_T tid)
|
eac209 | 1998-02-27 | Marcus Comstedt | | {
unsigned INT32 h = thread_table_hash(&tid);
|
17f08c | 2000-07-06 | Fredrik Hübinette (Hubbe) | | struct thread_state *s = NULL;
|
71f3a2 | 1998-11-22 | Fredrik Hübinette (Hubbe) | | #ifdef PIKE_DEBUG
|
939b18 | 1998-07-17 | Fredrik Hübinette (Hubbe) | | if(h>=THREAD_TABLE_SIZE)
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal("thread_table_hash failed miserably!\n");
|
939b18 | 1998-07-17 | Fredrik Hübinette (Hubbe) | | #endif
|
eac209 | 1998-02-27 | Marcus Comstedt | | mt_lock( & thread_table_lock );
|
d21327 | 1998-02-28 | Fredrik Hübinette (Hubbe) | | if(thread_table_chains[h] == NULL)
{
|
eac209 | 1998-02-27 | Marcus Comstedt | |
|
d21327 | 1998-02-28 | Fredrik Hübinette (Hubbe) | | }
else if(th_equal((s=thread_table_chains[h])->id, tid))
{
|
eac209 | 1998-02-27 | Marcus Comstedt | |
|
d21327 | 1998-02-28 | Fredrik Hübinette (Hubbe) | | }
else
{
|
eac209 | 1998-02-27 | Marcus Comstedt | | while((s = s->hashlink) != NULL)
|
d21327 | 1998-02-28 | Fredrik Hübinette (Hubbe) | | if(th_equal(s->id, tid))
|
eac209 | 1998-02-27 | Marcus Comstedt | | break;
if(s != NULL) {
|
ec2bab | 2000-06-24 | Fredrik Hübinette (Hubbe) | | |
eac209 | 1998-02-27 | Marcus Comstedt | | we want to search for it again */
if(s->hashlink != NULL)
s->hashlink->backlink = s->backlink;
*(s->backlink) = s->hashlink;
if((s->hashlink = thread_table_chains[h]) != NULL)
s->hashlink->backlink = &s->hashlink;
thread_table_chains[h] = s;
s->backlink = &thread_table_chains[h];
}
}
mt_unlock( & thread_table_lock );
return s;
}
|
048d23 | 2001-02-27 | Martin Stjernholm | | struct thread_state *gdb_thread_state_for_id(THREAD_T tid)
{
unsigned INT32 h = thread_table_hash(&tid);
struct thread_state *s;
for (s = thread_table_chains[h]; s != NULL; s = s->hashlink)
if(th_equal(s->id, tid))
break;
return s;
}
INT32 gdb_next_thread_state(INT32 prev, struct thread_state **ts)
{
if (!*ts || !(*ts)->hashlink) {
if (!*ts) prev = -1;
while (++prev < THREAD_TABLE_SIZE)
if ((*ts = thread_table_chains[prev]))
return prev;
*ts = NULL;
return 0;
}
*ts = (*ts)->hashlink;
return prev;
}
|
1f2133 | 2000-07-28 | Fredrik Hübinette (Hubbe) | | PMOD_EXPORT struct object *thread_for_id(THREAD_T tid)
|
eac209 | 1998-02-27 | Marcus Comstedt | | {
|
17f08c | 2000-07-06 | Fredrik Hübinette (Hubbe) | | struct thread_state *s = thread_state_for_id(tid);
|
26cd94 | 1999-05-07 | Fredrik Hübinette (Hubbe) | | return (s == NULL? NULL : THREADSTATE2OBJ(s));
|
eac209 | 1998-02-27 | Marcus Comstedt | |
}
|
ff2642 | 2018-08-07 | Tobias S. Josefowitz | | static inline void CALL_WITH_ERROR_HANDLING(struct thread_state *state,
void (*func)(void *ctx),
void *ctx)
{
JMP_BUF back;
if(SETJMP(back))
{
if(throw_severity <= THROW_ERROR) {
if (state->thread_obj) {
assign_svalue(&state->result, &throw_value);
}
call_handle_error();
}
if(throw_severity == THROW_EXIT)
{
pike_do_exit(throw_value.u.integer);
}
} else {
back.severity=THROW_EXIT;
func(ctx);
}
UNSETJMP(back);
}
|
2b42cc | 2007-10-06 | Marcus Comstedt | | PMOD_EXPORT void call_with_interpreter(void (*func)(void *ctx), void *ctx)
{
struct thread_state *state;
if((state = thread_state_for_id(th_self()))!=NULL) {
if(!state->swapped) {
|
dc4807 | 2008-12-27 | Henrik Grubbström (Grubba) | | #ifdef PIKE_DEBUG
int is_loose = state->debug_flags & THREAD_DEBUG_LOOSE;
state->debug_flags &= ~THREAD_DEBUG_LOOSE;
#endif
|
ff2642 | 2018-08-07 | Tobias S. Josefowitz | | CALL_WITH_ERROR_HANDLING(state, func, ctx);
|
dc4807 | 2008-12-27 | Henrik Grubbström (Grubba) | |
#ifdef PIKE_DEBUG
state->debug_flags |= is_loose;
#endif
|
2b42cc | 2007-10-06 | Marcus Comstedt | | } else {
mt_lock_interpreter();
SWAP_IN_THREAD(state);
|
dc4807 | 2008-12-27 | Henrik Grubbström (Grubba) | | DO_IF_DEBUG(state->debug_flags &= ~THREAD_DEBUG_LOOSE;)
|
2b42cc | 2007-10-06 | Marcus Comstedt | |
|
ff2642 | 2018-08-07 | Tobias S. Josefowitz | | CALL_WITH_ERROR_HANDLING(state, func, ctx);
|
2b42cc | 2007-10-06 | Marcus Comstedt | |
|
dc4807 | 2008-12-27 | Henrik Grubbström (Grubba) | | DO_IF_DEBUG(state->debug_flags |= THREAD_DEBUG_LOOSE;)
|
2b42cc | 2007-10-06 | Marcus Comstedt | | SWAP_OUT_THREAD(state);
mt_unlock_interpreter();
}
} else {
struct object *thread_obj;
|
d97eb7 | 2011-07-10 | Henrik Grubbström (Grubba) | | struct Pike_interpreter_struct new_interpreter;
|
2b42cc | 2007-10-06 | Marcus Comstedt | |
mt_lock_interpreter();
|
d97eb7 | 2011-07-10 | Henrik Grubbström (Grubba) | | Pike_interpreter_pointer = &new_interpreter;
|
2b42cc | 2007-10-06 | Marcus Comstedt | | init_interpreter();
Pike_interpreter.stack_top=((char *)&state)+ (thread_stack_size-16384) * STACK_DIRECTION;
Pike_interpreter.recoveries = NULL;
thread_obj = fast_clone_object(thread_id_prog);
INIT_THREAD_STATE((struct thread_state *)(thread_obj->storage +
thread_storage_offset));
num_threads++;
thread_table_insert(Pike_interpreter.thread_state);
|
ff2642 | 2018-08-07 | Tobias S. Josefowitz | | CALL_WITH_ERROR_HANDLING(Pike_interpreter.thread_state, func, ctx);
|
2b42cc | 2007-10-06 | Marcus Comstedt | |
cleanup_interpret();
Pike_interpreter.thread_state->status=THREAD_EXITED;
co_signal(&Pike_interpreter.thread_state->status_change);
thread_table_delete(Pike_interpreter.thread_state);
EXIT_THREAD_STATE(Pike_interpreter.thread_state);
Pike_interpreter.thread_state=NULL;
free_object(thread_obj);
thread_obj = NULL;
num_threads--;
|
cf13df | 2013-06-16 | Arne Goedeke | | #ifdef PIKE_DEBUG
Pike_interpreter_pointer = NULL;
#endif
|
8b91fc | 2018-08-08 | Henrik Grubbström (Grubba) | | mt_unlock_interpreter();
|
2b42cc | 2007-10-06 | Marcus Comstedt | | }
}
PMOD_EXPORT void enable_external_threads(void)
{
|
13670c | 2015-05-25 | Martin Nilsson | | num_threads++;
|
2b42cc | 2007-10-06 | Marcus Comstedt | | }
PMOD_EXPORT void disable_external_threads(void)
{
num_threads--;
}
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | |
|
95363a | 2000-04-11 | Fredrik Hübinette (Hubbe) | |
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | |
c7b7dd | 2001-10-28 | Martin Nilsson | | *! @[Thread()]
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | */
|
1f2133 | 2000-07-28 | Fredrik Hübinette (Hubbe) | | PMOD_EXPORT void f_all_threads(INT32 args)
|
eac209 | 1998-02-27 | Marcus Comstedt | | {
struct svalue *oldsp;
|
17f08c | 2000-07-06 | Fredrik Hübinette (Hubbe) | | struct thread_state *s;
|
eac209 | 1998-02-27 | Marcus Comstedt | |
pop_n_elems(args);
|
17f08c | 2000-07-06 | Fredrik Hübinette (Hubbe) | | oldsp = Pike_sp;
|
f2c01e | 2003-01-08 | Martin Stjernholm | | FOR_EACH_THREAD (s, {
|
26cd94 | 1999-05-07 | Fredrik Hübinette (Hubbe) | | struct object *o = THREADSTATE2OBJ(s);
|
88f320 | 2002-06-17 | Henrik Grubbström (Grubba) | | if (o) {
ref_push_object(o);
}
|
f2c01e | 2003-01-08 | Martin Stjernholm | | });
|
bd6739 | 2015-10-14 | Martin Nilsson | | f_aggregate(Pike_sp - oldsp);
|
eac209 | 1998-02-27 | Marcus Comstedt | | }
|
38e1e8 | 2001-11-08 | Fredrik Hübinette (Hubbe) | | #ifdef PIKE_DEBUG
|
00e668 | 2006-07-05 | Martin Stjernholm | | PMOD_EXPORT void debug_list_all_threads(void)
|
38e1e8 | 2001-11-08 | Fredrik Hübinette (Hubbe) | | {
INT32 x;
struct thread_state *s;
THREAD_T self = th_self();
|
fa7766 | 2016-02-11 | Martin Nilsson | | WERR("--Listing all threads--\n");
WERR("Current thread: %"PRINTSIZET"x\n", (size_t) self);
WERR("Current interpreter thread state: %p%s\n",
Pike_interpreter.thread_state,
Pike_interpreter.thread_state == (struct thread_state *) (ptrdiff_t) -1 ?
" (swapped)" : "");
WERR("Current thread state according to thread_state_for_id(): %p\n",
thread_state_for_id (self));
WERR("Current thread obj: %p\n",
(Pike_interpreter.thread_state &&
Pike_interpreter.thread_state != (struct thread_state *) (ptrdiff_t) -1) ?
Pike_interpreter.thread_state->thread_obj : NULL);
WERR("Current thread hash: %d\n",thread_table_hash(&self));
WERR("Current stack pointer: %p\n",&self);
|
38e1e8 | 2001-11-08 | Fredrik Hübinette (Hubbe) | | for(x=0; x<THREAD_TABLE_SIZE; x++)
{
for(s=thread_table_chains[x]; s; s=s->hashlink) {
struct object *o = THREADSTATE2OBJ(s);
|
fa7766 | 2016-02-11 | Martin Nilsson | | WERR("ThTab[%d]: state=%p, obj=%p, "
"swapped=%d, sp=%p (%+"PRINTPTRDIFFT"d), fp=%p, stackbase=%p, "
"id=%"PRINTSIZET"x\n",
x, s, o, s->swapped,
s->state.stack_pointer,
s->state.stack_pointer - s->state.evaluator_stack,
s->state.frame_pointer,
s->state.stack_top,
(size_t) s->id);
|
38e1e8 | 2001-11-08 | Fredrik Hübinette (Hubbe) | | }
}
|
fa7766 | 2016-02-11 | Martin Nilsson | | WERR("-----------------------\n");
|
38e1e8 | 2001-11-08 | Fredrik Hübinette (Hubbe) | | }
#endif
|
95363a | 2000-04-11 | Fredrik Hübinette (Hubbe) | |
|
1f2133 | 2000-07-28 | Fredrik Hübinette (Hubbe) | | PMOD_EXPORT int count_pike_threads(void)
|
56ac10 | 2000-03-29 | Fredrik Hübinette (Hubbe) | | {
return num_pike_threads;
}
|
eac209 | 1998-02-27 | Marcus Comstedt | |
|
2ea31a | 2016-02-22 | Henrik Grubbström (Grubba) | | #ifdef HAVE_GETHRTIME
union pike_hrtime {
INT64 val;
hrtime_t hrt;
};
#endif
|
74dfe8 | 2012-12-30 | Jonas Walldén | | static void check_threads(struct callback *UNUSED(cb), void *UNUSED(arg), void *UNUSED(arg2))
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | | {
|
0c2204 | 2008-11-18 | Martin Stjernholm | | #ifdef PROFILE_CHECK_THREADS
|
d0aa0d | 2011-04-02 | Martin Stjernholm | | static unsigned long calls = 0, yields = 0;
static unsigned long clock_checks = 0, no_clock_advs = 0;
|
a771ee | 2010-10-24 | Martin Stjernholm | | static unsigned long tps = 0, tps_int_n = 0;
static double tps_int_mean = 0.0, tps_int_m2 = 0.0;
|
0c2204 | 2008-11-18 | Martin Stjernholm | | calls++;
#endif
|
15ecdc | 2011-04-02 | Martin Stjernholm | | #ifdef PIKE_DEBUG
check_threads_calls++;
#endif
|
0c2204 | 2008-11-18 | Martin Stjernholm | |
|
59e827 | 2010-10-17 | Martin Stjernholm | | #if defined (USE_CLOCK_FOR_SLICES) && defined (PIKE_DEBUG)
if (last_clocked_thread != th_self())
Pike_fatal ("Stale thread %08lx in last_clocked_thread (self is %08lx)\n",
(unsigned long) last_clocked_thread, (unsigned long) th_self());
#endif
|
9d2116 | 2008-11-18 | Martin Stjernholm | |
|
92ec35 | 2010-10-23 | Martin Stjernholm | | #if defined(RDTSC) && defined(USE_CLOCK_FOR_SLICES)
|
2cf527 | 2010-10-17 | Artur Skawina | | |
f75624 | 2010-10-24 | Martin Stjernholm | | by using the TSC. */
|
2cf527 | 2010-10-17 | Artur Skawina | |
|
59e827 | 2010-10-17 | Martin Stjernholm | | if (use_tsc_for_slices) {
|
a771ee | 2010-10-24 | Martin Stjernholm | | static INT64 target_int = TSC_START_INTERVAL;
INT64 tsc_now, tsc_elapsed;
|
2cf527 | 2010-10-17 | Artur Skawina | |
|
da6644 | 2010-10-23 | Martin Stjernholm | |
|
2cf527 | 2010-10-17 | Artur Skawina | |
|
a771ee | 2010-10-24 | Martin Stjernholm | | RDTSC(tsc_now);
tsc_elapsed = tsc_now - prev_tsc;
|
da6644 | 2010-10-23 | Martin Stjernholm | |
|
a771ee | 2010-10-24 | Martin Stjernholm | | if (tsc_elapsed < target_int) {
|
da6644 | 2010-10-23 | Martin Stjernholm | | if (tsc_elapsed < 0) {
|
e9bda9 | 2010-10-22 | Martin Stjernholm | | #ifdef PROFILE_CHECK_THREADS
|
fa7766 | 2016-02-11 | Martin Nilsson | | WERR("[%d:%f] TSC backward jump detected "
"(now: %"PRINTINT64"d, prev: %"PRINTINT64"d, "
"target_int: %"PRINTINT64"d) - resetting\n",
getpid(), get_real_time() * (1.0 / CPU_TIME_TICKS),
tsc_now, prev_tsc, target_int);
|
e9bda9 | 2010-10-22 | Martin Stjernholm | | #endif
|
a771ee | 2010-10-24 | Martin Stjernholm | | target_int = TSC_START_INTERVAL;
|
da6644 | 2010-10-23 | Martin Stjernholm | | prev_tsc = 0;
|
e9bda9 | 2010-10-22 | Martin Stjernholm | | }
|
59e827 | 2010-10-17 | Martin Stjernholm | | else
return;
|
2cf527 | 2010-10-17 | Artur Skawina | | }
|
466caa | 2010-10-23 | Martin Stjernholm | | #ifdef PROFILE_CHECK_THREADS
clock_checks++;
|
a771ee | 2010-10-24 | Martin Stjernholm | | tps++;
#endif
{
clock_t clock_now = clock();
|
e03e2c | 2011-04-02 | Martin Stjernholm | | * slice length appreciably.
*
* Note that the real interval lengths will always be longer.
* One reason is that we won't get calls exactly when they run
* out. Another is the often lousy clock(3) resolution. */
|
a771ee | 2010-10-24 | Martin Stjernholm | |
if (prev_tsc) {
|
c0402d | 2012-07-23 | Jonas Walldén | | if (clock_now > prev_clock) {
|
a771ee | 2010-10-24 | Martin Stjernholm | | |
e03e2c | 2011-04-02 | Martin Stjernholm | | * ~20 tsc intervals.
*
* Note: The main source of the jumpiness is probably that
* clock(3) has so lousy resolution on many platforms, i.e.
* it may step forward very large intervals very seldom
* (100 times/sec on linux/glibc 2.x). It also has the
* effect that the actual tsc intervals will be closer to
* 1/200 sec. */
|
c0402d | 2012-07-23 | Jonas Walldén | | clock_t tsc_interval_time = clock_now - prev_clock;
|
a771ee | 2010-10-24 | Martin Stjernholm | | INT64 new_target_int =
(tsc_elapsed * (CLOCKS_PER_SEC / 400)) / tsc_interval_time;
|
634338 | 2011-04-02 | Martin Stjernholm | | if (new_target_int < target_int << 2)
|
a771ee | 2010-10-24 | Martin Stjernholm | | target_int = new_target_int;
else {
|
e03e2c | 2011-04-02 | Martin Stjernholm | |
|
a771ee | 2010-10-24 | Martin Stjernholm | | #ifdef PROFILE_CHECK_THREADS
|
fa7766 | 2016-02-11 | Martin Nilsson | | WERR("[%d:%f] Capping large TSC interval increase "
"(from %"PRINTINT64"d to %"PRINTINT64"d)\n",
getpid(), get_real_time() * (1.0 / CPU_TIME_TICKS),
target_int, new_target_int);
|
a771ee | 2010-10-24 | Martin Stjernholm | | #endif
|
634338 | 2011-04-02 | Martin Stjernholm | | target_int = (target_int << 2) + 1;
|
a771ee | 2010-10-24 | Martin Stjernholm | | }
prev_tsc = tsc_now;
prev_clock = clock_now;
|
1d1614 | 2016-02-11 | Martin Nilsson | | }
|
a771ee | 2010-10-24 | Martin Stjernholm | | else {
|
c0402d | 2012-07-23 | Jonas Walldén | | if (clock_now < prev_clock) {
|
a771ee | 2010-10-24 | Martin Stjernholm | |
prev_tsc = tsc_now;
prev_clock = clock_now;
}
target_int += tsc_elapsed;
#ifdef PROFILE_CHECK_THREADS
no_clock_advs++;
|
466caa | 2010-10-23 | Martin Stjernholm | | #endif
|
a771ee | 2010-10-24 | Martin Stjernholm | | }
|
64c566 | 2010-10-23 | Martin Stjernholm | | }
|
a771ee | 2010-10-24 | Martin Stjernholm | | else {
#ifdef PROFILE_CHECK_THREADS
|
fa7766 | 2016-02-11 | Martin Nilsson | | WERR("[%d:%f] Warning: Encountered zero prev_tsc "
"(thread_start_clock: %"PRINTINT64"d, "
"clock_now: %"PRINTINT64"d)\n",
getpid(), get_real_time() * (1.0 / CPU_TIME_TICKS),
(INT64) thread_start_clock, (INT64) clock_now);
|
a771ee | 2010-10-24 | Martin Stjernholm | | #endif
prev_tsc = tsc_now;
|
64c566 | 2010-10-23 | Martin Stjernholm | | }
|
a771ee | 2010-10-24 | Martin Stjernholm | |
|
c0402d | 2012-07-23 | Jonas Walldén | | if (clock_now < thread_start_clock)
|
a771ee | 2010-10-24 | Martin Stjernholm | |
thread_start_clock = 0;
else if (clock_now - thread_start_clock <
(clock_t) (CLOCKS_PER_SEC / 20))
return;
|
2cf527 | 2010-10-17 | Artur Skawina | | }
|
64c566 | 2010-10-23 | Martin Stjernholm | |
|
a771ee | 2010-10-24 | Martin Stjernholm | | #ifdef PROFILE_CHECK_THREADS
{
double delta = tps - tps_int_mean;
tps_int_n++;
tps_int_mean += delta / tps_int_n;
tps_int_m2 += delta * (tps - tps_int_mean);
tps = 0;
}
#endif
|
64c566 | 2010-10-23 | Martin Stjernholm | |
|
59e827 | 2010-10-17 | Martin Stjernholm | | goto do_yield;
|
2cf527 | 2010-10-17 | Artur Skawina | | }
|
92ec35 | 2010-10-23 | Martin Stjernholm | | #endif /* RDTSC && USE_CLOCK_FOR_SLICES */
|
59e827 | 2010-10-17 | Martin Stjernholm | |
#ifdef HAVE_GETHRTIME
|
7ee4aa | 2002-09-14 | Martin Stjernholm | | {
|
59d46a | 2016-02-22 | Henrik Grubbström (Grubba) | | static union pike_hrtime last_;
|
2ea31a | 2016-02-22 | Henrik Grubbström (Grubba) | | union pike_hrtime now;
now.hrt = gethrtime();
if( now.val-last_.val < 50000000 )
|
7ee4aa | 2002-09-14 | Martin Stjernholm | | return;
|
2ea31a | 2016-02-22 | Henrik Grubbström (Grubba) | | last_.val = now.val;
|
7ee4aa | 2002-09-14 | Martin Stjernholm | | }
|
82069a | 2003-11-26 | Henrik Grubbström (Grubba) | | #elif defined(HAVE_MACH_TASK_INFO_H) && defined(TASK_THREAD_TIMES_INFO)
|
08c53c | 2003-11-25 | Jonas Wallden | | {
static struct timeval last_check = { 0, 0 };
task_thread_times_info_data_t info;
mach_msg_type_number_t info_size = TASK_THREAD_TIMES_INFO_COUNT;
|
13670c | 2015-05-25 | Martin Nilsson | |
|
bc2a03 | 2009-04-21 | Jonas Wallden | |
|
576753 | 2009-04-21 | Jonas Wallden | | struct timeval tv;
|
c679ec | 2012-01-06 | Jonas Walldén | | ACCURATE_GETTIMEOFDAY(&tv);
{
|
576753 | 2009-04-21 | Jonas Wallden | | static INT64 real_time_last_check = 0;
INT64 real_time_now = tv.tv_sec * 1000000 + tv.tv_usec;
if (real_time_now - real_time_last_check < 35000)
return;
real_time_last_check = real_time_now;
}
|
13670c | 2015-05-25 | Martin Nilsson | |
|
9d2116 | 2008-11-18 | Martin Stjernholm | |
|
08c53c | 2003-11-25 | Jonas Wallden | | if (task_info(mach_task_self(), TASK_THREAD_TIMES_INFO,
(task_info_t) &info, &info_size) == 0) {
|
9d2116 | 2008-11-18 | Martin Stjernholm | | static INT64 last_check = 0;
INT64 now =
info.user_time.seconds * 1000000 +
info.user_time.microseconds +
info.system_time.seconds * 1000000 +
info.system_time.microseconds;
if (now - last_check < 50000)
return;
last_check = now;
|
08c53c | 2003-11-25 | Jonas Wallden | | }
}
|
7ee4aa | 2002-09-14 | Martin Stjernholm | | #elif defined (USE_CLOCK_FOR_SLICES)
|
b07fde | 2010-10-24 | Martin Stjernholm | | {
clock_t clock_now = clock();
|
c0402d | 2012-07-23 | Jonas Walldén | | if (clock_now < thread_start_clock)
|
b07fde | 2010-10-24 | Martin Stjernholm | |
thread_start_clock = 0;
else if (clock_now - thread_start_clock < (clock_t) (CLOCKS_PER_SEC / 20))
return;
}
|
0c2204 | 2008-11-18 | Martin Stjernholm | | #else
static int div_;
if(div_++ & 255)
return;
|
319fb1 | 2002-09-14 | Martin Stjernholm | | #endif
|
0a861b | 1997-09-17 | Fredrik Hübinette (Hubbe) | |
|
59e827 | 2010-10-17 | Martin Stjernholm | | do_yield:;
|
15ecdc | 2011-04-02 | Martin Stjernholm | | #ifdef PIKE_DEBUG
check_threads_yields++;
#endif
|
59e827 | 2010-10-17 | Martin Stjernholm | |
|
0c2204 | 2008-11-18 | Martin Stjernholm | | #ifdef PROFILE_CHECK_THREADS
{
static long last_time;
struct timeval now;
|
466caa | 2010-10-23 | Martin Stjernholm | |
|
d0aa0d | 2011-04-02 | Martin Stjernholm | | yields++;
|
f01020 | 2011-11-16 | Tobias S. Josefowitz | | ACCURATE_GETTIMEOFDAY (&now);
|
0c2204 | 2008-11-18 | Martin Stjernholm | | if (now.tv_sec > last_time) {
|
fa7766 | 2016-02-11 | Martin Nilsson | | WERR("[%d:%f] check_threads: %lu calls, "
"%lu clocks, %lu no advs, %lu yields"
", tps %g:%.1e\n",
getpid(), get_real_time() * (1.0 / CPU_TIME_TICKS),
calls, clock_checks, no_clock_advs, yields,
tps_int_mean,
tps_int_n > 1 ? sqrt (tps_int_m2 / (tps_int_n - 1)) : 0.0);
|
0c2204 | 2008-11-18 | Martin Stjernholm | | last_time = (unsigned long) now.tv_sec;
|
d0aa0d | 2011-04-02 | Martin Stjernholm | | calls = yields = clock_checks = no_clock_advs = 0;
|
0c2204 | 2008-11-18 | Martin Stjernholm | | }
}
#endif
|
15ecdc | 2011-04-02 | Martin Stjernholm | | {
#ifdef PIKE_DEBUG
|
d55914 | 2017-07-17 | Martin Nilsson | | UINT64 old_thread_swaps = thread_swaps;
|
15ecdc | 2011-04-02 | Martin Stjernholm | | #endif
pike_thread_yield();
#ifdef PIKE_DEBUG
if (thread_swaps != old_thread_swaps)
check_threads_swaps++;
#endif
}
|
5d6371 | 2010-09-28 | Martin Stjernholm | | }
|
a76b31 | 2010-09-28 | Henrik Grubbström (Grubba) | | PMOD_EXPORT void pike_thread_yield(void)
|
5d6371 | 2010-09-28 | Martin Stjernholm | | {
|
b867f9 | 2003-02-16 | Martin Stjernholm | | DEBUG_CHECK_THREAD();
|
26cd94 | 1999-05-07 | Fredrik Hübinette (Hubbe) | |
|
de413f | 1998-03-26 | Per Hedbor | | THREADS_ALLOW();
|
307b93 | 2009-03-13 | Martin Stjernholm | |
|
335a55 | 2001-11-02 | Martin Stjernholm | | th_yield();
|
de413f | 1998-03-26 | Per Hedbor | | THREADS_DISALLOW();
|
26cd94 | 1999-05-07 | Fredrik Hübinette (Hubbe) | |
|
7ee4aa | 2002-09-14 | Martin Stjernholm | | #ifdef USE_CLOCK_FOR_SLICES
|
41a096 | 2009-03-13 | Martin Stjernholm | |
|
7ee4aa | 2002-09-14 | Martin Stjernholm | | thread_start_clock = clock();
|
da6644 | 2010-10-23 | Martin Stjernholm | | #ifdef RDTSC
RDTSC (prev_tsc);
|
a771ee | 2010-10-24 | Martin Stjernholm | | prev_clock = thread_start_clock;
|
da6644 | 2010-10-23 | Martin Stjernholm | | #endif
|
41a096 | 2009-03-13 | Martin Stjernholm | | #ifdef PIKE_DEBUG
if (last_clocked_thread != th_self())
Pike_fatal ("Stale thread %08lx in last_clocked_thread (self is %08lx)\n",
(unsigned long) last_clocked_thread, (unsigned long) th_self());
#endif
|
7ee4aa | 2002-09-14 | Martin Stjernholm | | #endif
|
b867f9 | 2003-02-16 | Martin Stjernholm | | DEBUG_CHECK_THREAD();
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | | }
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | struct thread_starter
{
struct thread_state *thread_state;
struct array *args;
#ifdef HAVE_BROKEN_LINUX_THREAD_EUID
int euid, egid;
#endif /* HAVE_BROKEN_LINUX_THREAD_EUID */
};
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | | TH_RETURN_TYPE new_thread_func(void *data)
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | {
|
6d1a5e | 1996-10-07 | Fredrik Hübinette (Hubbe) | | struct thread_starter arg = *(struct thread_starter *)data;
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | struct object *thread_obj;
struct thread_state *thread_state;
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | JMP_BUF back;
|
b1b51f | 1996-10-11 | Fredrik Hübinette (Hubbe) | |
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "new_thread_func(): Thread %p created...\n",
arg.thread_state);
|
c17fed | 2000-05-20 | Henrik Grubbström (Grubba) | |
|
222d92 | 2000-05-20 | Henrik Grubbström (Grubba) | | #ifdef HAVE_BROKEN_LINUX_THREAD_EUID
|
c17fed | 2000-05-20 | Henrik Grubbström (Grubba) | |
if (!geteuid()) {
|
f663a0 | 2003-03-05 | Martin Stjernholm | | #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
int current = prctl(PR_GET_DUMPABLE);
|
a1ee48 | 2003-10-06 | Martin Stjernholm | | #ifdef PIKE_DEBUG
if (current == -1)
|
fa7766 | 2016-02-11 | Martin Nilsson | | WERR("%s:%d: Unexpected error from prctl(2). errno=%d\n",
__FILE__, __LINE__, errno);
|
a1ee48 | 2003-10-06 | Martin Stjernholm | | #endif
|
f663a0 | 2003-03-05 | Martin Stjernholm | | #endif
|
b096df | 2014-03-13 | Per Hedbor | | #ifdef HAVE_BROKEN_LINUX_THREAD_EUID
if( setegid(arg.egid) != 0 || seteuid(arg.euid) != 0 )
{
|
fa7766 | 2016-02-11 | Martin Nilsson | | WERR("%s:%d: Unexpected error from setegid(2). errno=%d\n",
__FILE__, __LINE__, errno);
|
b096df | 2014-03-13 | Per Hedbor | | }
#endif
|
f663a0 | 2003-03-05 | Martin Stjernholm | | #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
|
a1ee48 | 2003-10-06 | Martin Stjernholm | | if (current != -1 && prctl(PR_SET_DUMPABLE, current) == -1) {
|
35e115 | 2016-02-07 | Martin Nilsson | | DWERR("%s:%d: Unexpected error from prctl(2). errno=%d\n",
__FILE__, __LINE__, errno);
|
a1ee48 | 2003-10-06 | Martin Stjernholm | | }
|
f663a0 | 2003-03-05 | Martin Stjernholm | | #endif
|
c17fed | 2000-05-20 | Henrik Grubbström (Grubba) | | }
|
222d92 | 2000-05-20 | Henrik Grubbström (Grubba) | | #endif /* HAVE_BROKEN_LINUX_THREAD_EUID */
|
0d51b3 | 2008-09-09 | Martin Stjernholm | |
low_mt_lock_interpreter();
|
b867f9 | 2003-02-16 | Martin Stjernholm | |
|
fcca61 | 2016-02-11 | Martin Nilsson | | #ifdef PIKE_DEBUG
|
b867f9 | 2003-02-16 | Martin Stjernholm | | if(d_flag) {
THREAD_T self = th_self();
if( !th_equal(arg.thread_state->id, self) )
Pike_fatal("Current thread is wrong. %lx %lx\n",
(long)arg.thread_state->id, (long)self);
}
|
fcca61 | 2016-02-11 | Martin Nilsson | | #endif /* PIKE_DEBUG */
|
b867f9 | 2003-02-16 | Martin Stjernholm | |
arg.thread_state->swapped = 0;
|
d97eb7 | 2011-07-10 | Henrik Grubbström (Grubba) | | Pike_interpreter_pointer = &arg.thread_state->state;
|
b867f9 | 2003-02-16 | Martin Stjernholm | |
|
061244 | 2001-05-16 | Fredrik Hübinette (Hubbe) | | #ifdef PROFILING
Pike_interpreter.stack_bottom=((char *)&data);
#endif
|
17f08c | 2000-07-06 | Fredrik Hübinette (Hubbe) | | Pike_interpreter.stack_top=((char *)&data)+ (thread_stack_size-16384) * STACK_DIRECTION;
Pike_interpreter.recoveries = NULL;
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | |
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | add_ref(thread_obj = arg.thread_state->thread_obj);
INIT_THREAD_STATE(thread_state = arg.thread_state);
co_broadcast(&thread_state->status_change);
|
f0cd4c | 1999-03-21 | Henrik Grubbström (Grubba) | |
|
0d51b3 | 2008-09-09 | Martin Stjernholm | |
if (threads_disabled) {
SWAP_OUT_CURRENT_THREAD();
|
91518c | 2009-03-15 | Martin Stjernholm | | threads_disabled_wait (DLOC);
|
0d51b3 | 2008-09-09 | Martin Stjernholm | | SWAP_IN_CURRENT_THREAD();
}
|
b867f9 | 2003-02-16 | Martin Stjernholm | | DEBUG_CHECK_THREAD();
|
26cd94 | 1999-05-07 | Fredrik Hübinette (Hubbe) | |
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "new_thread_func(): Thread %p inited\n",
arg.thread_state);
|
38e1e8 | 2001-11-08 | Fredrik Hübinette (Hubbe) | |
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | if(SETJMP(back))
{
|
d273ca | 2014-12-07 | Henrik Grubbström (Grubba) | | if(throw_severity <= THROW_ERROR) {
if (thread_state->thread_obj) {
assign_svalue(&thread_state->result, &throw_value);
}
|
669704 | 2000-11-20 | Martin Stjernholm | | call_handle_error();
|
d273ca | 2014-12-07 | Henrik Grubbström (Grubba) | | }
if(throw_severity == THROW_EXIT)
|
14ff49 | 2009-09-29 | Martin Stjernholm | | {
pike_do_exit(throw_value.u.integer);
}
|
d273ca | 2014-12-07 | Henrik Grubbström (Grubba) | |
thread_state->status = THREAD_ABORTED;
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | } else {
|
725ba9 | 1996-10-12 | Fredrik Hübinette (Hubbe) | | INT32 args=arg.args->size;
|
61e9a0 | 1998-01-25 | Fredrik Hübinette (Hubbe) | | back.severity=THROW_EXIT;
|
6d1a5e | 1996-10-07 | Fredrik Hübinette (Hubbe) | | push_array_items(arg.args);
arg.args=0;
|
97ffe4 | 1997-01-26 | Per Hedbor | | f_call_function(args);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
|
a93a16 | 2008-12-19 | Martin Stjernholm | |
if (thread_state->thread_obj)
assign_svalue(&thread_state->result, Pike_sp-1);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | pop_stack();
|
d273ca | 2014-12-07 | Henrik Grubbström (Grubba) | |
thread_state->status = THREAD_EXITED;
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | }
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | UNSETJMP(back);
|
b867f9 | 2003-02-16 | Martin Stjernholm | | DEBUG_CHECK_THREAD();
|
38e1e8 | 2001-11-08 | Fredrik Hübinette (Hubbe) | |
|
621e75 | 2015-10-19 | Per Hedbor | | if(thread_state->thread_locals != NULL) {
free_mapping(thread_state->thread_locals);
thread_state->thread_locals = NULL;
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | }
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | co_broadcast(&thread_state->status_change);
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | |
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "new_thread_func(): Thread %p done\n", arg.thread_state);
|
b1b51f | 1996-10-11 | Fredrik Hübinette (Hubbe) | |
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | |
|
2ef3b9 | 2005-01-25 | Henrik Grubbström (Grubba) | | while(Pike_fp)
POP_PIKE_FRAME();
reset_evaluator();
low_cleanup_interpret(&thread_state->state);
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | |
|
0a14c2 | 2008-08-05 | Martin Stjernholm | | if (!thread_state->thread_obj)
cleanup_thread_state (thread_state);
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | thread_table_delete(thread_state);
EXIT_THREAD_STATE(thread_state);
Pike_interpreter.thread_state = thread_state = NULL;
|
d97eb7 | 2011-07-10 | Henrik Grubbström (Grubba) | | Pike_interpreter_pointer = NULL;
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | |
|
f1ee64 | 2003-03-17 | Henrik Grubbström (Grubba) | |
free_object(thread_obj);
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | thread_obj = NULL;
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | num_threads--;
|
fe76ce | 1997-09-08 | Fredrik Hübinette (Hubbe) | | if(!num_threads && threads_evaluator_callback)
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | | {
remove_callback(threads_evaluator_callback);
threads_evaluator_callback=0;
}
|
0f65e1 | 2002-09-14 | Martin Stjernholm | |
#ifdef INTERNAL_PROFILING
fprintf (stderr, "Thread usage summary:\n");
debug_print_rusage (stderr);
#endif
|
4bc7e4 | 2001-11-26 | Henrik Grubbström (Grubba) | |
|
c91f89 | 2000-04-19 | Martin Stjernholm | | mt_unlock_interpreter();
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | th_exit(0);
|
9282fd | 2015-09-27 | Martin Nilsson | | UNREACHABLE(return 0);
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | }
|
97ffe4 | 1997-01-26 | Per Hedbor | | #ifdef UNIX_THREADS
int num_lwps = 1;
#endif
|
b1b51f | 1996-10-11 | Fredrik Hübinette (Hubbe) | |
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | |
|
761bb0 | 2015-08-20 | Henrik Grubbström (Grubba) | | |
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *!
*! This function creates a new thread which will run simultaneously
*! to the rest of the program. The new thread will call the function
*! @[f] with the arguments @[args]. When @[f] returns the thread will cease
*! to exist.
*!
*! All Pike functions are 'thread safe' meaning that running
*! a function at the same time from different threads will not corrupt
*! any internal data in the Pike process.
*!
*! @returns
*! The returned value will be the same as the return value of
|
c7b7dd | 2001-10-28 | Martin Nilsson | | *! @[this_thread()] for the new thread.
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *!
*! @note
*! This function is only available on systems with POSIX or UNIX or WIN32
*! threads support.
*!
*! @seealso
*! @[Mutex], @[Condition], @[this_thread()]
*/
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | void f_thread_create(INT32 args)
{
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | struct thread_starter arg;
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | | struct thread_state *thread_state =
(struct thread_state *)Pike_fp->current_storage;
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | int tmp;
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | |
|
5cd312 | 2015-12-08 | Henrik Grubbström (Grubba) | | if (args < 1) {
|
06bd61 | 2016-01-26 | Martin Nilsson | | SIMPLE_WRONG_NUM_ARGS_ERROR("create", 1);
|
5cd312 | 2015-12-08 | Henrik Grubbström (Grubba) | | }
|
a72935 | 2015-12-13 | Henrik Grubbström (Grubba) | | if (!callablep(Pike_sp - args)) {
|
f98274 | 2016-01-26 | Martin Nilsson | | SIMPLE_ARG_TYPE_ERROR("create", 1, "function");
|
5cd312 | 2015-12-08 | Henrik Grubbström (Grubba) | | }
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | | if (thread_state->status != THREAD_NOT_STARTED) {
|
6818b0 | 2003-02-20 | Henrik Grubbström (Grubba) | | Pike_error("Threads can not be restarted (status:%d).\n",
thread_state->status);
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | | }
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | arg.args = aggregate_array(args);
arg.thread_state = thread_state;
|
b2a0fb | 1997-02-06 | Henrik Grubbström (Grubba) | |
|
2ef3b9 | 2005-01-25 | Henrik Grubbström (Grubba) | | if (low_init_interpreter(&thread_state->state)) {
free_array(arg.args);
Pike_error("Out of memory allocating stack.\n");
}
|
222d92 | 2000-05-20 | Henrik Grubbström (Grubba) | | #ifdef HAVE_BROKEN_LINUX_THREAD_EUID
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | arg.euid = geteuid();
arg.egid = getegid();
|
222d92 | 2000-05-20 | Henrik Grubbström (Grubba) | | #endif /* HAVE_BROKEN_LINUX_THREAD_EUID */
|
c17fed | 2000-05-20 | Henrik Grubbström (Grubba) | |
|
4743f8 | 1999-06-02 | Fredrik Hübinette (Hubbe) | | do {
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | tmp = th_create(&thread_state->id,
|
d40e38 | 1999-10-14 | Henrik Grubbström (Grubba) | | new_thread_func,
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | &arg);
|
700dac | 2002-02-05 | Martin Stjernholm | | if (tmp == EINTR) check_threads_etc();
|
4743f8 | 1999-06-02 | Fredrik Hübinette (Hubbe) | | } while( tmp == EINTR );
|
b2a0fb | 1997-02-06 | Henrik Grubbström (Grubba) | |
|
6d1a5e | 1996-10-07 | Fredrik Hübinette (Hubbe) | | if(!tmp)
{
num_threads++;
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | thread_table_insert(thread_state);
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | |
|
fe76ce | 1997-09-08 | Fredrik Hübinette (Hubbe) | | if(!threads_evaluator_callback)
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | | {
threads_evaluator_callback=add_to_callback(&evaluator_callbacks,
check_threads, 0,0);
|
424d9c | 1999-05-02 | Fredrik Hübinette (Hubbe) | | dmalloc_accept_leak(threads_evaluator_callback);
|
a29e02 | 1996-10-15 | Fredrik Hübinette (Hubbe) | | }
|
91518c | 2009-03-15 | Martin Stjernholm | |
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | | |
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | *
* The main race is the one on current_object,
* since it at this point only has one reference.
*
* We also want the stuff in arg to be copied properly
* before we exit the function...
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | | */
|
b867f9 | 2003-02-16 | Martin Stjernholm | | SWAP_OUT_CURRENT_THREAD();
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "f_thread_create %p waiting...\n", thread_state);
|
91518c | 2009-03-15 | Martin Stjernholm | | while (thread_state->status == THREAD_NOT_STARTED)
|
335f1b | 2017-08-09 | Henrik Grubbström (Grubba) | | co_wait_interpreter (&thread_state->status_change);
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "f_thread_create %p continue\n", thread_state);
|
b867f9 | 2003-02-16 | Martin Stjernholm | | SWAP_IN_CURRENT_THREAD();
|
6d1a5e | 1996-10-07 | Fredrik Hübinette (Hubbe) | | } else {
|
2ef3b9 | 2005-01-25 | Henrik Grubbström (Grubba) | | low_cleanup_interpret(&thread_state->state);
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | free_array(arg.args);
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | | Pike_error("Failed to create thread (errno = %d).\n", tmp);
|
6d1a5e | 1996-10-07 | Fredrik Hübinette (Hubbe) | | }
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | |
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "f_thread_create %p done\n", thread_state);
|
6d1a5e | 1996-10-07 | Fredrik Hübinette (Hubbe) | | }
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | |
|
1e4a64 | 1997-09-03 | Martin Stjernholm | | #ifdef UNIX_THREADS
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | |
c7b7dd | 2001-10-28 | Martin Nilsson | | *!
*! @fixme
*! Document this function
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | */
|
97ffe4 | 1997-01-26 | Per Hedbor | | void f_thread_set_concurrency(INT32 args)
{
int c=1;
|
d4ecd7 | 2003-01-05 | Martin Nilsson | | if(args)
c=Pike_sp[-args].u.integer;
else
|
06bd61 | 2016-01-26 | Martin Nilsson | | SIMPLE_WRONG_NUM_ARGS_ERROR("thread_set_concurrency", 1);
|
97ffe4 | 1997-01-26 | Per Hedbor | | pop_n_elems(args);
|
09dceb | 1997-09-01 | Per Hedbor | | num_lwps=c;
|
97ffe4 | 1997-01-26 | Per Hedbor | | th_setconcurrency(c);
}
|
1e4a64 | 1997-09-03 | Martin Stjernholm | | #endif
|
97ffe4 | 1997-01-26 | Per Hedbor | |
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | |
c7b7dd | 2001-10-28 | Martin Nilsson | | *! @[Thread()]
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | */
|
fa8c69 | 2000-11-30 | Fredrik Hübinette (Hubbe) | | PMOD_EXPORT void f_this_thread(INT32 args)
|
6d1a5e | 1996-10-07 | Fredrik Hübinette (Hubbe) | | {
pop_n_elems(args);
|
cb54df | 2015-09-02 | Henrik Grubbström (Grubba) | | if (Pike_interpreter.thread_state &&
Pike_interpreter.thread_state->thread_obj) {
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | ref_push_object(Pike_interpreter.thread_state->thread_obj);
} else {
push_undefined();
}
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | }
|
7a5298 | 2015-09-09 | Henrik Grubbström (Grubba) | |
static void f_get_thread_quanta(INT32 args)
{
pop_n_elems(args);
push_int64(thread_quanta);
#ifndef LONG_CPU_TIME_T
push_int(1000000000 / CPU_TIME_TICKS);
o_multiply();
#endif
}
static void f_set_thread_quanta(INT32 args)
{
|
0a3c55 | 2016-05-09 | Martin Nilsson | | INT64 ns = 0;
|
7a5298 | 2015-09-09 | Henrik Grubbström (Grubba) | |
#ifndef LONG_CPU_TIME_T
push_int(1000000000 / CPU_TIME_TICKS);
o_divide();
#endif
get_all_args("set_thread_quanta", args, "%l", &ns);
pop_n_elems(args);
push_int64(thread_quanta);
#ifndef LONG_CPU_TIME_T
push_int(1000000000 / CPU_TIME_TICKS);
o_multiply();
#endif
if (ns <= 0) ns = 0;
thread_quanta = ns;
if (Pike_interpreter.thread_state) {
Pike_interpreter.thread_state->interval_start = get_real_time();
}
}
|
60d987 | 2000-03-23 | Fredrik Hübinette (Hubbe) | | #define THIS_MUTEX ((struct mutex_storage *)(CURRENT_STORAGE))
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | |
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | struct key_storage;
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | struct mutex_storage
{
COND_T condition;
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | struct key_storage *key;
|
270295 | 2004-04-21 | Martin Stjernholm | | int num_waiting;
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | };
|
ea9a82 | 2020-06-24 | Henrik Grubbström (Grubba) | | enum key_kind
{
KEY_UNINITIALIZED = 0,
KEY_INITIALIZED,
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | KEY_NONE = KEY_INITIALIZED,
KEY_SHARED,
|
a94a08 | 2020-07-02 | Henrik Grubbström (Grubba) | | KEY_DOWNGRADED,
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | KEY_PENDING,
KEY_EXCLUSIVE,
|
ea9a82 | 2020-06-24 | Henrik Grubbström (Grubba) | | };
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | struct key_storage
{
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | struct object *self;
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | struct mutex_storage *mut;
|
33887a | 2002-10-28 | Martin Stjernholm | | struct object *mutex_obj;
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | struct thread_state *owner;
struct object *owner_obj;
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | struct key_storage *prev;
struct key_storage *next;
|
ea9a82 | 2020-06-24 | Henrik Grubbström (Grubba) | | enum key_kind kind;
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | };
#define OB2KEY(X) ((struct key_storage *)((X)->storage))
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | |
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | |
c7b7dd | 2001-10-28 | Martin Nilsson | | *! @[Mutex] is a class that implements mutual exclusion locks.
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *! Mutex locks are used to prevent multiple threads from simultaneously
*! execute sections of code which access or change shared data. The basic
*! operations for a mutex is locking and unlocking. If a thread attempts
*! to lock an already locked mutex the thread will sleep until the mutex
*! is unlocked.
*!
*! @note
*! This class is simulated when Pike is compiled without thread support,
*! so it's always available.
*!
*! In POSIX threads, mutex locks can only be unlocked by the same thread
*! that locked them. In Pike any thread can unlock a locked mutex.
*/
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | *! @decl MutexKey lock(int type, int(0..)|float seconds)
*! @decl MutexKey lock(int type, int(0..) seconds @
*! int(0..999999999) nanos)
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *!
*! This function attempts to lock the mutex. If the mutex is already
*! locked by a different thread the current thread will sleep until the
*! mutex is unlocked. The value returned is the 'key' to the lock. When
|
4f6801 | 2002-10-28 | Martin Stjernholm | | *! the key is destructed or has no more references the mutex will
|
5fba12 | 2004-04-26 | Martin Stjernholm | | *! automatically be unlocked.
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *!
*! The @[type] argument specifies what @[lock()] should do if the
*! mutex is already locked by this thread:
*! @int
|
a9cdcf | 2001-02-06 | Henrik Grubbström (Grubba) | | *! @value 0
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *! Throw an error.
*! @value 1
*! Sleep until the mutex is unlocked. Useful if some
*! other thread will unlock it.
*! @value 2
*! Return zero. This allows recursion within a locked region of
*! code, but in conjunction with other locks it easily leads
*! to unspecified locking order and therefore a risk for deadlocks.
*! @endint
*!
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | *! @param seconds
*! Seconds to wait before the timeout is reached.
*!
*! @param nanos
*! Nano (1/1000000000) seconds to wait before the timeout is reached.
*! This value is added to the number of seconds specified by @[seconds].
*!
*! A timeout of zero seconds disables the timeout.
*!
*! @note
*! The support for timeouts was added in Pike 8.1.14, which was
*! before the first public release of Pike 8.1.
*!
*! @note
*! Note that the timeout is approximate (best effort), and may
*! be exceeded if eg the interpreter is busy after the timeout.
*!
|
d059be | 2004-04-23 | Martin Stjernholm | | *! @note
|
5fba12 | 2004-04-26 | Martin Stjernholm | | *! If the mutex is destructed while it's locked or while threads are
*! waiting on it, it will continue to exist internally until the last
*! thread has stopped waiting and the last @[MutexKey] has
*! disappeared, but further calls to the functions in this class will
*! fail as is usual for destructed objects.
|
d059be | 2004-04-23 | Martin Stjernholm | | *!
|
d85b4b | 2004-05-01 | Martin Stjernholm | | *! @note
*! Pike 7.4 and earlier destructed any outstanding lock when the
*! mutex was destructed, but threads waiting in @[lock] still got
*! functioning locks as discussed above. This is inconsistent no
*! matter how you look at it, so it was changed in 7.6. The old
*! behavior is retained in compatibility mode for applications that
*! explicitly destruct mutexes to unlock them.
*!
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *! @seealso
*! @[trylock()]
*/
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | void f_mutex_lock(INT32 args)
{
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | struct mutex_storage *m;
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | struct key_storage *key;
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | struct object *o;
|
ef72d4 | 2020-07-01 | Henrik Grubbström (Grubba) | | INT_TYPE type = 0;
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | INT_TYPE seconds = 0, nanos = 0;
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | |
|
b867f9 | 2003-02-16 | Martin Stjernholm | | DEBUG_CHECK_THREAD();
|
38e1e8 | 2001-11-08 | Fredrik Hübinette (Hubbe) | |
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | m=THIS_MUTEX;
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | if (args <= 2) {
FLOAT_TYPE fsecs = 0.0;
get_all_args(NULL, args, ".%i%F", &type, &fsecs);
if (fsecs > 0.0) {
seconds = (INT_TYPE)fsecs;
nanos = (INT_TYPE)((fsecs - seconds) * 1000000000);
}
} else {
INT_TYPE adj = 0;
get_all_args(NULL, args, "%i%i%i", &type, &seconds, &nanos);
adj = nanos / 1000000000;
if (nanos < 0) adj--;
nanos -= adj * 1000000000;
seconds += adj;
}
|
a49ee6 | 1999-04-02 | Fredrik Hübinette (Hubbe) | |
switch(type)
{
default:
|
212c39 | 2018-02-25 | Martin Nilsson | | bad_arg_error("lock", args, 2, "int(0..2)", Pike_sp+1-args,
|
69c0aa | 2014-08-25 | Martin Nilsson | | "Unknown mutex locking style: %"PRINTPIKEINT"d\n",type);
|
13670c | 2015-05-25 | Martin Nilsson | |
|
a49ee6 | 1999-04-02 | Fredrik Hübinette (Hubbe) | |
case 0:
case 2:
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | for (key = m->key; key; key = key->next) {
if(key->owner == Pike_interpreter.thread_state)
{
THREADS_FPRINTF(0,
"Recursive LOCK k:%p, m:%p(%p), t:%p\n",
key, m, key->mut,
Pike_interpreter.thread_state);
|
a49ee6 | 1999-04-02 | Fredrik Hübinette (Hubbe) | |
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | if(type==0) Pike_error("Recursive mutex locks!\n");
|
a49ee6 | 1999-04-02 | Fredrik Hübinette (Hubbe) | |
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | pop_n_elems(args);
push_int(0);
return;
}
|
a49ee6 | 1999-04-02 | Fredrik Hübinette (Hubbe) | | }
case 1:
break;
}
|
46d7bf | 1997-09-03 | Henrik Grubbström (Grubba) | |
|
f777b7 | 2003-02-15 | Henrik Grubbström (Grubba) | | o=fast_clone_object(mutex_key);
|
4bdad0 | 1997-09-01 | Per Hedbor | |
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | key = OB2KEY(o);
key->mut = m;
add_ref (key->mutex_obj = Pike_fp->current_object);
key->prev = NULL;
if ((key->next = m->key)) {
m->key->prev = key;
}
m->key = key;
key->kind = KEY_PENDING;
|
b867f9 | 2003-02-16 | Martin Stjernholm | | DEBUG_CHECK_THREAD();
|
26cd94 | 1999-05-07 | Fredrik Hübinette (Hubbe) | |
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | if(key->next)
|
fe76ce | 1997-09-08 | Fredrik Hübinette (Hubbe) | | {
|
adb19b | 1999-06-30 | Fredrik Hübinette (Hubbe) | | if(threads_disabled)
{
free_object(o);
|
b2d3e4 | 2000-12-01 | Fredrik Hübinette (Hubbe) | | Pike_error("Cannot wait for mutexes when threads are disabled!\n");
|
adb19b | 1999-06-30 | Fredrik Hübinette (Hubbe) | | }
|
3399e6 | 2020-07-03 | Henrik Grubbström (Grubba) | | m->num_waiting++;
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | if (seconds || nanos) {
if (seconds >= 0) {
struct timeval timeout;
ACCURATE_GETTIMEOFDAY(&timeout);
timeout.tv_sec += seconds;
timeout.tv_usec += nanos/1000;
do
{
THREADS_FPRINTF(1, "WAITING TO LOCK m:%p\n", m);
SWAP_OUT_CURRENT_THREAD();
co_wait_interpreter_timeout(& m->condition, seconds, nanos);
SWAP_IN_CURRENT_THREAD();
check_threads_etc();
if (key->next) {
struct timeval now;
ACCURATE_GETTIMEOFDAY(&now);
seconds = timeout.tv_sec - now.tv_sec;
nanos = (timeout.tv_usec - now.tv_usec) * 1000;
if (nanos < 0) {
seconds--;
nanos += 1000000000;
}
if ((seconds < 0) || (!seconds && !nanos)) break;
}
} while (key->next);
}
} else {
do
{
THREADS_FPRINTF(1, "WAITING TO LOCK m:%p\n", m);
SWAP_OUT_CURRENT_THREAD();
co_wait_interpreter(& m->condition);
SWAP_IN_CURRENT_THREAD();
check_threads_etc();
} while (key->next);
}
|
270295 | 2004-04-21 | Martin Stjernholm | | m->num_waiting--;
|
fe76ce | 1997-09-08 | Fredrik Hübinette (Hubbe) | | }
|
270295 | 2004-04-21 | Martin Stjernholm | |
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | if (key->next) {
destruct(o);
free_object(o);
DEBUG_CHECK_THREAD();
THREADS_FPRINTF(1, "LOCK k:%p, m:%p(%p), t:%p\n",
NULL, m, NULL,
Pike_interpreter.thread_state);
pop_n_elems(args);
push_int(0);
return;
}
|
270295 | 2004-04-21 | Martin Stjernholm | | #ifdef PICKY_MUTEX
if (!Pike_fp->current_object->prog) {
free_object (o);
|
8af562 | 2016-08-09 | Henrik Grubbström (Grubba) | | if (!m->num_waiting) {
|
270295 | 2004-04-21 | Martin Stjernholm | | co_destroy (&m->condition);
|
8af562 | 2016-08-09 | Henrik Grubbström (Grubba) | | }
|
270295 | 2004-04-21 | Martin Stjernholm | | Pike_error ("Mutex was destructed while waiting for lock.\n");
}
#endif
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | key->kind = KEY_EXCLUSIVE;
|
fe76ce | 1997-09-08 | Fredrik Hübinette (Hubbe) | |
|
b867f9 | 2003-02-16 | Martin Stjernholm | | DEBUG_CHECK_THREAD();
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(1, "LOCK k:%p, m:%p(%p), t:%p\n",
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | key, m, key->mut,
|
7d06ba | 2016-02-07 | Martin Nilsson | | Pike_interpreter.thread_state);
|
65d3c3 | 1997-09-08 | Fredrik Hübinette (Hubbe) | | pop_n_elems(args);
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | push_object(o);
}
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | |
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | *! @decl MutexKey shared_lock(int type, int(0..)|float seconds)
*! @decl MutexKey shared_lock(int type, int(0..) seconds @
*! int(0..999999999) nanos)
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | *!
*! This function attempts to lock the mutex. If the mutex is already
*! locked by a different thread the current thread will sleep until the
*! mutex is unlocked. The value returned is the 'key' to the lock. When
*! the key is destructed or has no more references the mutex will
*! automatically be unlocked.
*!
*! The @[type] argument specifies what @[lock()] should do if the
*! mutex is already locked exclusively by this thread:
*! @int
*! @value 0
*! Throw an error.
*! @value 1
*! Sleep until the mutex is unlocked. Useful if some
*! other thread will unlock it.
*! @value 2
*! Return zero. This allows recursion within a locked region of
*! code, but in conjunction with other locks it easily leads
*! to unspecified locking order and therefore a risk for deadlocks.
*! @endint
*!
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | *! @param seconds
*! Seconds to wait before the timeout is reached.
*!
*! @param nanos
*! Nano (1/1000000000) seconds to wait before the timeout is reached.
*! This value is added to the number of seconds specified by @[seconds].
*!
*! A timeout of zero seconds disables the timeout.
*!
*! @note
*! Note that the timeout is approximate (best effort), and may
*! be exceeded if eg the interpreter is busy after the timeout.
*!
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | *! @note
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | *! Note that if the current thread already holds a shared key,
*! a new will be created without waiting, and regardless of
*! the value of @[type].
*!
*! @note
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | *! If the mutex is destructed while it's locked or while threads are
*! waiting on it, it will continue to exist internally until the last
*! thread has stopped waiting and the last @[MutexKey] has
*! disappeared, but further calls to the functions in this class will
*! fail as is usual for destructed objects.
*!
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | *! @note
*! Support for shared keys was added in Pike 8.1.
*!
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | *! @seealso
*! @[lock()], @[trylock()], @[try_shared_lock()]
*/
void f_mutex_shared_lock(INT32 args)
{
struct mutex_storage *m;
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | struct key_storage *key, *prev = NULL;
struct object *o, *prev_o = NULL;
INT_TYPE type = 0;
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | INT_TYPE seconds = 0, nanos = 0;
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | |
DEBUG_CHECK_THREAD();
m=THIS_MUTEX;
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | if (args <= 2) {
FLOAT_TYPE fsecs = 0.0;
get_all_args(NULL, args, ".%i%F", &type, &fsecs);
if (fsecs > 0.0) {
seconds = (INT_TYPE)fsecs;
nanos = (INT_TYPE)((fsecs - seconds) * 1000000000);
}
} else {
INT_TYPE adj = 0;
get_all_args(NULL, args, "%i%i%i", &type, &seconds, &nanos);
adj = nanos / 1000000000;
if (nanos < 0) adj--;
nanos -= adj * 1000000000;
seconds += adj;
}
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | |
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | if ((type < 0) || (type > 2)) {
bad_arg_error("shared_lock", args, 2, "int(0..2)", Pike_sp+1-args,
"Unknown mutex locking style: %"PRINTPIKEINT"d\n", type);
}
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | |
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | for (key = m->key; key; key = key->next) {
if (key->owner == Pike_interpreter.thread_state) {
THREADS_FPRINTF(0,
"Recursive LOCK k:%p, m:%p(%p), t:%p\n",
key, m, key->mut,
Pike_interpreter.thread_state);
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | |
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | if (key->kind >= KEY_PENDING) {
switch(type) {
case 0:
Pike_error("Recursive mutex locks!\n");
break;
case 1:
continue;
case 2:
pop_n_elems(args);
push_int(0);
return;
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | }
}
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | |
prev = key;
prev_o = prev->self;
add_ref(prev_o);
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | break;
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | }
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | }
o=fast_clone_object(mutex_key);
DEBUG_CHECK_THREAD();
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | if (prev_o && !prev_o->prog) {
prev = NULL;
free_object(prev_o);
prev_o = NULL;
for (key = m->key; key; key = key->next) {
if (key->kind >= KEY_PENDING) continue;
if (key->owner == Pike_interpreter.thread_state) {
prev = key;
prev_o = prev->self;
add_ref(prev_o);
break;
}
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | }
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | }
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | |
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | if (!prev) {
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | if(threads_disabled)
{
free_object(o);
Pike_error("Cannot wait for mutexes when threads are disabled!\n");
}
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | |
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | m->num_waiting++;
if (seconds || nanos) {
if (seconds >= 0) {
struct timeval timeout;
ACCURATE_GETTIMEOFDAY(&timeout);
timeout.tv_sec += seconds;
timeout.tv_usec += nanos/1000;
while (m->key && (m->key->kind >= KEY_PENDING)) {
THREADS_FPRINTF(1, "WAITING TO SHARE LOCK m:%p\n", m);
SWAP_OUT_CURRENT_THREAD();
co_wait_interpreter_timeout(& m->condition, seconds, nanos);
SWAP_IN_CURRENT_THREAD();
check_threads_etc();
if (m->key && (m->key->kind >= KEY_PENDING)) {
struct timeval now;
ACCURATE_GETTIMEOFDAY(&now);
seconds = timeout.tv_sec - now.tv_sec;
nanos = (timeout.tv_usec - now.tv_usec) * 1000;
if (nanos < 0) {
seconds--;
nanos += 1000000000;
}
if ((seconds < 0) || (!seconds && !nanos)) break;
}
}
}
} else {
while (m->key && (m->key->kind >= KEY_PENDING)) {
THREADS_FPRINTF(1, "WAITING TO SHARE LOCK m:%p\n", m);
SWAP_OUT_CURRENT_THREAD();
co_wait_interpreter(& m->condition);
SWAP_IN_CURRENT_THREAD();
check_threads_etc();
}
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | }
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | m->num_waiting--;
|
a94a08 | 2020-07-02 | Henrik Grubbström (Grubba) | |
if (m->key && (m->key->kind == KEY_DOWNGRADED)) {
prev = m->key;
prev_o = prev->self;
add_ref(prev_o);
}
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | }
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | if (m->key && (m->key->kind >= KEY_PENDING)) {
destruct(o);
free_object(o);
DEBUG_CHECK_THREAD();
THREADS_FPRINTF(1, "SHARED_LOCK k:%p, m:%p(%p), t:%p\n",
NULL, m, NULL,
Pike_interpreter.thread_state);
pop_n_elems(args);
push_int(0);
return;
}
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | #ifdef PICKY_MUTEX
if (!Pike_fp->current_object->prog) {
destruct(o);
free_object (o);
if (!m->num_waiting) {
co_destroy (&m->condition);
}
|
a94a08 | 2020-07-02 | Henrik Grubbström (Grubba) | | if (prev_o) free_object(prev_o);
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | Pike_error ("Mutex was destructed while waiting for lock.\n");
}
#endif
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | |
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | *
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | * prev != NULL
* prev == NULL && m->key == NULL
* prev == NULL && m->key && m->key->kind == KEY_READ
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | */
key = OB2KEY(o);
key->mut = m;
add_ref (key->mutex_obj = Pike_fp->current_object);
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | if (prev) {
key->prev = prev;
if ((key->next = prev->next)) {
prev->next->prev = key;
}
prev->next = key;
free_object(prev_o);
} else {
key->prev = NULL;
if ((key->next = m->key)) {
m->key->prev = key;
}
m->key = key;
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | }
|
a94a08 | 2020-07-02 | Henrik Grubbström (Grubba) | |
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | key->kind = KEY_SHARED;
DEBUG_CHECK_THREAD();
THREADS_FPRINTF(1, "SHARED_LOCK k:%p, m:%p(%p), t:%p\n",
key, m, key->mut,
Pike_interpreter.thread_state);
pop_n_elems(args);
push_object(o);
}
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | |
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | void f_mutex_trylock(INT32 args)
{
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | struct mutex_storage *m;
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | struct key_storage *key;
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | struct object *o;
|
ef72d4 | 2020-07-01 | Henrik Grubbström (Grubba) | | INT_TYPE type = 0;
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | int i=0;
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | |
|
46d7bf | 1997-09-03 | Henrik Grubbström (Grubba) | |
|
a49ee6 | 1999-04-02 | Fredrik Hübinette (Hubbe) | | m=THIS_MUTEX;
|
ef72d4 | 2020-07-01 | Henrik Grubbström (Grubba) | | get_all_args(NULL, args, ".%i", &type);
|
a49ee6 | 1999-04-02 | Fredrik Hübinette (Hubbe) | |
switch(type)
|
65df5c | 1997-09-01 | Per Hedbor | | {
|
a49ee6 | 1999-04-02 | Fredrik Hübinette (Hubbe) | | default:
|
212c39 | 2018-02-25 | Martin Nilsson | | bad_arg_error("trylock", args, 2, "int(0..2)", Pike_sp+1-args,
|
69c0aa | 2014-08-25 | Martin Nilsson | | "Unknown mutex locking style: %"PRINTPIKEINT"d\n",type);
|
a49ee6 | 1999-04-02 | Fredrik Hübinette (Hubbe) | |
case 0:
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | for (key = m->key; key; key = key->next) {
if(key->owner == Pike_interpreter.thread_state)
{
Pike_error("Recursive mutex locks!\n");
}
|
a49ee6 | 1999-04-02 | Fredrik Hübinette (Hubbe) | | }
case 2:
case 1:
break;
|
65df5c | 1997-09-01 | Per Hedbor | | }
|
50fd18 | 1997-09-17 | Fredrik Hübinette (Hubbe) | |
|
a49ee6 | 1999-04-02 | Fredrik Hübinette (Hubbe) | | o=clone_object(mutex_key,0);
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | key = OB2KEY(o);
|
a49ee6 | 1999-04-02 | Fredrik Hübinette (Hubbe) | |
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | if(!m->key)
{
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | key->mut = m;
add_ref (key->mutex_obj = Pike_fp->current_object);
m->key = key;
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | key->kind = KEY_EXCLUSIVE;
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | i=1;
}
|
13670c | 2015-05-25 | Martin Nilsson | |
|
65d3c3 | 1997-09-08 | Fredrik Hübinette (Hubbe) | | pop_n_elems(args);
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | if(i)
{
push_object(o);
} else {
|
de78e6 | 2020-03-02 | Henrik Grubbström (Grubba) | |
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | destruct(o);
free_object(o);
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | push_int(0);
}
}
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | |
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | *! @note
*! Support for shared keys was added in Pike 8.1.
*!
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | *! @seealso
*! @[shared_lock()], @[lock()], @[trylock()]
*/
void f_mutex_try_shared_lock(INT32 args)
{
struct mutex_storage *m;
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | struct key_storage *key, *prev = NULL;
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | struct object *o;
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | INT_TYPE type = 0;
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | int i=0;
m=THIS_MUTEX;
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | get_all_args(NULL, args, ".%i", &type);
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | |
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | if ((type < 0) || (type > 2)) {
bad_arg_error("try_shared_lock", args, 2, "int(0..2)", Pike_sp+1-args,
"Unknown mutex locking style: %"PRINTPIKEINT"d\n",type);
}
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | |
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | o = clone_object(mutex_key, 0);
for (key = m->key; key; key = key->next) {
if(key->owner == Pike_interpreter.thread_state)
{
if (key->kind >= KEY_PENDING) {
if (type == 0) {
free_object(o);
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | Pike_error("Recursive mutex locks!\n");
}
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | continue;
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | }
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | prev = key;
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | break;
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | }
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | }
|
a94a08 | 2020-07-02 | Henrik Grubbström (Grubba) | | if (m->key && (m->key->kind == KEY_DOWNGRADED) && !prev) {
prev = m->key;
}
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | key = OB2KEY(o);
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | if (prev) {
|
f2f6e4 | 2020-06-30 | Henrik Grubbström (Grubba) | |
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | key->mut = m;
add_ref (key->mutex_obj = Pike_fp->current_object);
key->prev = prev;
|
f2f6e4 | 2020-06-30 | Henrik Grubbström (Grubba) | | if ((key->next = prev->next)) {
|
8f1ff9 | 2020-06-29 | Henrik Grubbström (Grubba) | | prev->next->prev = key;
}
prev->next = key;
key->kind = KEY_SHARED;
i=1;
} else if (!m->key || (m->key->kind < KEY_PENDING)) {
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | key->mut = m;
add_ref (key->mutex_obj = Pike_fp->current_object);
if ((key->next = m->key)) {
key->next->prev = key;
}
m->key = key;
key->prev = NULL;
key->kind = KEY_SHARED;
i=1;
}
pop_n_elems(args);
if(i)
{
push_object(o);
} else {
destruct(o);
free_object(o);
push_int(0);
}
}
|
b9bba0 | 2001-08-08 | Leif Stensson | | |
c7b7dd | 2001-10-28 | Martin Nilsson | | *! @[Thread()]
|
b9bba0 | 2001-08-08 | Leif Stensson | | */
PMOD_EXPORT void f_mutex_locking_thread(INT32 args)
{
struct mutex_storage *m = THIS_MUTEX;
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | struct key_storage *k;
|
b9bba0 | 2001-08-08 | Leif Stensson | |
pop_n_elems(args);
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | for (k = m->key; k; k = k->next) {
if (k->kind == KEY_PENDING) continue;
if (m->key->owner) {
ref_push_object(m->key->owner->thread_obj);
return;
}
}
push_int(0);
|
b9bba0 | 2001-08-08 | Leif Stensson | | }
|
33887a | 2002-10-28 | Martin Stjernholm | | |
b9bba0 | 2001-08-08 | Leif Stensson | | *!
*! This mutex method returns the key object currently governing
*! the lock on this mutex. 0 is returned if the mutex isn't locked.
*!
*! @seealso
|
c7b7dd | 2001-10-28 | Martin Nilsson | | *! @[Thread()]
|
b9bba0 | 2001-08-08 | Leif Stensson | | */
PMOD_EXPORT void f_mutex_locking_key(INT32 args)
{
struct mutex_storage *m = THIS_MUTEX;
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | struct key_storage *k;
|
b9bba0 | 2001-08-08 | Leif Stensson | |
pop_n_elems(args);
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | for (k = m->key; k; k = k->next) {
if (k->kind == KEY_PENDING) continue;
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | ref_push_object(m->key->self);
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | return;
}
push_int(0);
|
b9bba0 | 2001-08-08 | Leif Stensson | | }
|
827101 | 2016-12-20 | Jonas Walldén | |
void f_mutex__sprintf (INT32 args)
{
struct mutex_storage *m = THIS_MUTEX;
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | struct key_storage *k;
|
827101 | 2016-12-20 | Jonas Walldén | | int c = 0;
if(args>0 && TYPEOF(Pike_sp[-args]) == PIKE_T_INT)
c = Pike_sp[-args].u.integer;
pop_n_elems (args);
if(c != 'O') {
push_undefined();
return;
}
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | |
k = m->key;
if (k) {
enum key_kind kind = KEY_UNINITIALIZED;
struct svalue *save_sp = Pike_sp;
push_static_text("Thread.Mutex(/*");
for (; k; k = k->next) {
if (k->kind != kind) {
kind = k->kind;
switch(kind) {
case KEY_PENDING:
push_static_text(" Waiting by");
break;
case KEY_EXCLUSIVE:
push_static_text(" Locked by");
break;
default:
break;
}
} else {
push_static_text(",");
}
push_static_text(" 0x");
push_int64(PTR_TO_INT(THREAD_T_TO_PTR(m->key->owner->id)));
f_int2hex(1);
}
push_static_text(" */)");
f_add(Pike_sp - save_sp);
|
827101 | 2016-12-20 | Jonas Walldén | | } else {
|
9acf3b | 2019-09-06 | Henrik Grubbström (Grubba) | | push_static_text("Thread.Mutex(/* Unlocked */)");
|
827101 | 2016-12-20 | Jonas Walldén | | }
}
|
f327f2 | 2018-09-23 | Henrik Grubbström (Grubba) | |
void f_mutex_cond(INT32 args)
{
ref_push_object_inherit(Pike_fp->current_object,
Pike_fp->context -
Pike_fp->current_program->inherits);
push_object(clone_object(condition_program, 1));
}
|
74dfe8 | 2012-12-30 | Jonas Walldén | | void init_mutex_obj(struct object *UNUSED(o))
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | {
co_init(& THIS_MUTEX->condition);
|
b46752 | 2017-06-25 | Martin Nilsson | | #ifdef PIKE_NULL_IS_SPECIAL
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | THIS_MUTEX->key=0;
|
270295 | 2004-04-21 | Martin Stjernholm | | THIS_MUTEX->num_waiting = 0;
|
b46752 | 2017-06-25 | Martin Nilsson | | #endif
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | }
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | |
|
74dfe8 | 2012-12-30 | Jonas Walldén | | void exit_mutex_obj(struct object *UNUSED(o))
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | {
|
270295 | 2004-04-21 | Martin Stjernholm | | struct mutex_storage *m = THIS_MUTEX;
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | struct key_storage *key = m->key;
|
270295 | 2004-04-21 | Martin Stjernholm | |
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(1, "DESTROYING MUTEX m:%p\n", THIS_MUTEX);
|
270295 | 2004-04-21 | Martin Stjernholm | |
|
5fba12 | 2004-04-26 | Martin Stjernholm | | #ifndef PICKY_MUTEX
if (key) {
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(1, "Destructed mutex is in use - delaying cleanup\n");
|
5fba12 | 2004-04-26 | Martin Stjernholm | | }
else {
#ifdef PIKE_DEBUG
if (m->num_waiting)
Pike_error ("key/num_waiting confusion.\n");
#endif
co_destroy(& m->condition);
}
#else
|
f72d41 | 2004-04-23 | Henrik Grubbström (Grubba) | | if(key) {
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | struct key_storage *next = key->next;
|
270295 | 2004-04-21 | Martin Stjernholm | | m->key=0;
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | for (; key; key = next) {
next = key->next;
key->prev = NULL;
key->next = NULL;
destruct(key->self);
}
|
270295 | 2004-04-21 | Martin Stjernholm | | if(m->num_waiting)
{
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(1, "Destructed mutex is being waited on.\n");
|
845456 | 2017-04-26 | Henrik Grubbström (Grubba) | | THREADS_ALLOW();
|
270295 | 2004-04-21 | Martin Stjernholm | |
co_broadcast (&m->condition);
|
845456 | 2017-04-26 | Henrik Grubbström (Grubba) | |
#ifdef HAVE_NO_YIELD
sleep(0);
#else /* HAVE_NO_YIELD */
th_yield();
#endif /* HAVE_NO_YIELD */
THREADS_DISALLOW();
|
270295 | 2004-04-21 | Martin Stjernholm | | }
}
|
8af562 | 2016-08-09 | Henrik Grubbström (Grubba) | | else {
|
5fba12 | 2004-04-26 | Martin Stjernholm | | co_destroy(& m->condition);
|
8af562 | 2016-08-09 | Henrik Grubbström (Grubba) | | }
|
5fba12 | 2004-04-26 | Martin Stjernholm | | #endif
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | }
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | |
|
192ceb | 2003-11-22 | Henrik Grubbström (Grubba) | | |
0c56d5 | 2021-07-23 | Henrik Grubbström (Grubba) | | *! and @[Mutex()->trylock()] et al. They are also passed as arguments
|
192ceb | 2003-11-22 | Henrik Grubbström (Grubba) | | *! to @[Condition()->wait()].
*!
*! As long as they are held, the corresponding mutex will be locked.
*!
*! The corresponding mutex will be unlocked when the object
*! is destructed (eg by not having any references left).
*!
*! @seealso
*! @[Mutex], @[Condition]
*/
|
60d987 | 2000-03-23 | Fredrik Hübinette (Hubbe) | | #define THIS_KEY ((struct key_storage *)(CURRENT_STORAGE))
|
74dfe8 | 2012-12-30 | Jonas Walldén | | void init_mutex_key_obj(struct object *UNUSED(o))
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | {
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(1, "KEY k:%p, t:%p\n",
THIS_KEY, Pike_interpreter.thread_state);
|
b46752 | 2017-06-25 | Martin Nilsson | | #ifdef PIKE_NULL_IS_SPECIAL
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | THIS_KEY->mut=0;
|
33887a | 2002-10-28 | Martin Stjernholm | | THIS_KEY->mutex_obj = NULL;
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | THIS_KEY->prev = NULL;
THIS_KEY->next = NULL;
|
b46752 | 2017-06-25 | Martin Nilsson | | #endif
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | THIS_KEY->self = Pike_fp->current_object;
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | THIS_KEY->owner = Pike_interpreter.thread_state;
|
84091f | 2015-09-07 | Arne Goedeke | | THIS_KEY->owner_obj = Pike_interpreter.thread_state->thread_obj;
if (THIS_KEY->owner_obj)
add_ref(THIS_KEY->owner_obj);
|
ea9a82 | 2020-06-24 | Henrik Grubbström (Grubba) | | THIS_KEY->kind = KEY_INITIALIZED;
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | }
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | |
|
74dfe8 | 2012-12-30 | Jonas Walldén | | void exit_mutex_key_obj(struct object *DEBUGUSED(o))
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | {
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(1, "UNLOCK k:%p m:(%p) t:%p o:%p\n",
THIS_KEY, THIS_KEY->mut,
Pike_interpreter.thread_state, THIS_KEY->owner);
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | if(THIS_KEY->mut)
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | {
|
03b1fe | 1997-09-06 | Per Hedbor | | struct mutex_storage *mut = THIS_KEY->mut;
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | struct key_storage *key = THIS_KEY;
|
f72d41 | 2004-04-23 | Henrik Grubbström (Grubba) | | struct object *mutex_obj;
|
c11387 | 1997-09-15 | Henrik Grubbström (Grubba) | |
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | |
if (key->prev) {
|
71f3a2 | 1998-11-22 | Fredrik Hübinette (Hubbe) | | #ifdef PIKE_DEBUG
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | if(key->prev->next != key)
Pike_fatal("Inconsistent mutex key link %p != %p!\n",
key->prev->next, key);
#endif
if ((key->prev->next = key->next)) {
key->next->prev = key->prev;
}
key->prev = NULL;
} else {
#ifdef PIKE_DEBUG
if(mut->key && (mut->key != key))
Pike_fatal("Mutex unlock from wrong key %p != %p!\n",
key->mut->key, key);
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | #endif
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | if ((mut->key = key->next)) {
key->next->prev = NULL;
}
}
key->next = NULL;
|
46d7bf | 1997-09-03 | Henrik Grubbström (Grubba) | | if (THIS_KEY->owner) {
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | THIS_KEY->owner = NULL;
}
if (THIS_KEY->owner_obj) {
free_object(THIS_KEY->owner_obj);
THIS_KEY->owner_obj=0;
|
46d7bf | 1997-09-03 | Henrik Grubbström (Grubba) | | }
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | THIS_KEY->mut=0;
|
ea9a82 | 2020-06-24 | Henrik Grubbström (Grubba) | | THIS_KEY->kind = KEY_UNINITIALIZED;
|
f72d41 | 2004-04-23 | Henrik Grubbström (Grubba) | | mutex_obj = THIS_KEY->mutex_obj;
THIS_KEY->mutex_obj = NULL;
|
845456 | 2017-04-26 | Henrik Grubbström (Grubba) | |
if (mut->num_waiting) {
THREADS_ALLOW();
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | co_broadcast(&mut->condition);
|
845456 | 2017-04-26 | Henrik Grubbström (Grubba) | |
#ifdef HAVE_NO_YIELD
sleep(0);
#else /* HAVE_NO_YIELD */
th_yield();
#endif /* HAVE_NO_YIELD */
THREADS_DISALLOW();
} else if (mutex_obj && !mutex_obj->prog) {
|
270295 | 2004-04-21 | Martin Stjernholm | | co_destroy (&mut->condition);
|
8af562 | 2016-08-09 | Henrik Grubbström (Grubba) | | }
|
845456 | 2017-04-26 | Henrik Grubbström (Grubba) | |
|
73cd0e | 2005-11-15 | Henrik Grubbström (Grubba) | | if (mutex_obj)
free_object(mutex_obj);
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | }
}
|
0c56d5 | 2021-07-23 | Henrik Grubbström (Grubba) | |
|
27f1f9 | 2019-05-20 | Henrik Grubbström (Grubba) | | static void f_mutex_key__sprintf(INT32 args)
{
int c = 0;
if(args>0 && TYPEOF(Pike_sp[-args]) == PIKE_T_INT)
c = Pike_sp[-args].u.integer;
pop_n_elems (args);
if(c != 'O') {
push_undefined();
return;
}
if (THIS_KEY->mutex_obj) {
|
9acf3b | 2019-09-06 | Henrik Grubbström (Grubba) | | push_text("Thread.MutexKey(/* %O */)");
|
27f1f9 | 2019-05-20 | Henrik Grubbström (Grubba) | | ref_push_object(THIS_KEY->mutex_obj);
f_sprintf(2);
} else {
|
9acf3b | 2019-09-06 | Henrik Grubbström (Grubba) | | push_text("Thread.MutexKey(/* Unlocked */)");
|
27f1f9 | 2019-05-20 | Henrik Grubbström (Grubba) | | }
}
|
0c56d5 | 2021-07-23 | Henrik Grubbström (Grubba) | |
|
a94a08 | 2020-07-02 | Henrik Grubbström (Grubba) | | static void f_mutex_key_downgrade(INT32 args)
{
struct key_storage *key = THIS_KEY;
if (key->kind < KEY_PENDING) return;
if (key->kind == KEY_PENDING) {
Pike_error("It is not possible to downgrade a key that is waiting.\n");
}
key->kind = KEY_DOWNGRADED;
co_broadcast(&key->mut->condition);
}
|
0c56d5 | 2021-07-23 | Henrik Grubbström (Grubba) | |
|
a94a08 | 2020-07-02 | Henrik Grubbström (Grubba) | | static void f_mutex_key_upgrade(INT32 args)
{
struct key_storage *key = THIS_KEY;
struct mutex_storage *m = key->mut;
if (key->kind >= KEY_PENDING) return;
if (key->kind != KEY_DOWNGRADED) {
Pike_error("Upgrade is not allowed for non-degraded mutex keys.\n");
}
if(key->next)
{
if(threads_disabled)
{
Pike_error("Cannot wait for mutexes when threads are disabled!\n");
}
key->kind = KEY_PENDING;
m->num_waiting++;
do
{
THREADS_FPRINTF(1, "WAITING TO LOCK m:%p\n", m);
SWAP_OUT_CURRENT_THREAD();
co_wait_interpreter(& m->condition);
SWAP_IN_CURRENT_THREAD();
check_threads_etc();
} while (key->next);
m->num_waiting--;
}
key->kind = KEY_EXCLUSIVE;
}
|
0c56d5 | 2021-07-23 | Henrik Grubbström (Grubba) | |
|
a94a08 | 2020-07-02 | Henrik Grubbström (Grubba) | | static void f_mutex_key_try_upgrade(INT32 args)
{
struct key_storage *key = THIS_KEY;
if (key->kind >= KEY_PENDING) {
push_int(1);
return;
}
if (key->kind != KEY_DOWNGRADED) {
Pike_error("Upgrade is not allowed for non-degraded mutex keys.\n");
}
if (key->next) {
push_int(0);
return;
}
key->kind = KEY_EXCLUSIVE;
push_int(1);
}
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | |
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | enum rwmux_kind
{
RWMUX_NONE = 0,
|
3d1d6e | 2020-06-23 | Henrik Grubbström (Grubba) | | RWMUX_TRY_READ = RWMUX_NONE,
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | RWMUX_READ,
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | RWMUX_DOWNGRADED,
|
3d1d6e | 2020-06-23 | Henrik Grubbström (Grubba) | | RWMUX_TRY_WRITE = RWMUX_DOWNGRADED,
|
1adec6 | 2020-12-09 | Henrik Grubbström (Grubba) | | RWMUX_UPGRADING,
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | RWMUX_WRITE,
};
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | struct rwmutex_key_storage
{
|
1adec6 | 2020-12-09 | Henrik Grubbström (Grubba) | | struct object *self;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | struct rwmutex_storage *rwmutex;
struct object *rwmutex_obj;
struct thread_state *owner;
struct object *owner_obj;
struct rwmutex_key_storage *prev;
struct rwmutex_key_storage *next;
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | enum rwmux_kind kind;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | };
struct rwmutex_storage
{
COND_T condition;
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | int readers;
int writers;
|
355584 | 2020-06-21 | Henrik Grubbström (Grubba) | | struct rwmutex_key_storage *key;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | };
#define THIS_RWMUTEX ((struct rwmutex_storage *)Pike_fp->current_storage)
static void init_rwmutex_obj(struct object *o)
{
co_init(&THIS_RWMUTEX->condition);
}
static void exit_rwmutex_obj(struct object *o)
{
co_destroy(&THIS_RWMUTEX->condition);
}
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | |
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | *!
*! Obtain a lock for reading (shared lock).
*!
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | | *! @throws
*! Throws an error if the current thread already has
|
0e4ebd | 2020-06-12 | Henrik Grubbström (Grubba) | | *! a lock (read or write).
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | | *!
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | *! @seealso
|
3d1d6e | 2020-06-23 | Henrik Grubbström (Grubba) | | *! @[try_read_lock()], @[write_lock()]
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | */
static void f_rwmutex_read_lock(INT32 args)
{
ref_push_object_inherit(Pike_fp->current_object,
Pike_fp->context -
Pike_fp->current_object->prog->inherits);
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | push_int(RWMUX_READ);
push_object(clone_object(rwmutex_key_program, 2));
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | }
|
3d1d6e | 2020-06-23 | Henrik Grubbström (Grubba) | |
static void f_rwmutex_try_read_lock(INT32 args)
{
ref_push_object_inherit(Pike_fp->current_object,
Pike_fp->context -
Pike_fp->current_object->prog->inherits);
push_int(RWMUX_TRY_READ);
push_object(clone_object(rwmutex_key_program, 2));
}
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | |
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | *!
*! Obtain a lock for writing (exclusive lock).
*!
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | | *! @throws
*! Throws an error if the current thread already has
|
0e4ebd | 2020-06-12 | Henrik Grubbström (Grubba) | | *! a lock (read or write).
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | | *!
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | *! @seealso
|
3d1d6e | 2020-06-23 | Henrik Grubbström (Grubba) | | *! @[read_lock()], @[try_read_lock()], @[try_write_lock()]
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | */
static void f_rwmutex_write_lock(INT32 args)
{
ref_push_object_inherit(Pike_fp->current_object,
Pike_fp->context -
Pike_fp->current_object->prog->inherits);
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | push_int(RWMUX_WRITE);
push_object(clone_object(rwmutex_key_program, 2));
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | }
|
3d1d6e | 2020-06-23 | Henrik Grubbström (Grubba) | |
static void f_rwmutex_try_write_lock(INT32 args)
{
ref_push_object_inherit(Pike_fp->current_object,
Pike_fp->context -
Pike_fp->current_object->prog->inherits);
push_int(RWMUX_TRY_WRITE);
push_object(clone_object(rwmutex_key_program, 2));
}
|
1adec6 | 2020-12-09 | Henrik Grubbström (Grubba) | |
static void f_rwmutex_current_locking_threads(INT32 args)
{
struct rwmutex_storage *m = THIS_RWMUTEX;
struct rwmutex_key_storage *key;
int count = 0;
for (key = m->key; key; key = key->next) {
if (key->owner_obj && key->owner_obj->prog) {
ref_push_object(key->owner_obj);
count++;
}
}
f_aggregate(count);
}
static void f_rwmutex_current_locking_keys(INT32 args)
{
struct rwmutex_storage *m = THIS_RWMUTEX;
struct rwmutex_key_storage *key;
int count = 0;
for (key = m->key; key; key = key->next) {
if (key->self && key->self->prog) {
ref_push_object(key->self);
count++;
}
}
f_aggregate(count);
}
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | |
static void f_rwmutex__sprintf(INT32 args)
{
struct rwmutex_storage *m = THIS_RWMUTEX;
int c = 0;
struct rwmutex_key_storage *key;
struct svalue *save_sp;
if(args>0 && TYPEOF(Pike_sp[-args]) == PIKE_T_INT)
c = Pike_sp[-args].u.integer;
pop_n_elems (args);
if(c != 'O') {
push_undefined();
return;
}
save_sp = Pike_sp;
push_static_text("Thread.RWMutex(/* r");
push_int(m->readers);
push_static_text("/w");
push_int(m->writers);
|
355584 | 2020-06-21 | Henrik Grubbström (Grubba) | | if (m->key) {
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | push_static_text(" Locked by");
|
355584 | 2020-06-21 | Henrik Grubbström (Grubba) | | for (key = m->key; key; key = key->next) {
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | if (key->owner) {
if (!c) {
push_static_text(",");
}
push_static_text(" 0x");
push_int64(PTR_TO_INT(THREAD_T_TO_PTR(key->owner->id)));
f_int2hex(1);
c = 0;
}
}
}
push_static_text(" */)");
f_add(Pike_sp - save_sp);
}
|
1adec6 | 2020-12-09 | Henrik Grubbström (Grubba) | |
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | #define THIS_RWKEY ((struct rwmutex_key_storage *)(CURRENT_STORAGE))
static void init_rwmutex_key_obj(struct object *UNUSED(o))
{
|
1adec6 | 2020-12-09 | Henrik Grubbström (Grubba) | |
THIS_RWKEY->self = Pike_fp->current_object;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | if (THIS_RWKEY->owner_obj) {
free_object(THIS_RWKEY->owner_obj);
}
THIS_RWKEY->owner = Pike_interpreter.thread_state;
THIS_RWKEY->owner_obj = Pike_interpreter.thread_state->thread_obj;
if (THIS_RWKEY->owner_obj)
add_ref(THIS_RWKEY->owner_obj);
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | THIS_RWKEY->kind = RWMUX_NONE;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | }
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | static void exit_rwmutex_key_obj(struct object *UNUSED(o))
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | {
if (THIS_RWKEY->rwmutex) {
struct rwmutex_storage *rwmutex = THIS_RWKEY->rwmutex;
struct object *rwmutex_obj = THIS_RWKEY->rwmutex_obj;
THIS_RWKEY->rwmutex = NULL;
THIS_RWKEY->rwmutex_obj = NULL;
if (THIS_RWKEY->owner_obj) {
free_object(THIS_RWKEY->owner_obj);
}
THIS_RWKEY->owner = NULL;
THIS_RWKEY->owner_obj = NULL;
if (THIS_RWKEY->prev) {
THIS_RWKEY->prev->next = THIS_RWKEY->next;
} else {
|
355584 | 2020-06-21 | Henrik Grubbström (Grubba) | | rwmutex->key = THIS_RWKEY->next;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | }
if (THIS_RWKEY->next) {
THIS_RWKEY->next->prev = THIS_RWKEY->prev;
}
THIS_RWKEY->next = NULL;
THIS_RWKEY->prev = NULL;
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | THIS_RWKEY->rwmutex = NULL;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | |
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | switch(THIS_RWKEY->kind) {
case RWMUX_NONE:
break;
case RWMUX_READ:
rwmutex->readers--;
break;
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | case RWMUX_DOWNGRADED:
rwmutex->writers = 0;
rwmutex->readers--;
break;
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | case RWMUX_WRITE:
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | rwmutex->writers = 0;
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | break;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | }
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | THIS_RWKEY->kind = RWMUX_NONE;
co_broadcast(&rwmutex->condition);
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | if (rwmutex_obj) {
free_object(rwmutex_obj);
}
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | |
THREADS_ALLOW();
#ifdef HAVE_NO_YIELD
sleep(0);
#else
th_yield();
#endif
THREADS_DISALLOW();
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | }
}
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | static void f_rwmutex_key_create(INT32 args)
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | {
struct object *rwmutex_obj = NULL;
struct rwmutex_storage *rwmutex = NULL;
|
0817a5 | 2019-10-14 | Henrik Grubbström (Grubba) | | struct rwmutex_key_storage *m;
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | enum rwmux_kind kind = RWMUX_READ;
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | | int self_count = 0;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | |
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | get_all_args("create", args, "%o.%d", &rwmutex_obj, &kind);
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | if (!(rwmutex = get_storage(rwmutex_obj, rwmutex_program))) {
SIMPLE_ARG_TYPE_ERROR("create", 1, "RWMutex");
}
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | | while (THIS_RWKEY->rwmutex) {
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | exit_rwmutex_key_obj(NULL);
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | | }
|
355584 | 2020-06-21 | Henrik Grubbström (Grubba) | | for (m = rwmutex->key; m; m = m->next) {
|
0817a5 | 2019-10-14 | Henrik Grubbström (Grubba) | | if ((m->owner == Pike_interpreter.thread_state) && (m->owner)) {
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | | self_count++;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | }
}
|
0e4ebd | 2020-06-12 | Henrik Grubbström (Grubba) | | if (self_count) {
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | |
Pike_error("Recursive mutex locks!\n");
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | }
init_rwmutex_key_obj(NULL);
THIS_RWKEY->rwmutex = rwmutex;
THIS_RWKEY->rwmutex_obj = rwmutex_obj;
add_ref(rwmutex_obj);
THIS_RWKEY->prev = NULL;
|
355584 | 2020-06-21 | Henrik Grubbström (Grubba) | | if ((THIS_RWKEY->next = rwmutex->key)) {
rwmutex->key->prev = THIS_RWKEY;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | }
|
355584 | 2020-06-21 | Henrik Grubbström (Grubba) | | rwmutex->key = THIS_RWKEY;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | |
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | THIS_RWKEY->kind = RWMUX_NONE;
switch(kind) {
|
3d1d6e | 2020-06-23 | Henrik Grubbström (Grubba) | | case RWMUX_TRY_READ:
if (rwmutex->writers > 0) {
destruct_object(Pike_fp->current_object, DESTRUCT_EXPLICIT);
break;
}
rwmutex->readers++;
THIS_RWKEY->kind = RWMUX_READ;
break;
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | case RWMUX_READ:
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | * - <=0 - Add reader.
* (No active writers.)
* 0 1 0 Wait for writers to go to 0.
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | * (Some other thread is attempting to
* take a write lock.)
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | * >0 1 >0 Add reader.
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | * (We already have a lock, which the other
* thread is waiting for, so avoid dead lock.)
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | * - >1 0 Wait for writers to go to 0.
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | * (Some other thread has a write lock.)
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | * - >1 >0 Add reader.
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | * (As we have a lock and there is at least
* one write lock, we must be the owners
* of the write lock.)
*/
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | |
SWAP_OUT_CURRENT_THREAD();
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | while(rwmutex->writers > 0) {
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | | co_wait_interpreter(&rwmutex->condition);
}
SWAP_IN_CURRENT_THREAD();
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | |
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | rwmutex->readers++;
THIS_RWKEY->kind = RWMUX_READ;
break;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | |
|
3d1d6e | 2020-06-23 | Henrik Grubbström (Grubba) | | case RWMUX_TRY_WRITE:
if (rwmutex->writers || rwmutex->readers) {
destruct_object(Pike_fp->current_object, DESTRUCT_EXPLICIT);
break;
}
rwmutex->writers = 2;
THIS_RWKEY->kind = RWMUX_WRITE;
break;
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | case RWMUX_WRITE:
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | * - 0 - Set writers to 1, wait for readers
* to go to 0, Set writers to 2.
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | * (No write lock active.)
* - -1 0 Wait for writers to go to 0, then as above.
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | * (Some other thread has a degraded write
* lock.)
* - 1 0 Wait for writers to go to 0, then as above.
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | * (Some other thread is attempting to
* get a write lock.)
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | * - >1 0 Wait for writers to go to 0, then as above.
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | * (Some other thread has a write lock.)
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | * - >1 >0 Add writer.
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | * (As we have a lock and there is at least
* one write lock, we must be the owners
* of the write lock.)
*
* Problem:
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | * >0 1 >0 (Some other thread is attempting to get
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | * a write lock (waiting on us). If
* self_count == readers, then we could
* take the write lock, complete and then
* restore the -1, but if the other thread
* also has a self_count >0 we run into
* a dead lock.)
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | | */
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | |
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | SWAP_OUT_CURRENT_THREAD();
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | | while(rwmutex->writers) {
co_wait_interpreter(&rwmutex->condition);
}
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | |
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | rwmutex->writers = 1;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | |
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | while(rwmutex->readers) {
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | | co_wait_interpreter(&rwmutex->condition);
}
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | |
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | rwmutex->writers = 2;
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | SWAP_IN_CURRENT_THREAD();
THIS_RWKEY->kind = RWMUX_WRITE;
break;
|
f86a3f | 2019-10-16 | Henrik Grubbström (Grubba) | | }
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | }
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | |
static void f_rwmutex_key_downgrade(INT32 args)
{
if (THIS_RWKEY->kind <= RWMUX_DOWNGRADED) {
return;
}
THIS_RWKEY->kind = RWMUX_DOWNGRADED;
THIS_RWKEY->rwmutex->readers = 1;
THIS_RWKEY->rwmutex->writers = -1;
|
81770b | 2020-06-16 | Henrik Grubbström (Grubba) | |
co_broadcast(&THIS_RWKEY->rwmutex->condition);
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | }
|
3d1d6e | 2020-06-23 | Henrik Grubbström (Grubba) | | *! @[try_upgrade()], @[downgrade()]
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | */
static void f_rwmutex_key_upgrade(INT32 args)
{
struct rwmutex_storage *rwmutex = NULL;
if (THIS_RWKEY->kind < RWMUX_DOWNGRADED) {
Pike_error("Unsupported operation -- not a (degraded) write lock.\n");
}
if (THIS_RWKEY->kind == RWMUX_WRITE) {
return;
}
THIS_RWKEY->kind = RWMUX_NONE;
rwmutex = THIS_RWKEY->rwmutex;
rwmutex->readers--;
rwmutex->writers = 1;
SWAP_OUT_CURRENT_THREAD();
while(rwmutex->readers) {
co_wait_interpreter(&rwmutex->condition);
}
SWAP_IN_CURRENT_THREAD();
rwmutex->writers = 2;
THIS_RWKEY->kind = RWMUX_WRITE;
}
|
3d1d6e | 2020-06-23 | Henrik Grubbström (Grubba) | |
static void f_rwmutex_key_try_upgrade(INT32 args)
{
struct rwmutex_storage *rwmutex = NULL;
if (THIS_RWKEY->kind < RWMUX_DOWNGRADED) {
Pike_error("Unsupported operation -- not a (degraded) write lock.\n");
}
if (THIS_RWKEY->kind == RWMUX_DOWNGRADED) {
rwmutex = THIS_RWKEY->rwmutex;
if (rwmutex->readers != 1) {
push_int(0);
return;
}
rwmutex->readers = 0;
rwmutex->writers = 2;
THIS_RWKEY->kind = RWMUX_WRITE;
}
push_int(1);
}
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | static void f_rwmutex_key__sprintf(INT32 args)
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | {
int c = 0;
get_all_args("_sprintf", args, "%d", &c);
if (c != 'O') {
push_undefined();
return;
}
if (THIS_RWKEY->rwmutex_obj) {
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | push_text("Thread.RWKey(/* %O, %s */)");
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | ref_push_object(THIS_RWKEY->rwmutex_obj);
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | switch(THIS_RWKEY->kind) {
case RWMUX_NONE:
push_text("Unlocked");
break;
case RWMUX_READ:
push_text("Read-lock");
break;
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | case RWMUX_DOWNGRADED:
push_text("Downgraded-write-lock");
break;
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | case RWMUX_WRITE:
push_text("Write-lock");
break;
}
f_sprintf(3);
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | } else {
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | push_text("Thread.RWKey(/* Unlocked */)");
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | }
}
|
192ceb | 2003-11-22 | Henrik Grubbström (Grubba) | |
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | |
1520f1 | 2018-12-07 | Stephen R. van den Berg | | *! In order to prevent races (which is the whole point of condition
*! variables), the modification of a shared resource and the signal notifying
*! modification of the resource must be performed inside the same mutex
*! lock, and the examining of the resource and waiting for a signal that
*! the resource has changed based on that examination must also happen
*! inside the same mutex lock.
*!
*! Typical wait operation:
*! @ol
|
ac0b6f | 2020-12-15 | H William Welliver | | *! @item
*! Take mutex lock
*! @item
*! Read/write shared resource
*! @item
*! Wait for the signal with the mutex lock in released state
*! @item
*! Reacquire mutex lock
*! @item
*! If needed, jump back to step 2 again
*! @item
*! Release mutex lock
|
1520f1 | 2018-12-07 | Stephen R. van den Berg | | *! @endol
*!
*! Typical signal operation:
*! @ol
|
ac0b6f | 2020-12-15 | H William Welliver | | *! @item
*! Take mutex lock
*! @item
*! Read/write shared resource
*! @item
*! Send signal
*! @item
*! Release mutex lock
|
1520f1 | 2018-12-07 | Stephen R. van den Berg | | *! @endol
*!
*! @example
*! You have some resource that multiple treads want to use. To
*! protect this resource for simultaneous access, you create a shared mutex.
*! Before you read or write the resource, you take the mutex so that you
*! get a consistent and private view of / control over it. When you decide
*! that the resource is not in the state you want it, and that you need
*! to wait for some other thread to modify the state for you before you
*! can continue, you wait on the conditional variable, which will
*! temporarily relinquish the mutex during the wait. This way a
*! different thread can take the mutex, update the state of the resource,
*! and then signal the condition (which does not in itself release the
*! mutex, but the signalled thread will be next in line once the mutex is
*! released).
*!
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *! @note
*! Condition variables are only available on systems with thread
*! support. The Condition class is not simulated otherwise, since that
*! can't be done accurately without continuations.
*!
*! @seealso
|
c7b7dd | 2001-10-28 | Martin Nilsson | | *! @[Mutex]
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | */
|
8349b4 | 2006-01-29 | Henrik Grubbström (Grubba) | | struct pike_cond {
COND_T cond;
int wait_count;
|
5c2f2f | 2018-09-16 | Henrik Grubbström (Grubba) | | struct object *mutex_obj;
|
8349b4 | 2006-01-29 | Henrik Grubbström (Grubba) | | };
|
b0c72a | 2006-01-30 | Henrik Grubbström (Grubba) | | #define THIS_COND ((struct pike_cond *)(CURRENT_STORAGE))
|
8349b4 | 2006-01-29 | Henrik Grubbström (Grubba) | |
|
5c2f2f | 2018-09-16 | Henrik Grubbström (Grubba) | |
static void f_cond_create(INT32 args)
{
struct pike_cond *cond = THIS_COND;
struct object *mux = NULL;
get_all_args("create", args, ".%O", &mux);
if (cond->mutex_obj) {
free_object(cond->mutex_obj);
cond->mutex_obj = NULL;
}
if (mux) {
struct program *prog = mux->prog;
if (prog) {
prog = prog->inherits[SUBTYPEOF(Pike_sp[-args])].prog;
if (prog == mutex_program) {
cond->mutex_obj = mux;
add_ref(mux);
}
}
}
}
|
4a59c0 | 2002-09-30 | Henrik Grubbström (Grubba) | | |
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | *! @decl void wait(Thread.MutexKey mutex_key, int(0..)|float seconds)
*! @decl void wait(Thread.MutexKey mutex_key, int(0..) seconds, @
*! int(0..999999999) nanos)
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *!
|
2ef3b9 | 2005-01-25 | Henrik Grubbström (Grubba) | | *! Wait for condition.
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *!
*! This function makes the current thread sleep until the condition
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | *! variable is signalled or the timeout is reached.
*!
*! @param mutex_key
*! A @[Thread.MutexKey] object for a @[Thread.Mutex]. It will be
*! unlocked atomically before waiting for the signal and then
*! relocked atomically when the signal is received or the timeout
*! is reached.
*!
*! @param seconds
*! Seconds to wait before the timeout is reached.
*!
*! @param nanos
*! Nano (1/1000000000) seconds to wait before the timeout is reached.
*! This value is added to the number of seconds specified by @[seconds].
*!
*! A timeout of zero seconds disables the timeout.
|
270295 | 2004-04-21 | Martin Stjernholm | | *!
*! The thread that sends the signal should have the mutex locked
*! while sending it. Otherwise it's impossible to avoid races where
*! signals are sent while the listener(s) haven't arrived to the
*! @[wait] calls yet.
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *!
|
4a59c0 | 2002-09-30 | Henrik Grubbström (Grubba) | | *! @note
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | *! The support for timeouts was added in Pike 7.8.121, which was
*! after the first public release of Pike 7.8.
*!
*! @note
*! Note that the timeout is approximate (best effort), and may
*! be exceeded if eg the mutex is busy after the timeout.
*!
*! @note
|
8349b4 | 2006-01-29 | Henrik Grubbström (Grubba) | | *! Note also that any threads waiting on the condition will be
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | *! woken up when it gets destructed.
|
8349b4 | 2006-01-29 | Henrik Grubbström (Grubba) | | *!
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *! @seealso
|
c7b7dd | 2001-10-28 | Martin Nilsson | | *! @[Mutex->lock()]
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | */
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | void f_cond_wait(INT32 args)
{
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | struct object *key_obj, *mutex_obj;
|
4a59c0 | 2002-09-30 | Henrik Grubbström (Grubba) | | struct mutex_storage *mut;
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | struct key_storage *key;
|
8349b4 | 2006-01-29 | Henrik Grubbström (Grubba) | | struct pike_cond *c;
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | INT_TYPE seconds = 0, nanos = 0;
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | |
|
1c3c3d | 2000-03-24 | Henrik Grubbström (Grubba) | | if(threads_disabled)
|
b2d3e4 | 2000-12-01 | Fredrik Hübinette (Hubbe) | | Pike_error("Cannot wait for conditions when threads are disabled!\n");
|
4a59c0 | 2002-09-30 | Henrik Grubbström (Grubba) | |
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | if (args <= 2) {
FLOAT_TYPE fsecs = 0.0;
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | get_all_args(NULL, args, "%o.%F", &key_obj, &fsecs);
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | seconds = (INT_TYPE) fsecs;
nanos = (INT_TYPE)((fsecs - seconds)*1000000000);
} else {
|
078c6d | 2010-10-10 | Martin Stjernholm | |
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | get_all_args(NULL, args, "%o%i%i", &key_obj, &seconds, &nanos);
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | }
|
13670c | 2015-05-25 | Martin Nilsson | |
|
5c2f2f | 2018-09-16 | Henrik Grubbström (Grubba) | | c = THIS_COND;
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | if ((key_obj->prog != mutex_key) ||
(!((key = OB2KEY(key_obj))->kind)) ||
(!(mut = key->mut)) ||
(c->mutex_obj && key->mutex_obj &&
(key->mutex_obj != c->mutex_obj))) {
|
69c0aa | 2014-08-25 | Martin Nilsson | | Pike_error("Bad argument 1 to wait()\n");
|
4a59c0 | 2002-09-30 | Henrik Grubbström (Grubba) | | }
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | if (key->kind != KEY_EXCLUSIVE) {
Pike_error("Bad argument 1 to wait()\n");
}
|
1c3c3d | 2000-03-24 | Henrik Grubbström (Grubba) | | if(args > 1) {
pop_n_elems(args - 1);
args = 1;
}
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | |
|
4a59c0 | 2002-09-30 | Henrik Grubbström (Grubba) | |
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | mutex_obj = key->mutex_obj;
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | if (key->prev) {
if ((key->prev->next = key->next)) {
key->next->prev = key->prev;
}
key->prev = NULL;
} else {
if ((mut->key = key->next)) {
key->next->prev = NULL;
}
}
key->next = NULL;
|
d46191 | 2020-06-26 | Henrik Grubbström (Grubba) | | key->mut = NULL;
key->mutex_obj = NULL;
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | key->kind = KEY_INITIALIZED;
co_broadcast(& mut->condition);
|
13670c | 2015-05-25 | Martin Nilsson | |
|
768559 | 2019-09-06 | Henrik Grubbström (Grubba) | | if (!c->mutex_obj) {
c->mutex_obj = mutex_obj;
add_ref(mutex_obj);
}
|
4a59c0 | 2002-09-30 | Henrik Grubbström (Grubba) | |
|
1c3c3d | 2000-03-24 | Henrik Grubbström (Grubba) | | SWAP_OUT_CURRENT_THREAD();
|
8349b4 | 2006-01-29 | Henrik Grubbström (Grubba) | | c->wait_count++;
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | if (seconds || nanos) {
co_wait_interpreter_timeout(&(c->cond), seconds, nanos);
} else {
co_wait_interpreter(&(c->cond));
}
|
8349b4 | 2006-01-29 | Henrik Grubbström (Grubba) | | c->wait_count--;
|
1c3c3d | 2000-03-24 | Henrik Grubbström (Grubba) | | SWAP_IN_CURRENT_THREAD();
|
13670c | 2015-05-25 | Martin Nilsson | |
|
8af562 | 2016-08-09 | Henrik Grubbström (Grubba) | | if (!mutex_obj->prog) {
Pike_error("Mutex was destructed while waiting for cond.\n");
}
|
4a59c0 | 2002-09-30 | Henrik Grubbström (Grubba) | |
|
d059be | 2004-04-23 | Martin Stjernholm | | mut->num_waiting++;
|
35fa44 | 2020-06-27 | Henrik Grubbström (Grubba) | | {
key->kind = KEY_PENDING;
if ((key->next = mut->key)) {
key->next->prev = key;
}
mut->key = key;
key->mut = mut;
key->mutex_obj = mutex_obj;
while(key->next) {
SWAP_OUT_CURRENT_THREAD();
co_wait_interpreter(& mut->condition);
SWAP_IN_CURRENT_THREAD();
check_threads_etc();
}
key->kind = KEY_EXCLUSIVE;
|
4a59c0 | 2002-09-30 | Henrik Grubbström (Grubba) | | }
|
f72d41 | 2004-04-23 | Henrik Grubbström (Grubba) | | mut->num_waiting--;
|
d059be | 2004-04-23 | Martin Stjernholm | |
|
4a59c0 | 2002-09-30 | Henrik Grubbström (Grubba) | | pop_stack();
return;
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | }
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | |
a9cdcf | 2001-02-06 | Henrik Grubbström (Grubba) | | *! @note
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *! Sometimes more than one thread is woken up.
*!
*! @seealso
*! @[broadcast()]
*/
|
96f63c | 2015-11-25 | Henrik Grubbström (Grubba) | | void f_cond_signal(INT32 UNUSED(args))
|
8349b4 | 2006-01-29 | Henrik Grubbström (Grubba) | | {
co_signal(&(THIS_COND->cond));
}
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | |
|
96f63c | 2015-11-25 | Henrik Grubbström (Grubba) | | void f_cond_broadcast(INT32 UNUSED(args))
|
8349b4 | 2006-01-29 | Henrik Grubbström (Grubba) | | {
co_broadcast(&(THIS_COND->cond));
}
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | |
|
508ef0 | 2019-09-06 | Henrik Grubbström (Grubba) | |
static void f_cond__sprintf(INT32 args)
{
int c = 0;
if(args>0 && TYPEOF(Pike_sp[-args]) == PIKE_T_INT)
c = Pike_sp[-args].u.integer;
pop_n_elems (args);
if(c != 'O') {
push_undefined();
return;
}
if (THIS_COND->mutex_obj) {
push_static_text("Thread.Condition(/* %O */)");
ref_push_object(THIS_COND->mutex_obj);
f_sprintf(2);
} else {
push_text("Thread.Condition(/* Unassociated */)");
}
}
|
74dfe8 | 2012-12-30 | Jonas Walldén | | void init_cond_obj(struct object *UNUSED(o))
|
8349b4 | 2006-01-29 | Henrik Grubbström (Grubba) | | {
co_init(&(THIS_COND->cond));
THIS_COND->wait_count = 0;
}
|
36e67a | 2006-01-28 | Martin Stjernholm | |
|
74dfe8 | 2012-12-30 | Jonas Walldén | | void exit_cond_obj(struct object *UNUSED(o))
|
36e67a | 2006-01-28 | Martin Stjernholm | | {
|
8349b4 | 2006-01-29 | Henrik Grubbström (Grubba) | |
while (THIS_COND->wait_count) {
|
a20b1b | 2006-04-25 | David Hedbor | | co_broadcast(&(THIS_COND->cond));
|
8349b4 | 2006-01-29 | Henrik Grubbström (Grubba) | |
THREADS_ALLOW();
#ifdef HAVE_NO_YIELD
sleep(0);
#else /* HAVE_NO_YIELD */
th_yield();
#endif /* HAVE_NO_YIELD */
THREADS_DISALLOW();
}
co_destroy(&(THIS_COND->cond));
|
5c2f2f | 2018-09-16 | Henrik Grubbström (Grubba) | |
if (THIS_COND->mutex_obj) {
free_object(THIS_COND->mutex_obj);
THIS_COND->mutex_obj = NULL;
}
|
36e67a | 2006-01-28 | Martin Stjernholm | | }
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | |
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | |
|
8b3484 | 2019-02-26 | Henrik Grubbström (Grubba) | | |
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *!
*! Returns the current call stack for the thread.
*!
|
8b3484 | 2019-02-26 | Henrik Grubbström (Grubba) | | *! @param flags
*!
*! A bit mask of flags affecting generation of the backtrace.
*!
*! Currently a single flag is defined:
*! @int
*! @value 1
*! Return @[LiveBacktraceFrame]s. This flag causes the frame
*! objects to track changes (as long as they are in use), and
*! makes eg local variables for functions available for
*! inspection or change.
*!
*! Note that since these values are "live", they may change or
*! dissapear at any time unless the corresponding thread has
*! been halted or similar.
*! @endint
*!
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *! @returns
*! The result has the same format as for @[predef::backtrace()].
*!
*! @seealso
*! @[predef::backtrace()]
*/
|
a7fef4 | 1997-09-03 | Per Hedbor | | void f_thread_backtrace(INT32 args)
{
|
17f08c | 2000-07-06 | Fredrik Hübinette (Hubbe) | | struct thread_state *foo = THIS_THREAD;
|
8b3484 | 2019-02-26 | Henrik Grubbström (Grubba) | | int flags = 0;
|
a8e989 | 2001-09-05 | Fredrik Hübinette (Hubbe) | |
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | if(foo == Pike_interpreter.thread_state)
|
fad4ca | 2001-09-05 | Fredrik Hübinette (Hubbe) | | {
|
8b3484 | 2019-02-26 | Henrik Grubbström (Grubba) | | f_backtrace(args);
return;
|
fad4ca | 2001-09-05 | Fredrik Hübinette (Hubbe) | | }
|
8b3484 | 2019-02-26 | Henrik Grubbström (Grubba) | |
|
c15e46 | 2019-05-29 | Stephen R. van den Berg | | get_all_args("backtrace", args, ".%d", &flags);
|
8b3484 | 2019-02-26 | Henrik Grubbström (Grubba) | |
pop_n_elems(args);
if(foo->state.stack_pointer)
|
a7fef4 | 1997-09-03 | Per Hedbor | | {
|
8b3484 | 2019-02-26 | Henrik Grubbström (Grubba) | | low_backtrace(& foo->state, flags);
|
fad4ca | 2001-09-05 | Fredrik Hübinette (Hubbe) | | }
else
{
|
8b3484 | 2019-02-26 | Henrik Grubbström (Grubba) | | ref_push_array(&empty_array);
|
a7fef4 | 1997-09-03 | Per Hedbor | | }
}
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | |
6f1382 | 2006-04-07 | Martin Stjernholm | | *!
*! Returns the status of the thread.
*!
*! @returns
*! @int
|
8678ad | 2006-08-09 | Martin Nilsson | | *! @value Thread.THREAD_NOT_STARTED
*! @value Thread.THREAD_RUNNING
*! @value Thread.THREAD_EXITED
|
d273ca | 2014-12-07 | Henrik Grubbström (Grubba) | | *! @value Thread.THREAD_ABORTED
|
6f1382 | 2006-04-07 | Martin Stjernholm | | *! @endint
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | */
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | void f_thread_id_status(INT32 args)
{
pop_n_elems(args);
push_int(THIS_THREAD->status);
}
|
19330c | 2020-06-20 | Stephen R. van den Berg | |
void f_thread_id_gethrvtime(INT32 args)
{
#ifdef CPU_TIME_MIGHT_BE_THREAD_LOCAL
thread_gethrvtime(THIS_THREAD, args);
#else
pop_n_elems(args);
push_int(0);
#endif
}
|
30c061 | 2008-06-29 | Martin Stjernholm | | |
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *!
|
5e50ef | 2001-09-25 | Henrik Grubbström (Grubba) | | *! Returns a string identifying the thread.
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | */
|
9a0d42 | 2000-02-06 | Martin Stjernholm | | void f_thread_id__sprintf (INT32 args)
{
|
e6dbc2 | 2002-11-29 | Marcus Comstedt | | int c = 0;
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | if(args>0 && TYPEOF(Pike_sp[-args]) == PIKE_T_INT)
|
e6dbc2 | 2002-11-29 | Marcus Comstedt | | c = Pike_sp[-args].u.integer;
|
9a0d42 | 2000-02-06 | Martin Stjernholm | | pop_n_elems (args);
|
e6dbc2 | 2002-11-29 | Marcus Comstedt | | if(c != 'O') {
push_undefined();
return;
}
|
827101 | 2016-12-20 | Jonas Walldén | | push_static_text ("Thread.Thread(0x");
|
d2361e | 2003-06-30 | Martin Stjernholm | | push_int64(PTR_TO_INT(THREAD_T_TO_PTR(THIS_THREAD->id)));
|
827101 | 2016-12-20 | Jonas Walldén | | f_int2hex(1);
|
5e9fc0 | 2015-08-18 | Per Hedbor | | push_static_text (")");
|
9a0d42 | 2000-02-06 | Martin Stjernholm | | f_add (3);
}
|
30c061 | 2008-06-29 | Martin Stjernholm | | |
5e50ef | 2001-09-25 | Henrik Grubbström (Grubba) | | *!
*! Returns an id number identifying the thread.
*/
void f_thread_id_id_number(INT32 args)
{
pop_n_elems(args);
|
d2361e | 2003-06-30 | Martin Stjernholm | | push_int64(PTR_TO_INT(THREAD_T_TO_PTR(THIS_THREAD->id)));
|
5e50ef | 2001-09-25 | Henrik Grubbström (Grubba) | | }
|
442abd | 2004-06-29 | Alexander Demenshin | | |
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *!
*! Waits for the thread to complete, and then returns
*! the value returned from the thread function.
|
d273ca | 2014-12-07 | Henrik Grubbström (Grubba) | | *!
*! @throws
*! Rethrows the error thrown by the thread if it exited by
*! throwing an error.
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | */
|
74dfe8 | 2012-12-30 | Jonas Walldén | | static void f_thread_id_result(INT32 UNUSED(args))
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | {
|
17f08c | 2000-07-06 | Fredrik Hübinette (Hubbe) | | struct thread_state *th=THIS_THREAD;
|
d273ca | 2014-12-07 | Henrik Grubbström (Grubba) | | int th_status;
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
|
4bc7e4 | 2001-11-26 | Henrik Grubbström (Grubba) | | if (threads_disabled) {
Pike_error("Cannot wait for threads when threads are disabled!\n");
}
|
0a14c2 | 2008-08-05 | Martin Stjernholm | | th->waiting++;
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "Thread->wait(): Waiting for thread_state %p "
"(state:%d).\n", th, th->status);
|
d273ca | 2014-12-07 | Henrik Grubbström (Grubba) | | while(th->status < THREAD_EXITED) {
|
700dac | 2002-02-05 | Martin Stjernholm | | SWAP_OUT_CURRENT_THREAD();
|
c91f89 | 2000-04-19 | Martin Stjernholm | | co_wait_interpreter(&th->status_change);
|
700dac | 2002-02-05 | Martin Stjernholm | | SWAP_IN_CURRENT_THREAD();
check_threads_etc();
|
f72d41 | 2004-04-23 | Henrik Grubbström (Grubba) | | THREADS_FPRINTF(0,
|
7d06ba | 2016-02-07 | Martin Nilsson | | "Thread->wait(): Waiting for thread_state %p "
"(state:%d).\n", th, th->status);
|
700dac | 2002-02-05 | Martin Stjernholm | | }
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | |
|
d273ca | 2014-12-07 | Henrik Grubbström (Grubba) | | th_status = th->status;
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | | assign_svalue_no_free(Pike_sp, &th->result);
|
17f08c | 2000-07-06 | Fredrik Hübinette (Hubbe) | | Pike_sp++;
|
50ea68 | 2003-03-14 | Henrik Grubbström (Grubba) | | dmalloc_touch_svalue(Pike_sp-1);
|
0a14c2 | 2008-08-05 | Martin Stjernholm | |
th->waiting--;
if (!th->thread_obj)
cleanup_thread_state (th);
|
d273ca | 2014-12-07 | Henrik Grubbström (Grubba) | |
if (th_status == THREAD_ABORTED) f_throw(1);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | }
|
9595b9 | 2004-08-12 | Henrik Grubbström (Grubba) | | static int num_pending_interrupts = 0;
static struct callback *thread_interrupt_callback = NULL;
static void check_thread_interrupt(struct callback *foo,
|
74dfe8 | 2012-12-30 | Jonas Walldén | | void *UNUSED(bar), void *UNUSED(gazonk))
|
9595b9 | 2004-08-12 | Henrik Grubbström (Grubba) | | {
|
18e21f | 2014-05-25 | Henrik Grubbström (Grubba) | | if (Pike_interpreter.thread_state->flags & THREAD_FLAG_INHIBIT) {
return;
}
|
286b31 | 2004-12-30 | Henrik Grubbström (Grubba) | | if (Pike_interpreter.thread_state->flags & THREAD_FLAG_SIGNAL_MASK) {
if (Pike_interpreter.thread_state->flags & THREAD_FLAG_TERM) {
throw_severity = THROW_THREAD_EXIT;
} else {
throw_severity = THROW_ERROR;
}
Pike_interpreter.thread_state->flags &= ~THREAD_FLAG_SIGNAL_MASK;
|
9595b9 | 2004-08-12 | Henrik Grubbström (Grubba) | | if (!--num_pending_interrupts) {
remove_callback(foo);
thread_interrupt_callback = NULL;
}
|
286b31 | 2004-12-30 | Henrik Grubbström (Grubba) | | if (throw_severity == THROW_ERROR) {
Pike_error("Interrupted.\n");
} else {
push_int(-1);
assign_svalue(&throw_value, Pike_sp-1);
pike_throw();
}
|
9595b9 | 2004-08-12 | Henrik Grubbström (Grubba) | | }
}
|
8d81c3 | 2018-10-12 | Henrik Grubbström (Grubba) | | *! This function causes the thread to throw an error
*! where the message defaults to @expr{"Interrupted.\n"@}.
*!
|
9595b9 | 2004-08-12 | Henrik Grubbström (Grubba) | | *! @fixme
*! The argument @[msg] is currently ignored.
*!
*! @note
*! Interrupts are asynchronous, and are currently not queued.
|
8d81c3 | 2018-10-12 | Henrik Grubbström (Grubba) | | *!
*! @note
*! Due to the asynchronous nature of interrupts, it may take
*! some time before the thread reacts to the interrupt.
|
9595b9 | 2004-08-12 | Henrik Grubbström (Grubba) | | */
static void f_thread_id_interrupt(INT32 args)
{
pop_n_elems(args);
|
286b31 | 2004-12-30 | Henrik Grubbström (Grubba) | | if (!(THIS_THREAD->flags & THREAD_FLAG_SIGNAL_MASK)) {
|
9595b9 | 2004-08-12 | Henrik Grubbström (Grubba) | | num_pending_interrupts++;
if (!thread_interrupt_callback) {
thread_interrupt_callback =
add_to_callback(&evaluator_callbacks, check_thread_interrupt, 0, 0);
}
}
|
18e21f | 2014-05-25 | Henrik Grubbström (Grubba) | | THIS_THREAD->flags |= THREAD_FLAG_INTR;
|
9595b9 | 2004-08-12 | Henrik Grubbström (Grubba) | | }
|
09a573 | 2008-08-05 | Martin Stjernholm | | static void low_thread_kill (struct thread_state *th)
{
if (!(th->flags & THREAD_FLAG_SIGNAL_MASK)) {
num_pending_interrupts++;
if (!thread_interrupt_callback) {
thread_interrupt_callback =
add_to_callback(&evaluator_callbacks, check_thread_interrupt, 0, 0);
}
}
th->flags |= THREAD_FLAG_TERM;
}
|
286b31 | 2004-12-30 | Henrik Grubbström (Grubba) | | |
8d81c3 | 2018-10-12 | Henrik Grubbström (Grubba) | | *!
*! @note
*! Due to the asynchronous nature of interrupts, it may take
*! some time before the thread reacts to the interrupt.
|
286b31 | 2004-12-30 | Henrik Grubbström (Grubba) | | */
static void f_thread_id_kill(INT32 args)
{
pop_n_elems(args);
|
09a573 | 2008-08-05 | Martin Stjernholm | | low_thread_kill (THIS_THREAD);
|
286b31 | 2004-12-30 | Henrik Grubbström (Grubba) | | }
|
74dfe8 | 2012-12-30 | Jonas Walldén | | void init_thread_obj(struct object *UNUSED(o))
|
a7fef4 | 1997-09-03 | Per Hedbor | | {
|
21b12a | 2014-09-03 | Martin Nilsson | | memset(&THIS_THREAD->state, 0, sizeof(struct Pike_interpreter_struct));
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | THIS_THREAD->thread_obj = Pike_fp->current_object;
|
16479e | 2002-11-18 | Martin Stjernholm | | THIS_THREAD->swapped = 0;
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | THIS_THREAD->status=THREAD_NOT_STARTED;
|
9595b9 | 2004-08-12 | Henrik Grubbström (Grubba) | | THIS_THREAD->flags = 0;
|
0a14c2 | 2008-08-05 | Martin Stjernholm | | THIS_THREAD->waiting = 0;
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | SET_SVAL(THIS_THREAD->result, T_INT, NUMBER_UNDEFINED, integer, 0);
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | co_init(& THIS_THREAD->status_change);
|
621e75 | 2015-10-19 | Per Hedbor | | THIS_THREAD->thread_locals=NULL;
|
247f73 | 2007-06-10 | Martin Stjernholm | | #ifdef CPU_TIME_MIGHT_BE_THREAD_LOCAL
|
f4a995 | 2003-02-08 | Martin Stjernholm | | THIS_THREAD->auto_gc_time = 0;
#endif
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | }
|
0a14c2 | 2008-08-05 | Martin Stjernholm | | static void cleanup_thread_state (struct thread_state *th)
|
574088 | 1998-01-01 | Fredrik Hübinette (Hubbe) | | {
|
0a14c2 | 2008-08-05 | Martin Stjernholm | | #ifdef PIKE_DEBUG
if (th->thread_obj) Pike_fatal ("Thread state still active.\n");
#endif
if (th->status == THREAD_RUNNING || th->waiting)
return;
|
286b31 | 2004-12-30 | Henrik Grubbström (Grubba) | | if (THIS_THREAD->flags & THREAD_FLAG_SIGNAL_MASK) {
Pike_interpreter.thread_state->flags &= ~THREAD_FLAG_SIGNAL_MASK;
|
9595b9 | 2004-08-12 | Henrik Grubbström (Grubba) | | if (!--num_pending_interrupts) {
remove_callback(thread_interrupt_callback);
thread_interrupt_callback = NULL;
|
13670c | 2015-05-25 | Martin Nilsson | | }
|
9595b9 | 2004-08-12 | Henrik Grubbström (Grubba) | | }
|
0a14c2 | 2008-08-05 | Martin Stjernholm | |
co_destroy(& THIS_THREAD->status_change);
th_destroy(& THIS_THREAD->id);
}
|
74dfe8 | 2012-12-30 | Jonas Walldén | | void exit_thread_obj(struct object *UNUSED(o))
|
0a14c2 | 2008-08-05 | Martin Stjernholm | | {
THIS_THREAD->thread_obj = NULL;
cleanup_thread_state (THIS_THREAD);
|
621e75 | 2015-10-19 | Per Hedbor | | if(THIS_THREAD->thread_locals != NULL) {
free_mapping(THIS_THREAD->thread_locals);
THIS_THREAD->thread_locals = NULL;
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | }
|
a7fef4 | 1997-09-03 | Per Hedbor | | }
|
a9cdcf | 2001-02-06 | Henrik Grubbström (Grubba) | | |
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | */
|
74dfe8 | 2012-12-30 | Jonas Walldén | | static void thread_was_recursed(struct object *UNUSED(o))
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | | {
|
17f08c | 2000-07-06 | Fredrik Hübinette (Hubbe) | | struct thread_state *tmp=THIS_THREAD;
|
621e75 | 2015-10-19 | Per Hedbor | | if(tmp->thread_locals != NULL)
gc_recurse_mapping(tmp->thread_locals);
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | }
|
74dfe8 | 2012-12-30 | Jonas Walldén | | static void thread_was_checked(struct object *UNUSED(o))
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | {
|
17f08c | 2000-07-06 | Fredrik Hübinette (Hubbe) | | struct thread_state *tmp=THIS_THREAD;
|
621e75 | 2015-10-19 | Per Hedbor | | if(tmp->thread_locals != NULL)
debug_gc_check (tmp->thread_locals,
|
d9d6f0 | 2001-06-30 | Martin Stjernholm | | " as mapping for thread local values in thread");
|
177321 | 2000-04-12 | Fredrik Hübinette (Hubbe) | |
#ifdef PIKE_DEBUG
if(tmp->swapped)
|
cc2e9f | 2003-09-24 | Martin Stjernholm | | gc_mark_stack_external (tmp->state.frame_pointer, tmp->state.stack_pointer,
tmp->state.evaluator_stack);
|
177321 | 2000-04-12 | Fredrik Hübinette (Hubbe) | | #endif
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | }
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | |
c7b7dd | 2001-10-28 | Martin Nilsson | | *! stored in an instance of @[Local] can only be retrieved by that
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *! same thread.
*!
*! @note
*! This class is simulated when Pike is compiled without thread support,
*! so it's always available.
*/
|
d4e637 | 2001-02-06 | Henrik Grubbström (Grubba) | |
|
96f63c | 2015-11-25 | Henrik Grubbström (Grubba) | | void f_thread_local_create( INT32 UNUSED(args) )
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | {
static INT32 thread_local_id = 0;
|
621e75 | 2015-10-19 | Per Hedbor | | ((struct thread_local_var *)CURRENT_STORAGE)->id =
|
031939 | 2001-02-06 | Per Hedbor | | thread_local_id++;
}
|
d86cd7 | 1998-08-24 | Marcus Comstedt | |
|
031939 | 2001-02-06 | Per Hedbor | | PMOD_EXPORT void f_thread_local(INT32 args)
{
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | struct object *loc = clone_object(thread_local_prog,0);
pop_n_elems(args);
push_object(loc);
}
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | |
c7b7dd | 2001-10-28 | Martin Nilsson | | *! This returns the value prevoiusly stored in the @[Local] object by
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | *! the @[set()] method by this thread.
*!
*! @seealso
*! @[set()]
*/
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | void f_thread_local_get(INT32 args)
{
struct svalue key;
struct mapping *m;
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | SET_SVAL(key, T_INT, NUMBER_NUMBER, integer,
|
621e75 | 2015-10-19 | Per Hedbor | | ((struct thread_local_var *)CURRENT_STORAGE)->id);
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | pop_n_elems(args);
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | | if(Pike_interpreter.thread_state != NULL &&
|
621e75 | 2015-10-19 | Per Hedbor | | (m = Pike_interpreter.thread_state->thread_locals) != NULL)
|
17f08c | 2000-07-06 | Fredrik Hübinette (Hubbe) | | mapping_index_no_free(Pike_sp++, m, &key);
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | else {
|
074dd1 | 2011-10-22 | Henrik Grubbström (Grubba) | | push_undefined();
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | }
}
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | |
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | void f_thread_local_set(INT32 args)
{
struct svalue key;
struct mapping *m;
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | SET_SVAL(key, T_INT, NUMBER_NUMBER, integer,
|
621e75 | 2015-10-19 | Per Hedbor | | ((struct thread_local_var *)CURRENT_STORAGE)->id);
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | if(args>1)
pop_n_elems(args-1);
else if(args<1)
|
06bd61 | 2016-01-26 | Martin Nilsson | | SIMPLE_WRONG_NUM_ARGS_ERROR("Thread.Local.set", 1);
|
d86cd7 | 1998-08-24 | Marcus Comstedt | |
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | if(Pike_interpreter.thread_state == NULL)
|
cd6f7e | 2000-12-01 | Martin Stjernholm | | Pike_error("Trying to set Thread.Local without thread!\n");
|
d86cd7 | 1998-08-24 | Marcus Comstedt | |
|
621e75 | 2015-10-19 | Per Hedbor | | if((m = Pike_interpreter.thread_state->thread_locals) == NULL)
m = Pike_interpreter.thread_state->thread_locals =
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | allocate_mapping(4);
|
17f08c | 2000-07-06 | Fredrik Hübinette (Hubbe) | | mapping_insert(m, &key, &Pike_sp[-1]);
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | }
|
f6d017 | 1997-10-15 | Fredrik Hübinette (Hubbe) | |
|
d9d6f0 | 2001-06-30 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
9a8ddb | 2014-11-16 | Henrik Grubbström (Grubba) | | void gc_check_thread_local (struct object *UNUSED(o))
|
d9d6f0 | 2001-06-30 | Martin Stjernholm | | {
if (Pike_in_gc == GC_PASS_LOCATE) {
struct svalue key, *val;
struct thread_state *s;
|
017b57 | 2011-10-28 | Henrik Grubbström (Grubba) | | SET_SVAL(key, T_INT, NUMBER_NUMBER, integer,
|
621e75 | 2015-10-19 | Per Hedbor | | ((struct thread_local_var *)CURRENT_STORAGE)->id);
|
d9d6f0 | 2001-06-30 | Martin Stjernholm | |
|
f2c01e | 2003-01-08 | Martin Stjernholm | | FOR_EACH_THREAD (s, {
|
621e75 | 2015-10-19 | Per Hedbor | | if (s->thread_locals &&
(val = low_mapping_lookup(s->thread_locals, &key)))
|
e1a35e | 2003-09-08 | Martin Stjernholm | | debug_gc_check_svalues (val, 1,
|
d9d6f0 | 2001-06-30 | Martin Stjernholm | | " as thread local value in Thread.Local object"
" (indirect ref)");
|
f2c01e | 2003-01-08 | Martin Stjernholm | | });
|
d9d6f0 | 2001-06-30 | Martin Stjernholm | | }
}
#endif
|
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | |
|
a9cdcf | 2001-02-06 | Henrik Grubbström (Grubba) | |
|
64b7b6 | 2000-11-02 | Henrik Grubbström (Grubba) | | |
13670c | 2015-05-25 | Martin Nilsson | | *
|
64b7b6 | 2000-11-02 | Henrik Grubbström (Grubba) | | */
static struct farmer {
struct farmer *neighbour;
void *field;
void (*harvest)(void *);
THREAD_T me;
COND_T harvest_moon;
#ifdef HAVE_BROKEN_LINUX_THREAD_EUID
int euid, egid;
#endif /* HAVE_BROKEN_LINUX_THREAD_EUID */
} *farmers;
|
74ea78 | 2016-01-29 | Martin Nilsson | | static PIKE_MUTEX_T rosie;
|
64b7b6 | 2000-11-02 | Henrik Grubbström (Grubba) | |
static int _num_farmers, _num_idle_farmers;
static TH_RETURN_TYPE farm(void *_a)
{
struct farmer *me = (struct farmer *)_a;
#ifdef HAVE_BROKEN_LINUX_THREAD_EUID
if (!geteuid()) {
|
f663a0 | 2003-03-05 | Martin Stjernholm | | #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
int current = prctl(PR_GET_DUMPABLE);
#endif
|
b096df | 2014-03-13 | Per Hedbor | | #ifdef HAVE_BROKEN_LINUX_THREAD_EUID
if( setegid(arg.egid) != 0 || seteuid(arg.euid) != 0 )
{
|
fa7766 | 2016-02-11 | Martin Nilsson | | WERR("%s:%d: Unexpected error from setegid(2). errno=%d\n",
__FILE__, __LINE__, errno);
|
b096df | 2014-03-13 | Per Hedbor | | }
#endif
|
f663a0 | 2003-03-05 | Martin Stjernholm | | #if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
if (prctl(PR_SET_DUMPABLE, current) == -1)
Pike_fatal ("Didn't expect prctl to go wrong. errno=%d\n", errno);
#endif
|
64b7b6 | 2000-11-02 | Henrik Grubbström (Grubba) | | }
#endif /* HAVE_BROKEN_LINUX_THREAD_EUID */
do
{
me->harvest( me->field );
me->harvest = 0;
mt_lock( &rosie );
if( ++_num_idle_farmers > 16 )
{
--_num_idle_farmers;
--_num_farmers;
mt_unlock( &rosie );
free( me );
return 0;
}
me->neighbour = farmers;
farmers = me;
|
fa7766 | 2016-02-11 | Martin Nilsson | |
|
64b7b6 | 2000-11-02 | Henrik Grubbström (Grubba) | | while(!me->harvest) co_wait( &me->harvest_moon, &rosie );
--_num_idle_farmers;
mt_unlock( &rosie );
} while(1);
|
9282fd | 2015-09-27 | Martin Nilsson | | UNREACHABLE(return 0);
|
64b7b6 | 2000-11-02 | Henrik Grubbström (Grubba) | | }
int th_num_idle_farmers(void)
{
return _num_idle_farmers;
}
int th_num_farmers(void)
{
return _num_farmers;
}
static struct farmer *new_farmer(void (*fun)(void *), void *args)
{
struct farmer *me = malloc(sizeof(struct farmer));
if (!me) {
|
5aad93 | 2002-08-15 | Marcus Comstedt | | Pike_fatal("new_farmer(): Out of memory!\n");
|
64b7b6 | 2000-11-02 | Henrik Grubbström (Grubba) | | }
dmalloc_accept_leak(me);
_num_farmers++;
me->neighbour = 0;
me->field = args;
me->harvest = fun;
co_init( &me->harvest_moon );
#ifdef HAVE_BROKEN_LINUX_THREAD_EUID
me->euid = geteuid();
me->egid = getegid();
#endif /* HAVE_BROKEN_LINUX_THREAD_EUID */
th_create_small(&me->me, farm, me);
return me;
}
PMOD_EXPORT void th_farm(void (*fun)(void *), void *here)
{
|
6e00e2 | 2003-11-13 | Martin Stjernholm | | #ifdef PIKE_DEBUG
|
5aad93 | 2002-08-15 | Marcus Comstedt | | if(!fun) Pike_fatal("The farmers don't known how to handle empty fields\n");
|
6e00e2 | 2003-11-13 | Martin Stjernholm | | #endif
|
64b7b6 | 2000-11-02 | Henrik Grubbström (Grubba) | | mt_lock( &rosie );
if(farmers)
{
struct farmer *f = farmers;
farmers = f->neighbour;
f->field = here;
f->harvest = fun;
mt_unlock( &rosie );
co_signal( &f->harvest_moon );
return;
}
mt_unlock( &rosie );
new_farmer( fun, here );
}
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | void low_th_init(void)
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | {
|
7d06ba | 2016-02-07 | Martin Nilsson | | THREADS_FPRINTF(0, "Initializing threads.\n");
|
fed8de | 1997-10-05 | Henrik Grubbström (Grubba) | |
|
83b184 | 2003-02-08 | Martin Stjernholm | | really_low_th_init();
|
fed8de | 1997-10-05 | Henrik Grubbström (Grubba) | |
|
12ae2f | 1997-09-05 | Henrik Grubbström (Grubba) | | mt_init( & interpreter_lock);
|
63ba77 | 2010-10-12 | Martin Stjernholm | | mt_init( & interpreter_lock_wanted);
|
bc21dc | 2001-11-01 | Martin Stjernholm | | low_mt_lock_interpreter();
|
eac209 | 1998-02-27 | Marcus Comstedt | | mt_init( & thread_table_lock);
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | mt_init( & interleave_lock);
|
64b7b6 | 2000-11-02 | Henrik Grubbström (Grubba) | | mt_init( & rosie);
|
ef1e93 | 1998-03-26 | Henrik Grubbström (Grubba) | | co_init( & live_threads_change);
co_init( & threads_disabled_change);
|
eac209 | 1998-02-27 | Marcus Comstedt | | thread_table_init();
|
864d3c | 1998-01-29 | Fredrik Hübinette (Hubbe) | |
|
92ec35 | 2010-10-23 | Martin Stjernholm | | #if defined(RDTSC) && defined(USE_CLOCK_FOR_SLICES)
|
f91994 | 2010-10-17 | Martin Stjernholm | | {
INT32 cpuid[4];
x86_get_cpuid (1, cpuid);
|
fb09e9 | 2015-09-28 | Martin Nilsson | | use_tsc_for_slices = cpuid[2] & 0x10;
|
927d3c | 2010-10-24 | Martin Stjernholm | | #if 0
|
f91994 | 2010-10-17 | Martin Stjernholm | | if (use_tsc_for_slices) {
x86_get_cpuid (0x80000007, cpuid);
|
fb09e9 | 2015-09-28 | Martin Nilsson | | use_tsc_for_slices = cpuid[2] & 0x100;
|
f91994 | 2010-10-17 | Martin Stjernholm | | }
|
927d3c | 2010-10-24 | Martin Stjernholm | | #endif
|
f91994 | 2010-10-17 | Martin Stjernholm | | }
#endif
|
b32ef1 | 2000-04-19 | Martin Stjernholm | | th_running = 1;
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | }
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | static struct object *backend_thread_obj = NULL;
|
d97eb7 | 2011-07-10 | Henrik Grubbström (Grubba) | | static struct Pike_interpreter_struct *original_interpreter = NULL;
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | | void th_init(void)
{
|
89fc4c | 2000-08-10 | Henrik Grubbström (Grubba) | | ptrdiff_t mutex_key_offset;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | ptrdiff_t rwmutex_key_offset;
|
a91ca0 | 1998-07-10 | Henrik Grubbström (Grubba) | |
|
e4419e | 1997-02-06 | Fredrik Hübinette (Hubbe) | | #ifdef UNIX_THREADS
|
13670c | 2015-05-25 | Martin Nilsson | |
|
45ee5d | 1999-02-10 | Fredrik Hübinette (Hubbe) | | ADD_EFUN("thread_set_concurrency",f_thread_set_concurrency,tFunc(tInt,tVoid), OPT_SIDE_EFFECT);
|
e4419e | 1997-02-06 | Fredrik Hübinette (Hubbe) | | #endif
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | |
|
15ecdc | 2011-04-02 | Martin Stjernholm | | #ifdef PIKE_DEBUG
ADD_EFUN("_thread_swaps", f__thread_swaps,
tFunc(tVoid,tInt), OPT_SIDE_EFFECT);
ADD_EFUN("_check_threads_calls", f__check_threads_calls,
tFunc(tVoid,tInt), OPT_SIDE_EFFECT);
ADD_EFUN("_check_threads_yields", f__check_threads_yields,
tFunc(tVoid,tInt), OPT_SIDE_EFFECT);
ADD_EFUN("_check_threads_swaps", f__check_threads_swaps,
tFunc(tVoid,tInt), OPT_SIDE_EFFECT);
#endif
|
3f87be | 1999-12-14 | Martin Stjernholm | | START_NEW_PROGRAM_ID(THREAD_MUTEX_KEY);
|
90e978 | 1999-01-31 | Fredrik Hübinette (Hubbe) | | mutex_key_offset = ADD_STORAGE(struct key_storage);
|
46d7bf | 1997-09-03 | Henrik Grubbström (Grubba) | | |
e413da | 2001-02-01 | Henrik Grubbström (Grubba) | | * It also allows a thread to take over ownership of a key.
|
46d7bf | 1997-09-03 | Henrik Grubbström (Grubba) | | */
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | PIKE_MAP_VARIABLE("_owner",
mutex_key_offset + OFFSETOF(key_storage, owner_obj),
|
33887a | 2002-10-28 | Martin Stjernholm | | tObjIs_THREAD_ID, T_OBJECT, 0);
PIKE_MAP_VARIABLE("_mutex", mutex_key_offset + OFFSETOF(key_storage, mutex_obj),
|
95489a | 2008-06-29 | Martin Nilsson | | tObjIs_THREAD_MUTEX, T_OBJECT, ID_PROTECTED|ID_PRIVATE);
|
27f1f9 | 2019-05-20 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("_sprintf",f_mutex_key__sprintf,tFunc(tInt,tStr),ID_PROTECTED);
|
a94a08 | 2020-07-02 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("downgrade", f_mutex_key_downgrade, tFunc(tNone,tVoid), 0);
ADD_FUNCTION("upgrade", f_mutex_key_upgrade, tFunc(tNone,tVoid), 0);
ADD_FUNCTION("try_upgrade", f_mutex_key_try_upgrade, tFunc(tNone,tInt01), 0);
|
598892 | 1996-10-05 | Fredrik Hübinette (Hubbe) | | set_init_callback(init_mutex_key_obj);
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | set_exit_callback(exit_mutex_key_obj);
|
bad516 | 2000-06-23 | Fredrik Hübinette (Hubbe) | | mutex_key=Pike_compiler->new_program;
|
3f87be | 1999-12-14 | Martin Stjernholm | | add_ref(mutex_key);
end_class("mutex_key", 0);
|
b1f4eb | 1998-01-13 | Fredrik Hübinette (Hubbe) | | mutex_key->flags|=PROGRAM_DESTRUCT_IMMEDIATE;
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | |
|
3f87be | 1999-12-14 | Martin Stjernholm | | START_NEW_PROGRAM_ID(THREAD_MUTEX);
|
52e4c6 | 1999-12-13 | Martin Stjernholm | | ADD_STORAGE(struct mutex_storage);
|
3f87be | 1999-12-14 | Martin Stjernholm | | ADD_FUNCTION("lock",f_mutex_lock,
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | tOr(tFunc(tOr(tInt02,tVoid) tOr3(tVoid, tIntPos, tFloat),
tObjIs_THREAD_MUTEX_KEY),
tFunc(tInt02 tIntPos tIntPos, tObjIs_THREAD_MUTEX_KEY)), 0);
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("shared_lock",f_mutex_shared_lock,
|
6018db | 2021-07-21 | Henrik Grubbström (Grubba) | | tOr(tFunc(tOr(tInt02,tVoid) tOr3(tVoid, tIntPos, tFloat),
tObjIs_THREAD_MUTEX_KEY),
tFunc(tInt02 tIntPos tIntPos, tObjIs_THREAD_MUTEX_KEY)), 0);
|
3f87be | 1999-12-14 | Martin Stjernholm | | ADD_FUNCTION("trylock",f_mutex_trylock,
tFunc(tOr(tInt02,tVoid),tObjIs_THREAD_MUTEX_KEY),0);
|
4781e5 | 2020-06-28 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("try_shared_lock",f_mutex_try_shared_lock,
tFunc(tOr(tInt02,tVoid),tObjIs_THREAD_MUTEX_KEY),0);
|
b9bba0 | 2001-08-08 | Leif Stensson | | ADD_FUNCTION("current_locking_thread",f_mutex_locking_thread,
tFunc(tNone,tObjIs_THREAD_ID), 0);
ADD_FUNCTION("current_locking_key",f_mutex_locking_key,
tFunc(tNone,tObjIs_THREAD_MUTEX_KEY), 0);
|
4c4b75 | 2017-06-24 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("_sprintf",f_mutex__sprintf,tFunc(tInt,tStr),0);
|
5bb8d0 | 2018-09-27 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("condition", f_mutex_cond,
tFunc(tNone, tObjIs_THREAD_CONDITION), 0);
|
52e4c6 | 1999-12-13 | Martin Stjernholm | | set_init_callback(init_mutex_obj);
set_exit_callback(exit_mutex_obj);
|
5c2f2f | 2018-09-16 | Henrik Grubbström (Grubba) | | mutex_program = Pike_compiler->new_program;
add_ref(mutex_program);
|
52e4c6 | 1999-12-13 | Martin Stjernholm | | end_class("mutex", 0);
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | START_NEW_PROGRAM_ID(THREAD_RWMUTEX_KEY);
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | rwmutex_key_offset = ADD_STORAGE(struct rwmutex_key_storage);
PIKE_MAP_VARIABLE("_owner",
rwmutex_key_offset +
OFFSETOF(rwmutex_key_storage, owner_obj),
tObjIs_THREAD_ID, T_OBJECT, 0);
PIKE_MAP_VARIABLE("_mutex", rwmutex_key_offset +
OFFSETOF(rwmutex_key_storage, rwmutex_obj),
tObjIs_THREAD_MUTEX, T_OBJECT, ID_PROTECTED|ID_PRIVATE);
set_init_callback(init_rwmutex_key_obj);
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | set_exit_callback(exit_rwmutex_key_obj);
ADD_FUNCTION("create", f_rwmutex_key_create,
tFunc(tOr(tObjIs_THREAD_RWMUTEX, tVoid)
tOr(tInt02, tVoid), tVoid),
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | ID_PROTECTED);
|
e94404 | 2020-06-14 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("downgrade", f_rwmutex_key_downgrade,
tFunc(tNone, tVoid), 0);
ADD_FUNCTION("upgrade", f_rwmutex_key_upgrade,
tFunc(tNone, tVoid), 0);
|
3d1d6e | 2020-06-23 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("try_upgrade", f_rwmutex_key_try_upgrade,
tFunc(tNone, tInt01), 0);
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("_sprintf", f_rwmutex_key__sprintf,
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | tFunc(tOr(tInt, tVoid), tStr), ID_PROTECTED);
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | rwmutex_key_program = Pike_compiler->new_program;
add_ref(rwmutex_key_program);
end_class("RWKey", 0);
rwmutex_key_program->flags |= PROGRAM_DESTRUCT_IMMEDIATE;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | |
START_NEW_PROGRAM_ID(THREAD_RWMUTEX);
ADD_STORAGE(struct rwmutex_storage);
ADD_FUNCTION("read_lock", f_rwmutex_read_lock,
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | tFunc(tNone, tObjIs_THREAD_RWMUTEX_KEY), 0);
|
3d1d6e | 2020-06-23 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("try_read_lock", f_rwmutex_try_read_lock,
tFunc(tNone, tObjIs_THREAD_RWMUTEX_KEY), 0);
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("write_lock", f_rwmutex_write_lock,
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | tFunc(tNone, tObjIs_THREAD_RWMUTEX_KEY), 0);
|
3d1d6e | 2020-06-23 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("try_write_lock", f_rwmutex_try_write_lock,
tFunc(tNone, tObjIs_THREAD_RWMUTEX_KEY), 0);
|
1adec6 | 2020-12-09 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("current_locking_threads", f_rwmutex_current_locking_threads,
tFunc(tNone, tArr(tObjImpl_THREAD_ID)), 0);
ADD_FUNCTION("current_locking_keys", f_rwmutex_current_locking_keys,
tFunc(tNone, tArr(tObjImpl_THREAD_RWMUTEX_KEY)), 0);
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("_sprintf", f_rwmutex__sprintf,
tFunc(tOr(tInt, tVoid), tStr), ID_PROTECTED);
set_init_callback(init_rwmutex_obj);
set_exit_callback(exit_rwmutex_obj);
rwmutex_program = Pike_compiler->new_program;
add_ref(rwmutex_program);
end_class("RWMutex", 0);
|
3f87be | 1999-12-14 | Martin Stjernholm | | START_NEW_PROGRAM_ID(THREAD_CONDITION);
|
8349b4 | 2006-01-29 | Henrik Grubbström (Grubba) | | ADD_STORAGE(struct pike_cond);
|
5c2f2f | 2018-09-16 | Henrik Grubbström (Grubba) | | PIKE_MAP_VARIABLE("_mutex", OFFSETOF(pike_cond, mutex_obj),
tObjIs_THREAD_MUTEX, T_OBJECT, ID_PROTECTED|ID_PRIVATE);
ADD_FUNCTION("create", f_cond_create,
tFunc(tOr(tObjIs_THREAD_MUTEX, tVoid), tVoid),
ID_PROTECTED);
|
3f87be | 1999-12-14 | Martin Stjernholm | | ADD_FUNCTION("wait",f_cond_wait,
|
4a5f54 | 2009-01-25 | Henrik Grubbström (Grubba) | | tOr(tFunc(tObjIs_THREAD_MUTEX_KEY tOr3(tVoid, tIntPos, tFloat),
tVoid),
tFunc(tObjIs_THREAD_MUTEX_KEY tIntPos tIntPos, tVoid)),0);
|
b93e6e | 1999-06-19 | Fredrik Hübinette (Hubbe) | | ADD_FUNCTION("signal",f_cond_signal,tFunc(tNone,tVoid),0);
ADD_FUNCTION("broadcast",f_cond_broadcast,tFunc(tNone,tVoid),0);
|
508ef0 | 2019-09-06 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("_sprintf", f_cond__sprintf,
tFunc(tOr(tInt, tVoid), tStr), ID_PROTECTED);
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | set_init_callback(init_cond_obj);
set_exit_callback(exit_cond_obj);
|
f327f2 | 2018-09-23 | Henrik Grubbström (Grubba) | | condition_program = Pike_compiler->new_program;
add_ref(condition_program);
|
b98eb3 | 1997-02-11 | Henrik Grubbström (Grubba) | | end_class("condition", 0);
|
13670c | 2015-05-25 | Martin Nilsson | |
|
de413f | 1998-03-26 | Per Hedbor | | {
struct program *tmp;
|
3f87be | 1999-12-14 | Martin Stjernholm | | START_NEW_PROGRAM_ID(THREAD_DISABLE_THREADS);
|
de413f | 1998-03-26 | Per Hedbor | | set_init_callback(init_threads_disable);
set_exit_callback(exit_threads_disable);
|
bad516 | 2000-06-23 | Fredrik Hübinette (Hubbe) | | tmp = Pike_compiler->new_program;
|
3f87be | 1999-12-14 | Martin Stjernholm | | add_ref(tmp);
end_class("threads_disabled", 0);
|
de413f | 1998-03-26 | Per Hedbor | | tmp->flags|=PROGRAM_DESTRUCT_IMMEDIATE;
add_global_program("_disable_threads", tmp);
|
56a696 | 1998-04-05 | Fredrik Hübinette (Hubbe) | | free_program(tmp);
|
de413f | 1998-03-26 | Per Hedbor | | }
|
6d1a5e | 1996-10-07 | Fredrik Hübinette (Hubbe) | |
|
3f87be | 1999-12-14 | Martin Stjernholm | | START_NEW_PROGRAM_ID(THREAD_LOCAL);
|
621e75 | 2015-10-19 | Per Hedbor | | ADD_STORAGE(struct thread_local_var);
|
b93e6e | 1999-06-19 | Fredrik Hübinette (Hubbe) | | ADD_FUNCTION("get",f_thread_local_get,tFunc(tNone,tMix),0);
|
b21d9e | 2000-11-06 | Martin Stjernholm | | ADD_FUNCTION("set",f_thread_local_set,tFunc(tSetvar(1,tMix),tVar(1)),0);
|
d4e637 | 2001-02-06 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("create", f_thread_local_create,
|
4c4b75 | 2017-06-24 | Henrik Grubbström (Grubba) | | tFunc(tNone,tVoid), ID_PROTECTED);
|
d9d6f0 | 2001-06-30 | Martin Stjernholm | | #ifdef PIKE_DEBUG
set_gc_check_callback(gc_check_thread_local);
#endif
|
bad516 | 2000-06-23 | Fredrik Hübinette (Hubbe) | | thread_local_prog=Pike_compiler->new_program;
|
3f87be | 1999-12-14 | Martin Stjernholm | | add_ref(thread_local_prog);
end_class("thread_local", 0);
|
d4e637 | 2001-02-06 | Henrik Grubbström (Grubba) | | ADD_EFUN("thread_local", f_thread_local,
|
3f87be | 1999-12-14 | Martin Stjernholm | | tFunc(tNone,tObjIs_THREAD_LOCAL),
|
d4e637 | 2001-02-06 | Henrik Grubbström (Grubba) | | OPT_EXTERNAL_DEPEND);
|
d86cd7 | 1998-08-24 | Marcus Comstedt | |
|
3f87be | 1999-12-14 | Martin Stjernholm | | START_NEW_PROGRAM_ID(THREAD_ID);
|
17f08c | 2000-07-06 | Fredrik Hübinette (Hubbe) | | thread_storage_offset=ADD_STORAGE(struct thread_state);
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | | PIKE_MAP_VARIABLE("result", OFFSETOF(thread_state, result),
tMix, T_MIXED, 0);
ADD_FUNCTION("create",f_thread_create,
|
761bb0 | 2015-08-20 | Henrik Grubbström (Grubba) | | tFuncV(tMixed,tMixed,tVoid),
|
95489a | 2008-06-29 | Martin Nilsson | | ID_PROTECTED);
|
671ae8 | 2019-08-04 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("backtrace", f_thread_backtrace,
tFunc(tOr(tVoid,tInt01),tArray), 0);
|
b93e6e | 1999-06-19 | Fredrik Hübinette (Hubbe) | | ADD_FUNCTION("wait",f_thread_id_result,tFunc(tNone,tMix),0);
ADD_FUNCTION("status",f_thread_id_status,tFunc(tNone,tInt),0);
|
19330c | 2020-06-20 | Stephen R. van den Berg | | ADD_FUNCTION("gethrvtime",f_thread_id_gethrvtime,tFunc(tNone,tInt),0);
|
4c4b75 | 2017-06-24 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("_sprintf",f_thread_id__sprintf,tFunc(tInt,tStr),0);
|
5e50ef | 2001-09-25 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("id_number",f_thread_id_id_number,tFunc(tNone,tInt),0);
|
9595b9 | 2004-08-12 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("interrupt", f_thread_id_interrupt,
tFunc(tOr(tVoid,tStr), tVoid), 0);
|
286b31 | 2004-12-30 | Henrik Grubbström (Grubba) | | ADD_FUNCTION("kill", f_thread_id_kill, tFunc(tNone, tVoid), 0);
|
a5bd2b | 2000-06-10 | Martin Stjernholm | | set_gc_recurse_callback(thread_was_recursed);
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | set_gc_check_callback(thread_was_checked);
|
a7fef4 | 1997-09-03 | Per Hedbor | | set_init_callback(init_thread_obj);
|
a2db6b | 1998-01-02 | Fredrik Hübinette (Hubbe) | | set_exit_callback(exit_thread_obj);
|
bad516 | 2000-06-23 | Fredrik Hübinette (Hubbe) | | thread_id_prog=Pike_compiler->new_program;
|
95363a | 2000-04-11 | Fredrik Hübinette (Hubbe) | | thread_id_prog->flags |= PROGRAM_NO_EXPLICIT_DESTRUCT;
|
3f87be | 1999-12-14 | Martin Stjernholm | | add_ref(thread_id_prog);
end_class("thread_id", 0);
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | |
add_global_program("thread_create", thread_id_prog);
|
3f87be | 1999-12-14 | Martin Stjernholm | |
ADD_EFUN("this_thread",f_this_thread,
tFunc(tNone,tObjIs_THREAD_ID),
OPT_EXTERNAL_DEPEND);
ADD_EFUN("all_threads",f_all_threads,
tFunc(tNone,tArr(tObjIs_THREAD_ID)),
OPT_EXTERNAL_DEPEND);
|
52e4c6 | 1999-12-13 | Martin Stjernholm | |
|
7a5298 | 2015-09-09 | Henrik Grubbström (Grubba) | | ADD_EFUN("get_thread_quanta", f_get_thread_quanta,
tFunc(tNone, tInt),
OPT_EXTERNAL_DEPEND);
ADD_EFUN("set_thread_quanta", f_set_thread_quanta,
tFunc(tInt, tInt),
OPT_EXTERNAL_DEPEND);
|
5d2f12 | 1998-08-27 | Henrik Grubbström (Grubba) | |
add_integer_constant("THREAD_NOT_STARTED", THREAD_NOT_STARTED, 0);
add_integer_constant("THREAD_RUNNING", THREAD_RUNNING, 0);
add_integer_constant("THREAD_EXITED", THREAD_EXITED, 0);
|
d273ca | 2014-12-07 | Henrik Grubbström (Grubba) | | add_integer_constant("THREAD_ABORTED", THREAD_ABORTED, 0);
|
5d2f12 | 1998-08-27 | Henrik Grubbström (Grubba) | |
|
d97eb7 | 2011-07-10 | Henrik Grubbström (Grubba) | | original_interpreter = Pike_interpreter_pointer;
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | backend_thread_obj = fast_clone_object(thread_id_prog);
INIT_THREAD_STATE((struct thread_state *)(backend_thread_obj->storage +
|
b867f9 | 2003-02-16 | Martin Stjernholm | | thread_storage_offset));
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | | thread_table_insert(Pike_interpreter.thread_state);
|
6d1a5e | 1996-10-07 | Fredrik Hübinette (Hubbe) | | }
|
09a573 | 2008-08-05 | Martin Stjernholm | | #ifdef DO_PIKE_CLEANUP
void cleanup_all_other_threads (void)
{
int i, num_kills = num_pending_interrupts;
time_t timeout = time (NULL) + 2;
mt_lock (&thread_table_lock);
for (i = 0; i < THREAD_TABLE_SIZE; i++) {
struct thread_state *th;
for (th = thread_table_chains[i]; th; th = th->hashlink)
if (th != Pike_interpreter.thread_state) {
low_thread_kill (th);
num_kills++;
}
}
mt_unlock (&thread_table_lock);
while (num_pending_interrupts && time (NULL) < timeout) {
THREADS_ALLOW();
|
371406 | 2010-02-18 | Stephen R. van den Berg | | sysleep(1.0);
|
09a573 | 2008-08-05 | Martin Stjernholm | | THREADS_DISALLOW();
}
|
0a2bf6 | 2008-08-05 | Martin Stjernholm | | #if 0
|
09a573 | 2008-08-05 | Martin Stjernholm | | if (num_kills) {
|
fa7766 | 2016-02-11 | Martin Nilsson | | WERR("Killed %d thread(s) in exit cleanup",
num_kills - num_pending_interrupts);
|
09a573 | 2008-08-05 | Martin Stjernholm | | if (num_pending_interrupts)
|
fa7766 | 2016-02-11 | Martin Nilsson | | WERR(", %d more haven't responded", num_pending_interrupts);
|
09a573 | 2008-08-05 | Martin Stjernholm | | fputs (".\n", stderr);
}
|
0a2bf6 | 2008-08-05 | Martin Stjernholm | | #endif
|
09a573 | 2008-08-05 | Martin Stjernholm | | }
#endif
|
be478c | 1997-08-30 | Henrik Grubbström (Grubba) | | void th_cleanup(void)
|
6d1a5e | 1996-10-07 | Fredrik Hübinette (Hubbe) | | {
|
b32ef1 | 2000-04-19 | Martin Stjernholm | | th_running = 0;
|
043131 | 2003-02-15 | Henrik Grubbström (Grubba) | | if (Pike_interpreter.thread_state) {
thread_table_delete(Pike_interpreter.thread_state);
Pike_interpreter.thread_state = NULL;
}
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | if(backend_thread_obj)
|
c3b995 | 2000-02-15 | Henrik Grubbström (Grubba) | | {
|
d97eb7 | 2011-07-10 | Henrik Grubbström (Grubba) | |
*original_interpreter = Pike_interpreter;
|
de78e6 | 2020-03-02 | Henrik Grubbström (Grubba) | |
|
1d456f | 2003-02-20 | Henrik Grubbström (Grubba) | | destruct(backend_thread_obj);
free_object(backend_thread_obj);
backend_thread_obj = NULL;
|
d97eb7 | 2011-07-10 | Henrik Grubbström (Grubba) | |
Pike_interpreter_pointer = original_interpreter;
|
56f4f4 | 2001-09-18 | Fredrik Hübinette (Hubbe) | | destruct_objects_to_destruct_cb();
|
c3b995 | 2000-02-15 | Henrik Grubbström (Grubba) | | }
|
f327f2 | 2018-09-23 | Henrik Grubbström (Grubba) | | if(condition_program)
{
free_program(condition_program);
condition_program = NULL;
}
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | if(rwmutex_program)
{
free_program(rwmutex_program);
rwmutex_program = NULL;
}
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | if(rwmutex_key_program)
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | {
|
cff417 | 2020-06-13 | Henrik Grubbström (Grubba) | | free_program(rwmutex_key_program);
rwmutex_key_program = NULL;
|
ca8582 | 2019-08-21 | Henrik Grubbström (Grubba) | | }
|
5c2f2f | 2018-09-16 | Henrik Grubbström (Grubba) | | if(mutex_program)
{
free_program(mutex_program);
mutex_program = NULL;
}
|
6d1a5e | 1996-10-07 | Fredrik Hübinette (Hubbe) | | if(mutex_key)
{
free_program(mutex_key);
mutex_key=0;
}
|
d86cd7 | 1998-08-24 | Marcus Comstedt | | if(thread_local_prog)
{
free_program(thread_local_prog);
thread_local_prog=0;
}
|
6d1a5e | 1996-10-07 | Fredrik Hübinette (Hubbe) | | if(thread_id_prog)
{
free_program(thread_id_prog);
thread_id_prog=0;
}
|
58580c | 2001-11-12 | Martin Stjernholm | |
#ifdef PIKE_USE_OWN_ATFORK
free_callback_list(&atfork_prepare_callback);
free_callback_list(&atfork_parent_callback);
free_callback_list(&atfork_child_callback);
#endif
|
07513e | 1996-10-04 | Fredrik Hübinette (Hubbe) | | }
|
83b184 | 2003-02-08 | Martin Stjernholm | | #endif /* !CONFIGURE_TEST */
|
ab9501 | 2021-06-19 | Henrik Grubbström (Grubba) | | #else /* !_REENTRANT */
|
2b902c | 2021-06-21 | Henrik Grubbström (Grubba) | | #ifndef CONFIGURE_TEST
|
ab9501 | 2021-06-19 | Henrik Grubbström (Grubba) | | PMOD_EXPORT void call_with_interpreter(void (*func)(void *ctx), void *ctx)
{
JMP_BUF back;
if(SETJMP(back))
{
if(throw_severity <= THROW_ERROR) {
call_handle_error();
}
if(throw_severity == THROW_EXIT)
{
pike_do_exit(throw_value.u.integer);
}
} else {
back.severity=THROW_EXIT;
func(ctx);
}
UNSETJMP(back);
}
|
2b902c | 2021-06-21 | Henrik Grubbström (Grubba) | | #endif /* !CONFIGURE_TEST */
|
ab9501 | 2021-06-19 | Henrik Grubbström (Grubba) | |
#endif /* _REENTRANT */
|