more on thread-local allocation

svn: r16879
This commit is contained in:
Matthew Flatt 2009-11-18 20:07:58 +00:00
parent bdca9c1e8f
commit f921cf62cc
7 changed files with 90 additions and 51 deletions

View File

@ -279,25 +279,16 @@ void exception_thread(void *shared_thread_state)
}
}
/* this initializes the subsystem (sets the exception port, starts the
exception handling thread, etc) */
static void macosx_init_exception_handler()
void GC_attach_current_thread_exceptions_to_handler()
{
mach_port_t thread_self, exc_port_s;
mach_msg_type_name_t type;
kern_return_t retval;
/* get ids for ourself */
if(!task_self) task_self = mach_task_self();
thread_self = mach_thread_self();
if (!task_self) return;
/* allocate the port we're going to get exceptions on */
retval = mach_port_allocate(task_self, MACH_PORT_RIGHT_RECEIVE, &exc_port);
if(retval != KERN_SUCCESS) {
GCPRINT(GCOUTF, "Couldn't allocate exception port: %s\n",
mach_error_string(retval));
abort();
}
/* get ids for ourself */
thread_self = mach_thread_self();
/* extract out the send rights for that port, which the OS needs */
retval = mach_port_extract_right(task_self, exc_port, MACH_MSG_TYPE_MAKE_SEND,
@ -315,6 +306,25 @@ static void macosx_init_exception_handler()
GCPRINT(GCOUTF, "Couldn't set exception ports: %s\n", mach_error_string(retval));
abort();
}
}
/* this initializes the subsystem (sets the exception port, starts the
exception handling thread, etc) */
static void macosx_init_exception_handler()
{
kern_return_t retval;
if(!task_self) task_self = mach_task_self();
/* allocate the port we're going to get exceptions on */
retval = mach_port_allocate(task_self, MACH_PORT_RIGHT_RECEIVE, &exc_port);
if(retval != KERN_SUCCESS) {
GCPRINT(GCOUTF, "Couldn't allocate exception port: %s\n",
mach_error_string(retval));
abort();
}
GC_attach_current_thread_exceptions_to_handler();
#ifdef PPC_HAND_ROLLED_THREAD
/* Old hand-rolled thread creation. */

View File

@ -181,7 +181,8 @@ typedef struct Thread_Local_Variables {
int num_running_threads_;
int swap_no_setjmp_;
int thread_swap_count_;
int did_gc_count_;
int scheme_did_gc_count_;
int worker_gc_counter_;
struct Scheme_Object **scheme_current_runstack_start_;
struct Scheme_Object **scheme_current_runstack_;
MZ_MARK_STACK_TYPE scheme_current_cont_mark_stack_;
@ -344,7 +345,8 @@ XFORM_GC_VARIABLE_STACK_THROUGH_THREAD_LOCAL;
#define num_running_threads XOA (scheme_get_thread_local_variables()->num_running_threads_)
#define swap_no_setjmp XOA (scheme_get_thread_local_variables()->swap_no_setjmp_)
#define thread_swap_count XOA (scheme_get_thread_local_variables()->thread_swap_count_)
#define did_gc_count XOA (scheme_get_thread_local_variables()->did_gc_count_)
#define scheme_did_gc_count XOA (scheme_get_thread_local_variables()->scheme_did_gc_count_)
#define worker_gc_counter XOA (scheme_get_thread_local_variables()->worker_gc_counter_)
#define scheme_current_runstack_start XOA (scheme_get_thread_local_variables()->scheme_current_runstack_start_)
#define scheme_current_runstack XOA (scheme_get_thread_local_variables()->scheme_current_runstack_)
#define scheme_current_cont_mark_stack XOA (scheme_get_thread_local_variables()->scheme_current_cont_mark_stack_)

View File

@ -75,10 +75,12 @@ static int gc_not_ok;
THREAD_LOCAL_DECL(extern unsigned long GC_gen0_alloc_page_ptr);
#endif
future_t **g_current_ft;
Scheme_Object ***g_scheme_current_runstack;
Scheme_Object ***g_scheme_current_runstack_start;
void **g_jit_future_storage;
static future_t **g_current_ft;
static Scheme_Object ***g_scheme_current_runstack;
static Scheme_Object ***g_scheme_current_runstack_start;
static void **g_jit_future_storage;
static int *gc_counter_ptr;
THREAD_LOCAL_DECL(static int worker_gc_counter);
static void register_traversers(void);
extern void scheme_on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Scheme_Object **argv);
@ -307,6 +309,7 @@ void futures_init(void)
pthread_attr_setstacksize(&attr, INITIAL_C_STACK_SIZE);
for (i = 0; i < THREAD_POOL_SIZE; i++)
{
gc_counter_ptr = &scheme_did_gc_count;
pthread_create(&threadid, &attr, worker_thread_future_loop, &i);
sema_wait(&ready_sema);
@ -326,6 +329,12 @@ static void start_gc_not_ok()
pthread_mutex_lock(&gc_ok_m);
gc_not_ok++;
pthread_mutex_unlock(&gc_ok_m);
#ifdef MZ_PRECISE_GC
if (worker_gc_counter != *gc_counter_ptr) {
GC_gen0_alloc_page_ptr = 0; /* forces future to ask for memory */
worker_gc_counter = *gc_counter_ptr;
}
#endif
}
static void end_gc_not_ok()
@ -581,7 +590,6 @@ Scheme_Object *touch(int argc, Scheme_Object *argv[])
return retval;
}
//Entry point for a worker thread allocated for
//executing futures. This function will never terminate
//(until the process dies).
@ -616,10 +624,6 @@ void *worker_thread_future_loop(void *arg)
g_fuel_pointers[id] = &scheme_fuel_counter;
g_stack_boundary_pointers[id] = &scheme_jit_stack_boundary;
#ifdef MZ_PRECISE_GC
GC_gen0_alloc_page_ptr = 0; /* disables inline allocation */
#endif
g_current_ft = &current_ft;
g_scheme_current_runstack = &scheme_current_runstack;
g_scheme_current_runstack_start = &scheme_current_runstack_start;
@ -744,6 +748,7 @@ int future_do_runtimecall(
future->rt_prim = NULL;
retval = future->rt_prim_retval;
future->rt_prim_retval = NULL;
pthread_mutex_unlock(&g_future_queue_mutex);
return 1;
}
@ -777,27 +782,34 @@ int rtcall_void_void(void (*f)())
}
int rtcall_void_pvoid(void (*f)(), void **retval)
int rtcall_alloc_void_pvoid(void (*f)(), void **retval)
{
START_XFORM_SKIP;
future_t *future;
prim_data_t data;
memset(&data, 0, sizeof(prim_data_t));
if (!IS_WORKER_THREAD)
{
return 0;
}
data.void_pvoid = f;
data.sigtype = SIG_VOID_PVOID;
while (1) {
memset(&data, 0, sizeof(prim_data_t));
if (!IS_WORKER_THREAD)
{
return 0;
}
future = get_my_future();
future->rt_prim = (void*)f;
future->prim_data = data;
data.alloc_void_pvoid = f;
data.sigtype = SIG_ALLOC_VOID_PVOID;
future_do_runtimecall((void*)f, NULL);
future = get_my_future();
future->rt_prim = (void*)f;
future->prim_data = data;
*retval = future->prim_data.retval;
future_do_runtimecall((void*)f, NULL);
*retval = future->alloc_retval;
future->alloc_retval = NULL;
if (*gc_counter_ptr == future->alloc_retval_counter)
break;
}
return 1;
END_XFORM_SKIP;
@ -840,6 +852,7 @@ int rtcall_obj_int_pobj_obj(
future_do_runtimecall((void*)f, NULL);
*retval = future->prim_data.retval;
future->prim_data.retval = NULL;
return 1;
END_XFORM_SKIP;
@ -880,6 +893,7 @@ int rtcall_int_pobj_obj(
future_do_runtimecall((void*)f, NULL);
*retval = future->prim_data.retval;
future->prim_data.retval = NULL;
return 1;
END_XFORM_SKIP;
@ -962,6 +976,7 @@ int rtcall_int_pobj_obj_obj(
future_do_runtimecall((void*)f, NULL);
*retval = future->prim_data.retval;
future->prim_data.retval = NULL;
return 1;
END_XFORM_SKIP;
@ -995,11 +1010,12 @@ void *invoke_rtcall(future_t *future)
pret = &dummy_ret;
break;
}
case SIG_VOID_PVOID:
case SIG_ALLOC_VOID_PVOID:
{
prim_void_pvoid_t func = pdata->void_pvoid;
prim_alloc_void_pvoid_t func = pdata->alloc_void_pvoid;
ret = func();
pdata->retval = ret;
future->alloc_retval = ret;
future->alloc_retval_counter = scheme_did_gc_count;
break;
}
case SIG_OBJ_INT_POBJ_OBJ:

View File

@ -33,7 +33,7 @@ extern int future_do_runtimecall(void *func, void *retval);
extern void futures_init(void);
typedef void (*prim_void_void_t)(void);
typedef void *(*prim_void_pvoid_t)(void);
typedef void *(*prim_alloc_void_pvoid_t)(void);
typedef Scheme_Object* (*prim_obj_int_pobj_obj_t)(Scheme_Object*, int, Scheme_Object**);
typedef Scheme_Object* (*prim_int_pobj_obj_t)(int, Scheme_Object**);
typedef Scheme_Object* (*prim_int_pobj_obj_obj_t)(int, Scheme_Object**, Scheme_Object*);
@ -43,7 +43,7 @@ typedef struct {
unsigned int sigtype;
prim_void_void_t void_void;
prim_void_pvoid_t void_pvoid;
prim_alloc_void_pvoid_t alloc_void_pvoid;
prim_obj_int_pobj_obj_t obj_int_pobj_obj;
prim_int_pobj_obj_t int_pobj_obj;
prim_int_pobj_obj_obj_t int_pobj_obj_obj;
@ -90,6 +90,8 @@ typedef struct future {
void *rt_prim_retval;
prim_data_t prim_data;
void *alloc_retval;
int alloc_retval_counter;
Scheme_Object *retval;
struct future *prev;
@ -152,7 +154,7 @@ extern void print_ms_and_us(void);
//Signature flags for primitive invocations
//Here the convention is SIG_[arg1type]_[arg2type]..._[return type]
#define SIG_VOID_VOID 1 //void -> void
#define SIG_VOID_PVOID 2 //void -> void*
#define SIG_ALLOC_VOID_PVOID 2 //void -> void*
#define SIG_OBJ_INT_POBJ_OBJ 3 //Scheme_Object* -> int -> Scheme_Object** -> Scheme_Object*
#define SIG_INT_OBJARR_OBJ 4 //int -> Scheme_Object*[] -> Scheme_Object
#define SIG_INT_POBJ_OBJ_OBJ 17 //int -> Scheme_Object** -> Scheme_Object* -> Scheme_Object*
@ -169,7 +171,7 @@ extern void print_ms_and_us(void);
}
extern int rtcall_void_void(void (*f)());
extern int rtcall_void_pvoid(void (*f)(), void **retval);
extern int rtcall_alloc_void_pvoid(void (*f)(), void **retval);
extern int rtcall_obj_int_pobj_obj(
Scheme_Object* (*f)(Scheme_Object*, int, Scheme_Object**),
Scheme_Object *a,
@ -195,7 +197,7 @@ extern int rtcall_int_pobj_obj(
#define LOG_THISCALL LOG(__FUNCTION__)
#define LOG_RTCALL_VOID_VOID(f) LOG("(function=%p)", f)
#define LOG_RTCALL_VOID_PVOID(f) LOG("(function=%p)", f)
#define LOG_RTCALL_ALLOC_VOID_PVOID(f) LOG("(function=%p)", f)
#define LOG_RTCALL_OBJ_INT_POBJ_OBJ(f,a,b,c) LOG("(function = %p, a=%p, b=%d, c=%p)", f, a, b, c)
#define LOG_RTCALL_OBJ_INT_POBJ_VOID(a,b,c) LOG("(%p, %d, %p)", a, b,c)
#define LOG_RTCALL_INT_OBJARR_OBJ(a,b) LOG("(%d, %p)", a, b)
@ -218,7 +220,7 @@ extern int rtcall_int_pobj_obj(
#define LOG_THISCALL
#define LOG_RTCALL_VOID_VOID(f)
#define LOG_RTCALL_VOID_PVOID(f)
#define LOG_RTCALL_ALLOC_VOID_PVOID(f)
#define LOG_RTCALL_OBJ_INT_POBJ_OBJ(f,a,b,c)
#define LOG_RTCALL_OBJ_INT_POBJ_VOID(a,b,c)
#define LOG_RTCALL_INT_OBJARR_OBJ(a,b)

View File

@ -2256,8 +2256,8 @@ static void *ts_prepare_retry_alloc(void *p, void *p2)
LOG_PRIM_START(&prepare_retry_alloc);
jit_future_storage[0] = p;
jit_future_storage[1] = p2;
if (rtcall_void_pvoid(GC_make_jit_nursery_page,
&ret)) {
if (rtcall_alloc_void_pvoid(GC_make_jit_nursery_page,
&ret)) {
GC_gen0_alloc_page_ptr = ret;
retry_alloc_r1 = jit_future_storage[1];
p = jit_future_storage[0];
@ -2284,6 +2284,7 @@ static void *ts_prepare_retry_alloc(void *p, void *p2)
# define ts_scheme_apply_from_native _scheme_apply_from_native
# define ts_scheme_tail_apply_from_native _scheme_tail_apply_from_native
# define ts_on_demand on_demand
# define ts_prepare_retry_alloc prepare_retry_alloc
#endif
static int generate_direct_prim_tail_call(mz_jit_state *jitter, int num_rands)

View File

@ -220,6 +220,9 @@ void scheme_set_report_out_of_memory(Scheme_Report_Out_Of_Memory_Proc p)
#ifdef OS_X
#include <mach/mach.h>
# ifdef MZ_PRECISE_GC
extern void GC_attach_current_thread_exceptions_to_handler();
# endif
#endif
#ifdef MZ_XFORM
@ -241,6 +244,11 @@ void scheme_init_os_thread()
}
# endif
#endif
#ifdef OS_X
# ifdef MZ_PRECISE_GC
GC_attach_current_thread_exceptions_to_handler();
# endif
#endif
}
#ifdef MZ_XFORM
END_XFORM_SKIP;

View File

@ -160,7 +160,7 @@ volatile int *scheme_fuel_counter_ptr;
THREAD_LOCAL_DECL(static int swap_no_setjmp = 0);
THREAD_LOCAL_DECL(static int thread_swap_count);
THREAD_LOCAL_DECL(static int did_gc_count);
THREAD_LOCAL_DECL(int scheme_did_gc_count);
static int init_load_on_demand = 1;
@ -7390,7 +7390,7 @@ static void get_ready_for_GC()
scheme_current_thread->gmp_tls_data = data;
}
did_gc_count++;
scheme_did_gc_count++;
}
extern int GC_words_allocd;
@ -7575,7 +7575,7 @@ static Scheme_Object *current_stats(int argc, Scheme_Object *argv[])
case 5:
SCHEME_VEC_ELS(v)[4] = scheme_make_integer(thread_swap_count);
case 4:
SCHEME_VEC_ELS(v)[3] = scheme_make_integer(did_gc_count);
SCHEME_VEC_ELS(v)[3] = scheme_make_integer(scheme_did_gc_count);
case 3:
SCHEME_VEC_ELS(v)[2] = scheme_make_integer(gcend);
case 2: