diff --git a/src/mzscheme/include/scheme.h b/src/mzscheme/include/scheme.h index 4e5c881b68..8e406c1121 100644 --- a/src/mzscheme/include/scheme.h +++ b/src/mzscheme/include/scheme.h @@ -1491,7 +1491,7 @@ typedef void (*Scheme_Invoke_Proc)(Scheme_Env *env, long phase_shift, # define scheme_fuel_counter (*scheme_fuel_counter_ptr) # endif #else -MZ_EXTERN volatile int scheme_fuel_counter; +MZ_EXTERN THREAD_LOCAL volatile int scheme_fuel_counter; #endif #ifdef FUEL_AUTODECEREMENTS diff --git a/src/mzscheme/src/eval.c b/src/mzscheme/src/eval.c index 2b54ef1e19..b73df666e8 100644 --- a/src/mzscheme/src/eval.c +++ b/src/mzscheme/src/eval.c @@ -147,7 +147,7 @@ #define EMBEDDED_DEFINES_START_ANYWHERE 0 /* globals */ -volatile int scheme_fuel_counter; +THREAD_LOCAL volatile int scheme_fuel_counter; int scheme_startup_use_jit = 1; void scheme_set_startup_use_jit(int v) { scheme_startup_use_jit = v; } diff --git a/src/mzscheme/src/port.c b/src/mzscheme/src/port.c index 83cd58d4ce..b63e5c4b34 100644 --- a/src/mzscheme/src/port.c +++ b/src/mzscheme/src/port.c @@ -8422,7 +8422,7 @@ static long ITimer(void) END_XFORM_SKIP; #endif -void scheme_start_itimer_thread(long usec) +static void scheme_start_itimer_thread(long usec) { DWORD id; @@ -8441,65 +8441,137 @@ void scheme_start_itimer_thread(long usec) #ifdef USE_PTHREAD_THREAD_TIMER #include +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 pthread_mutex_t itimer_mutex; -static pthread_cond_t itimer_cond; -static volatile long itimer_delay; +static THREAD_LOCAL ITimer_Data itimerdata; #ifdef MZ_XFORM START_XFORM_SKIP; #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); - if (itimer_continue) { - itimer_continue = 0; +static void *green_thread_timer(void *data) +{ + 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 { - itimer_continue = -1; - pthread_cond_wait(&itimer_cond, &itimer_mutex); + itimer_data->state = -1; + 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 END_XFORM_SKIP; #endif -void scheme_start_itimer_thread(long usec) -{ - itimer_delay = usec; +static void start_green_thread_timer(long usec) { + itimerdata.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) { - pthread_t t; - pthread_mutex_init(&itimer_mutex, NULL); - pthread_cond_init(&itimer_cond, NULL); - pthread_create(&t, NULL, run_itimer, NULL); - itimer = 1; - } else { - pthread_mutex_lock(&itimer_mutex); - if (!itimer_continue) { +static void kickoff_green_thread_timer(long usec) { + pthread_mutex_lock(&itimerdata.mutex); + itimerdata.delay = usec; + if (!itimerdata.state) { /* itimer thread is currently running working */ - itimer_continue = 1; - } else if (itimer_continue < 0) { + itimerdata.state = 1; + } else if (itimerdata.state < 0) { /* itimer thread is waiting on cond */ - itimer_continue = 0; - pthread_cond_signal(&itimer_cond); + itimerdata.state = 0; + pthread_cond_signal(&itimerdata.cond); } else { /* itimer thread is working, and we've already 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 +#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 diff --git a/src/mzscheme/src/schemef.h b/src/mzscheme/src/schemef.h index 1f37b63ddf..36cdcae970 100644 --- a/src/mzscheme/src/schemef.h +++ b/src/mzscheme/src/schemef.h @@ -71,7 +71,7 @@ MZ_EXTERN Scheme_Object *scheme_current_break_cell(); # ifndef MZ_USE_PLACES MZ_EXTERN THREAD_LOCAL Scheme_Thread *scheme_current_thread; # endif -MZ_EXTERN volatile int scheme_fuel_counter; +MZ_EXTERN THREAD_LOCAL volatile int scheme_fuel_counter; #else MZ_EXTERN Scheme_Thread **scheme_current_thread_ptr; MZ_EXTERN volatile int *scheme_fuel_counter_ptr; diff --git a/src/mzscheme/src/schemex.h b/src/mzscheme/src/schemex.h index 9d564c9491..6fef165afb 100644 --- a/src/mzscheme/src/schemex.h +++ b/src/mzscheme/src/schemex.h @@ -57,7 +57,7 @@ Scheme_Object *(*scheme_current_break_cell)(); # ifndef MZ_USE_PLACES Scheme_Thread *scheme_current_thread; # endif -volatile int scheme_fuel_counter; +THREAD_LOCAL volatile int scheme_fuel_counter; #else Scheme_Thread **scheme_current_thread_ptr; volatile int *scheme_fuel_counter_ptr; diff --git a/src/mzscheme/src/schpriv.h b/src/mzscheme/src/schpriv.h index 227fbe7b73..6410ac4851 100644 --- a/src/mzscheme/src/schpriv.h +++ b/src/mzscheme/src/schpriv.h @@ -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) #endif -extern volatile int scheme_fuel_counter; +extern THREAD_LOCAL volatile int scheme_fuel_counter; 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_resume_remembered_threads(void); #endif -#if defined(USE_WIN32_THREAD_TIMER) || defined(USE_PTHREAD_THREAD_TIMER) -void scheme_start_itimer_thread(long usec); -#endif + +void scheme_kickoff_green_thread_time_slice_timer(long usec); #ifdef UNIX_PROCESSES void scheme_block_child_signals(int block); diff --git a/src/mzscheme/src/thread.c b/src/mzscheme/src/thread.c index 72b4258534..2654994753 100644 --- a/src/mzscheme/src/thread.c +++ b/src/mzscheme/src/thread.c @@ -54,11 +54,6 @@ # include # endif #endif -#ifdef USE_ITIMER -# include -# include -# include -#endif #ifdef USE_WINSOCK_TCP # ifdef USE_TCP # include @@ -3636,28 +3631,6 @@ void scheme_out_of_fuel(void) 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, double sleep_end) { @@ -4251,26 +4224,7 @@ void scheme_thread_block(float sleep_time) scheme_fuel_counter = p->engine_weight; scheme_jit_stack_boundary = scheme_stack_boundary; -#ifdef USE_ITIMER - { - 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 + scheme_kickoff_green_thread_time_slice_timer(MZ_THREAD_QUANTUM_USEC); /* Check scheduled_kills early and often. */ check_scheduled_kills(); diff --git a/src/mzscheme/uconfig.h b/src/mzscheme/uconfig.h index 12610b9bf0..463f2ad6f8 100644 --- a/src/mzscheme/uconfig.h +++ b/src/mzscheme/uconfig.h @@ -36,4 +36,9 @@ #define USE_GETRUSAGE -#define USE_ITIMER +#if defined MZ_USE_PLACES +# undef USE_ITIMER +# define USE_PTHREAD_THREAD_TIMER +#else +# define USE_ITIMER +#endif