Places uses pthread timers to timout green threads
svn: r16311
This commit is contained in:
parent
059ec602fb
commit
ef0062637e
|
@ -1491,7 +1491,7 @@ typedef void (*Scheme_Invoke_Proc)(Scheme_Env *env, long phase_shift,
|
||||||
# define scheme_fuel_counter (*scheme_fuel_counter_ptr)
|
# define scheme_fuel_counter (*scheme_fuel_counter_ptr)
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
MZ_EXTERN volatile int scheme_fuel_counter;
|
MZ_EXTERN THREAD_LOCAL volatile int scheme_fuel_counter;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FUEL_AUTODECEREMENTS
|
#ifdef FUEL_AUTODECEREMENTS
|
||||||
|
|
|
@ -147,7 +147,7 @@
|
||||||
#define EMBEDDED_DEFINES_START_ANYWHERE 0
|
#define EMBEDDED_DEFINES_START_ANYWHERE 0
|
||||||
|
|
||||||
/* globals */
|
/* globals */
|
||||||
volatile int scheme_fuel_counter;
|
THREAD_LOCAL volatile int scheme_fuel_counter;
|
||||||
|
|
||||||
int scheme_startup_use_jit = 1;
|
int scheme_startup_use_jit = 1;
|
||||||
void scheme_set_startup_use_jit(int v) { scheme_startup_use_jit = v; }
|
void scheme_set_startup_use_jit(int v) { scheme_startup_use_jit = v; }
|
||||||
|
|
|
@ -8422,7 +8422,7 @@ static long ITimer(void)
|
||||||
END_XFORM_SKIP;
|
END_XFORM_SKIP;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void scheme_start_itimer_thread(long usec)
|
static void scheme_start_itimer_thread(long usec)
|
||||||
{
|
{
|
||||||
DWORD id;
|
DWORD id;
|
||||||
|
|
||||||
|
@ -8441,65 +8441,137 @@ void scheme_start_itimer_thread(long usec)
|
||||||
#ifdef USE_PTHREAD_THREAD_TIMER
|
#ifdef USE_PTHREAD_THREAD_TIMER
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
typedef struct ITimer_Data {
|
||||||
|
int itimer;
|
||||||
|
int state;
|
||||||
|
pthread_t thread;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t cond;
|
||||||
|
int delay;
|
||||||
|
volatile int * fuel_counter_ptr;
|
||||||
|
volatile unsigned long * jit_stack_boundary_ptr;
|
||||||
|
} ITimer_Data;
|
||||||
|
|
||||||
static int itimer = 0, itimer_continue = 0;
|
static THREAD_LOCAL ITimer_Data itimerdata;
|
||||||
static pthread_mutex_t itimer_mutex;
|
|
||||||
static pthread_cond_t itimer_cond;
|
|
||||||
static volatile long itimer_delay;
|
|
||||||
|
|
||||||
#ifdef MZ_XFORM
|
#ifdef MZ_XFORM
|
||||||
START_XFORM_SKIP;
|
START_XFORM_SKIP;
|
||||||
#endif
|
#endif
|
||||||
static void *run_itimer(void *p)
|
|
||||||
{
|
|
||||||
while (1) {
|
|
||||||
usleep(itimer_delay);
|
|
||||||
scheme_fuel_counter = 0;
|
|
||||||
scheme_jit_stack_boundary = (unsigned long)-1;
|
|
||||||
|
|
||||||
pthread_mutex_lock(&itimer_mutex);
|
static void *green_thread_timer(void *data)
|
||||||
if (itimer_continue) {
|
{
|
||||||
itimer_continue = 0;
|
ITimer_Data *itimer_data;
|
||||||
|
itimer_data = (ITimer_Data *)data;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
usleep(itimer_data->delay);
|
||||||
|
*(itimer_data->fuel_counter_ptr) = 0;
|
||||||
|
*(itimer_data->jit_stack_boundary_ptr) = (unsigned long)-1;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&itimer_data->mutex);
|
||||||
|
if (itimer_data->state) {
|
||||||
|
itimer_data->state = 0;
|
||||||
} else {
|
} else {
|
||||||
itimer_continue = -1;
|
itimer_data->state = -1;
|
||||||
pthread_cond_wait(&itimer_cond, &itimer_mutex);
|
pthread_cond_wait(&itimer_data->cond, &itimer_data->mutex);
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&itimer_mutex);
|
pthread_mutex_unlock(&itimer_data->mutex);
|
||||||
}
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MZ_XFORM
|
#ifdef MZ_XFORM
|
||||||
END_XFORM_SKIP;
|
END_XFORM_SKIP;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void scheme_start_itimer_thread(long usec)
|
static void start_green_thread_timer(long usec) {
|
||||||
{
|
itimerdata.delay = usec;
|
||||||
itimer_delay = usec;
|
itimerdata.fuel_counter_ptr = &scheme_fuel_counter;
|
||||||
|
itimerdata.jit_stack_boundary_ptr = &scheme_jit_stack_boundary;
|
||||||
|
pthread_mutex_init(&itimerdata.mutex, NULL);
|
||||||
|
pthread_cond_init(&itimerdata.cond, NULL);
|
||||||
|
pthread_create(&itimerdata.thread, NULL, green_thread_timer, &itimerdata);
|
||||||
|
itimerdata.itimer = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (!itimer) {
|
static void kickoff_green_thread_timer(long usec) {
|
||||||
pthread_t t;
|
pthread_mutex_lock(&itimerdata.mutex);
|
||||||
pthread_mutex_init(&itimer_mutex, NULL);
|
itimerdata.delay = usec;
|
||||||
pthread_cond_init(&itimer_cond, NULL);
|
if (!itimerdata.state) {
|
||||||
pthread_create(&t, NULL, run_itimer, NULL);
|
|
||||||
itimer = 1;
|
|
||||||
} else {
|
|
||||||
pthread_mutex_lock(&itimer_mutex);
|
|
||||||
if (!itimer_continue) {
|
|
||||||
/* itimer thread is currently running working */
|
/* itimer thread is currently running working */
|
||||||
itimer_continue = 1;
|
itimerdata.state = 1;
|
||||||
} else if (itimer_continue < 0) {
|
} else if (itimerdata.state < 0) {
|
||||||
/* itimer thread is waiting on cond */
|
/* itimer thread is waiting on cond */
|
||||||
itimer_continue = 0;
|
itimerdata.state = 0;
|
||||||
pthread_cond_signal(&itimer_cond);
|
pthread_cond_signal(&itimerdata.cond);
|
||||||
} else {
|
} else {
|
||||||
/* itimer thread is working, and we've already
|
/* itimer thread is working, and we've already
|
||||||
asked it to continue */
|
asked it to continue */
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&itimer_mutex);
|
pthread_mutex_unlock(&itimerdata.mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void scheme_start_itimer_thread(long usec)
|
||||||
|
{
|
||||||
|
if (!itimerdata.itimer) {
|
||||||
|
start_green_thread_timer(usec);
|
||||||
|
} else {
|
||||||
|
kickoff_green_thread_timer(usec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_ITIMER
|
||||||
|
|
||||||
|
#ifdef MZ_XFORM
|
||||||
|
START_XFORM_SKIP;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void itimer_expired(int ignored)
|
||||||
|
{
|
||||||
|
scheme_fuel_counter = 0;
|
||||||
|
scheme_jit_stack_boundary = (unsigned long)-1;
|
||||||
|
# ifdef SIGSET_NEEDS_REINSTALL
|
||||||
|
MZ_SIGSET(SIGPROF, itimer_expired);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void kickoff_itimer(long usec) {
|
||||||
|
struct itimerval t;
|
||||||
|
struct itimerval old;
|
||||||
|
static int itimer_handler_installed = 0;
|
||||||
|
|
||||||
|
if (!itimer_handler_installed) {
|
||||||
|
itimer_handler_installed = 1;
|
||||||
|
MZ_SIGSET(SIGPROF, itimer_expired);
|
||||||
|
}
|
||||||
|
|
||||||
|
t.it_value.tv_sec = 0;
|
||||||
|
t.it_value.tv_usec = usec;
|
||||||
|
t.it_interval.tv_sec = 0;
|
||||||
|
t.it_interval.tv_usec = 0;
|
||||||
|
|
||||||
|
setitimer(ITIMER_PROF, &t, &old);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MZ_XFORM
|
||||||
|
END_XFORM_SKIP;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void scheme_kickoff_green_thread_time_slice_timer(long usec) {
|
||||||
|
#ifdef USE_ITIMER
|
||||||
|
kickoff_itimer(usec);
|
||||||
|
#elif defined(USE_WIN32_THREAD_TIMER)
|
||||||
|
scheme_start_itimer_thread(usec);
|
||||||
|
#elif defined(USE_PTHREAD_THREAD_TIMER)
|
||||||
|
scheme_start_itimer_thread(usec);
|
||||||
|
#else
|
||||||
|
#error scheme_start_green_thread_time_slice_timer NOT IMPLEMENTED
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef OS_X
|
#ifdef OS_X
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ MZ_EXTERN Scheme_Object *scheme_current_break_cell();
|
||||||
# ifndef MZ_USE_PLACES
|
# ifndef MZ_USE_PLACES
|
||||||
MZ_EXTERN THREAD_LOCAL Scheme_Thread *scheme_current_thread;
|
MZ_EXTERN THREAD_LOCAL Scheme_Thread *scheme_current_thread;
|
||||||
# endif
|
# endif
|
||||||
MZ_EXTERN volatile int scheme_fuel_counter;
|
MZ_EXTERN THREAD_LOCAL volatile int scheme_fuel_counter;
|
||||||
#else
|
#else
|
||||||
MZ_EXTERN Scheme_Thread **scheme_current_thread_ptr;
|
MZ_EXTERN Scheme_Thread **scheme_current_thread_ptr;
|
||||||
MZ_EXTERN volatile int *scheme_fuel_counter_ptr;
|
MZ_EXTERN volatile int *scheme_fuel_counter_ptr;
|
||||||
|
|
|
@ -57,7 +57,7 @@ Scheme_Object *(*scheme_current_break_cell)();
|
||||||
# ifndef MZ_USE_PLACES
|
# ifndef MZ_USE_PLACES
|
||||||
Scheme_Thread *scheme_current_thread;
|
Scheme_Thread *scheme_current_thread;
|
||||||
# endif
|
# endif
|
||||||
volatile int scheme_fuel_counter;
|
THREAD_LOCAL volatile int scheme_fuel_counter;
|
||||||
#else
|
#else
|
||||||
Scheme_Thread **scheme_current_thread_ptr;
|
Scheme_Thread **scheme_current_thread_ptr;
|
||||||
volatile int *scheme_fuel_counter_ptr;
|
volatile int *scheme_fuel_counter_ptr;
|
||||||
|
|
|
@ -365,7 +365,7 @@ extern THREAD_LOCAL MZ_MARK_POS_TYPE scheme_current_cont_mark_pos;
|
||||||
# define MZ_CONT_MARK_POS (scheme_current_thread->cont_mark_pos)
|
# define MZ_CONT_MARK_POS (scheme_current_thread->cont_mark_pos)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern volatile int scheme_fuel_counter;
|
extern THREAD_LOCAL volatile int scheme_fuel_counter;
|
||||||
|
|
||||||
extern THREAD_LOCAL Scheme_Thread *scheme_main_thread;
|
extern THREAD_LOCAL Scheme_Thread *scheme_main_thread;
|
||||||
|
|
||||||
|
@ -419,9 +419,8 @@ void scheme_forget_subthread(struct Scheme_Thread_Memory *);
|
||||||
void scheme_suspend_remembered_threads(void);
|
void scheme_suspend_remembered_threads(void);
|
||||||
void scheme_resume_remembered_threads(void);
|
void scheme_resume_remembered_threads(void);
|
||||||
#endif
|
#endif
|
||||||
#if defined(USE_WIN32_THREAD_TIMER) || defined(USE_PTHREAD_THREAD_TIMER)
|
|
||||||
void scheme_start_itimer_thread(long usec);
|
void scheme_kickoff_green_thread_time_slice_timer(long usec);
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef UNIX_PROCESSES
|
#ifdef UNIX_PROCESSES
|
||||||
void scheme_block_child_signals(int block);
|
void scheme_block_child_signals(int block);
|
||||||
|
|
|
@ -54,11 +54,6 @@
|
||||||
# include <be/net/socket.h>
|
# include <be/net/socket.h>
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_ITIMER
|
|
||||||
# include <sys/types.h>
|
|
||||||
# include <sys/time.h>
|
|
||||||
# include <signal.h>
|
|
||||||
#endif
|
|
||||||
#ifdef USE_WINSOCK_TCP
|
#ifdef USE_WINSOCK_TCP
|
||||||
# ifdef USE_TCP
|
# ifdef USE_TCP
|
||||||
# include <winsock.h>
|
# include <winsock.h>
|
||||||
|
@ -3636,28 +3631,6 @@ void scheme_out_of_fuel(void)
|
||||||
scheme_current_thread->ran_some = 1;
|
scheme_current_thread->ran_some = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_ITIMER
|
|
||||||
static int itimer_handler_installed = 0;
|
|
||||||
|
|
||||||
#ifdef MZ_XFORM
|
|
||||||
START_XFORM_SKIP;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void timer_expired(int ignored)
|
|
||||||
{
|
|
||||||
scheme_fuel_counter = 0;
|
|
||||||
scheme_jit_stack_boundary = (unsigned long)-1;
|
|
||||||
# ifdef SIGSET_NEEDS_REINSTALL
|
|
||||||
MZ_SIGSET(SIGPROF, timer_expired);
|
|
||||||
# endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MZ_XFORM
|
|
||||||
END_XFORM_SKIP;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void init_schedule_info(Scheme_Schedule_Info *sinfo, Scheme_Thread *false_pos_ok,
|
static void init_schedule_info(Scheme_Schedule_Info *sinfo, Scheme_Thread *false_pos_ok,
|
||||||
double sleep_end)
|
double sleep_end)
|
||||||
{
|
{
|
||||||
|
@ -4251,26 +4224,7 @@ void scheme_thread_block(float sleep_time)
|
||||||
scheme_fuel_counter = p->engine_weight;
|
scheme_fuel_counter = p->engine_weight;
|
||||||
scheme_jit_stack_boundary = scheme_stack_boundary;
|
scheme_jit_stack_boundary = scheme_stack_boundary;
|
||||||
|
|
||||||
#ifdef USE_ITIMER
|
scheme_kickoff_green_thread_time_slice_timer(MZ_THREAD_QUANTUM_USEC);
|
||||||
{
|
|
||||||
struct itimerval t, old;
|
|
||||||
|
|
||||||
if (!itimer_handler_installed) {
|
|
||||||
itimer_handler_installed = 1;
|
|
||||||
MZ_SIGSET(SIGPROF, timer_expired);
|
|
||||||
}
|
|
||||||
|
|
||||||
t.it_value.tv_sec = 0;
|
|
||||||
t.it_value.tv_usec = MZ_THREAD_QUANTUM_USEC;
|
|
||||||
t.it_interval.tv_sec = 0;
|
|
||||||
t.it_interval.tv_usec = 0;
|
|
||||||
|
|
||||||
setitimer(ITIMER_PROF, &t, &old);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if defined(USE_WIN32_THREAD_TIMER) || defined(USE_PTHREAD_THREAD_TIMER)
|
|
||||||
scheme_start_itimer_thread(MZ_THREAD_QUANTUM_USEC);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check scheduled_kills early and often. */
|
/* Check scheduled_kills early and often. */
|
||||||
check_scheduled_kills();
|
check_scheduled_kills();
|
||||||
|
|
|
@ -36,4 +36,9 @@
|
||||||
|
|
||||||
#define USE_GETRUSAGE
|
#define USE_GETRUSAGE
|
||||||
|
|
||||||
#define USE_ITIMER
|
#if defined MZ_USE_PLACES
|
||||||
|
# undef USE_ITIMER
|
||||||
|
# define USE_PTHREAD_THREAD_TIMER
|
||||||
|
#else
|
||||||
|
# define USE_ITIMER
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user