future repairs
svn: r16884
This commit is contained in:
parent
b80c782046
commit
77ae545fe6
|
@ -702,7 +702,6 @@ static void *allocate_medium(const size_t request_size_bytes, const int type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline static mpage *gen0_create_new_nursery_mpage(NewGC *gc, const size_t page_size) {
|
inline static mpage *gen0_create_new_nursery_mpage(NewGC *gc, const size_t page_size) {
|
||||||
mpage *newmpage;
|
mpage *newmpage;
|
||||||
|
|
||||||
|
|
|
@ -102,12 +102,10 @@ THREAD_LOCAL_DECL(static future_t *current_ft);
|
||||||
//Functions
|
//Functions
|
||||||
#ifndef UNIT_TEST
|
#ifndef UNIT_TEST
|
||||||
static void *worker_thread_future_loop(void *arg);
|
static void *worker_thread_future_loop(void *arg);
|
||||||
static void *invoke_rtcall(future_t *future);
|
static void invoke_rtcall(future_t *future);
|
||||||
static future_t *enqueue_future(void);
|
static future_t *enqueue_future(void);
|
||||||
static future_t *get_pending_future(void);
|
static future_t *get_pending_future(void);
|
||||||
static future_t *get_my_future(void);
|
static future_t *get_my_future(void);
|
||||||
static future_t *get_future_by_threadid(pthread_t threadid);
|
|
||||||
static future_t *get_future(int futureid);
|
|
||||||
static future_t *get_last_future(void);
|
static future_t *get_last_future(void);
|
||||||
#else
|
#else
|
||||||
//Garbage stubs for unit testing
|
//Garbage stubs for unit testing
|
||||||
|
@ -263,7 +261,7 @@ void scheme_init_futures(Scheme_Env *env)
|
||||||
1),
|
1),
|
||||||
newenv);
|
newenv);
|
||||||
|
|
||||||
#ifdef INSTRUMENT_PRIMITIVES
|
#ifdef INSTRUMENT_PRIMITIVES
|
||||||
scheme_add_global_constant(
|
scheme_add_global_constant(
|
||||||
"start-primitive-tracking",
|
"start-primitive-tracking",
|
||||||
scheme_make_prim_w_arity(
|
scheme_make_prim_w_arity(
|
||||||
|
@ -281,7 +279,7 @@ void scheme_init_futures(Scheme_Env *env)
|
||||||
0,
|
0,
|
||||||
0),
|
0),
|
||||||
newenv);
|
newenv);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
scheme_finish_primitive_module(newenv);
|
scheme_finish_primitive_module(newenv);
|
||||||
scheme_protect_primitive_provide(newenv, NULL);
|
scheme_protect_primitive_provide(newenv, NULL);
|
||||||
|
@ -300,9 +298,9 @@ void futures_init(void)
|
||||||
g_rt_threadid = pthread_self();
|
g_rt_threadid = pthread_self();
|
||||||
g_signal_handle = scheme_get_signal_handle();
|
g_signal_handle = scheme_get_signal_handle();
|
||||||
|
|
||||||
#ifdef MZ_PRECISE_GC
|
#ifdef MZ_PRECISE_GC
|
||||||
register_traversers();
|
register_traversers();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Create the worker thread pool. These threads will
|
//Create the worker thread pool. These threads will
|
||||||
//'queue up' and wait for futures to become available
|
//'queue up' and wait for futures to become available
|
||||||
|
@ -310,6 +308,10 @@ void futures_init(void)
|
||||||
pthread_attr_setstacksize(&attr, INITIAL_C_STACK_SIZE);
|
pthread_attr_setstacksize(&attr, INITIAL_C_STACK_SIZE);
|
||||||
for (i = 0; i < THREAD_POOL_SIZE; i++)
|
for (i = 0; i < THREAD_POOL_SIZE; i++)
|
||||||
{
|
{
|
||||||
|
/* FIXME: insteda of using global variables, we need to
|
||||||
|
commuincate though some record. Global variables
|
||||||
|
won't work with places, since the relevant values
|
||||||
|
are all place-specific. */
|
||||||
gc_counter_ptr = &scheme_did_gc_count;
|
gc_counter_ptr = &scheme_did_gc_count;
|
||||||
g_shared_GC = GC;
|
g_shared_GC = GC;
|
||||||
pthread_create(&threadid, &attr, worker_thread_future_loop, &i);
|
pthread_create(&threadid, &attr, worker_thread_future_loop, &i);
|
||||||
|
@ -433,10 +435,11 @@ void print_ms_and_us()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Scheme_Object *future(int argc, Scheme_Object *argv[])
|
Scheme_Object *future(int argc, Scheme_Object *argv[])
|
||||||
|
/* Called in runtime thread */
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_FUTURES
|
#ifdef DEBUG_FUTURES
|
||||||
LOG_THISCALL;
|
LOG_THISCALL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int init_runstack_size;
|
int init_runstack_size;
|
||||||
int futureid;
|
int futureid;
|
||||||
|
@ -463,9 +466,9 @@ Scheme_Object *future(int argc, Scheme_Object *argv[])
|
||||||
//init_runstack_size = MZ_RUNSTACK - MZ_RUNSTACK_START;
|
//init_runstack_size = MZ_RUNSTACK - MZ_RUNSTACK_START;
|
||||||
init_runstack_size = 1000;
|
init_runstack_size = 1000;
|
||||||
|
|
||||||
#ifdef DEBUG_FUTURES
|
#ifdef DEBUG_FUTURES
|
||||||
printf("Allocating Scheme stack of %d bytes for future %d.\n", init_runstack_size, futureid);
|
printf("Allocating Scheme stack of %d bytes for future %d.\n", init_runstack_size, futureid);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{
|
{
|
||||||
Scheme_Object **rs_start, **rs;
|
Scheme_Object **rs_start, **rs;
|
||||||
|
@ -500,12 +503,14 @@ Scheme_Object *future(int argc, Scheme_Object *argv[])
|
||||||
|
|
||||||
|
|
||||||
Scheme_Object *num_processors(int argc, Scheme_Object *argv[])
|
Scheme_Object *num_processors(int argc, Scheme_Object *argv[])
|
||||||
|
/* Called in runtime thread */
|
||||||
{
|
{
|
||||||
return scheme_make_integer(THREAD_POOL_SIZE);
|
return scheme_make_integer(THREAD_POOL_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int future_ready(Scheme_Object *obj)
|
int future_ready(Scheme_Object *obj)
|
||||||
|
/* Called in runtime thread by Scheme scheduler */
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
future_t *ft = (future_t*)obj;
|
future_t *ft = (future_t*)obj;
|
||||||
|
@ -521,9 +526,9 @@ int future_ready(Scheme_Object *obj)
|
||||||
|
|
||||||
|
|
||||||
Scheme_Object *touch(int argc, Scheme_Object *argv[])
|
Scheme_Object *touch(int argc, Scheme_Object *argv[])
|
||||||
|
/* Called in runtime thread */
|
||||||
{
|
{
|
||||||
Scheme_Object *retval = NULL;
|
Scheme_Object *retval = NULL;
|
||||||
void *rtcall_retval = NULL;
|
|
||||||
future_t *ft;
|
future_t *ft;
|
||||||
|
|
||||||
if (!SAME_TYPE(SCHEME_TYPE(argv[0]), scheme_future_type))
|
if (!SAME_TYPE(SCHEME_TYPE(argv[0]), scheme_future_type))
|
||||||
|
@ -533,10 +538,10 @@ Scheme_Object *touch(int argc, Scheme_Object *argv[])
|
||||||
|
|
||||||
ft = (future_t*)argv[0];
|
ft = (future_t*)argv[0];
|
||||||
|
|
||||||
#ifdef DEBUG_FUTURES
|
#ifdef DEBUG_FUTURES
|
||||||
LOG("touch (future %d)", futureid);
|
LOG("touch (future %d)", futureid);
|
||||||
dump_state();
|
dump_state();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//Spin waiting for primitive calls or a return value from
|
//Spin waiting for primitive calls or a return value from
|
||||||
//the worker thread
|
//the worker thread
|
||||||
|
@ -576,7 +581,7 @@ Scheme_Object *touch(int argc, Scheme_Object *argv[])
|
||||||
//while the runtime call executes
|
//while the runtime call executes
|
||||||
pthread_mutex_unlock(&g_future_queue_mutex);
|
pthread_mutex_unlock(&g_future_queue_mutex);
|
||||||
LOG("Invoking primitive %p on behalf of future %d...", ft->rt_prim, ft->id);
|
LOG("Invoking primitive %p on behalf of future %d...", ft->rt_prim, ft->id);
|
||||||
rtcall_retval = invoke_rtcall(ft);
|
invoke_rtcall(ft);
|
||||||
LOG("done.\n");
|
LOG("done.\n");
|
||||||
pthread_mutex_lock(&g_future_queue_mutex);
|
pthread_mutex_lock(&g_future_queue_mutex);
|
||||||
|
|
||||||
|
@ -602,6 +607,8 @@ Scheme_Object *touch(int argc, Scheme_Object *argv[])
|
||||||
//executing futures. This function will never terminate
|
//executing futures. This function will never terminate
|
||||||
//(until the process dies).
|
//(until the process dies).
|
||||||
void *worker_thread_future_loop(void *arg)
|
void *worker_thread_future_loop(void *arg)
|
||||||
|
/* Called in future thread; runtime thread is blocked until ready_sema
|
||||||
|
is signaled. */
|
||||||
{
|
{
|
||||||
START_XFORM_SKIP;
|
START_XFORM_SKIP;
|
||||||
Scheme_Object *v;
|
Scheme_Object *v;
|
||||||
|
@ -679,9 +686,13 @@ void *worker_thread_future_loop(void *arg)
|
||||||
//From this thread's perspective, this call will never return
|
//From this thread's perspective, this call will never return
|
||||||
//until all the work to be done in the future has been completed,
|
//until all the work to be done in the future has been completed,
|
||||||
//including runtime calls.
|
//including runtime calls.
|
||||||
|
//If jitcode asks the runrtime thread to do work, then
|
||||||
|
//a GC can occur.
|
||||||
LOG("Running JIT code at %p...\n", ft->code);
|
LOG("Running JIT code at %p...\n", ft->code);
|
||||||
v = jitcode(ft->orig_lambda, 0, NULL);
|
v = jitcode(ft->orig_lambda, 0, NULL);
|
||||||
LOG("Finished running JIT code at %p.\n", ft->code);
|
LOG("Finished running JIT code at %p.\n", ft->code);
|
||||||
|
|
||||||
|
// Get future again, since a GC may have occurred
|
||||||
ft = current_ft;
|
ft = current_ft;
|
||||||
|
|
||||||
//Set the return val in the descriptor
|
//Set the return val in the descriptor
|
||||||
|
@ -715,6 +726,7 @@ int future_do_runtimecall(
|
||||||
//int sigtype,
|
//int sigtype,
|
||||||
//void *args,
|
//void *args,
|
||||||
void *retval)
|
void *retval)
|
||||||
|
/* Called in future thread */
|
||||||
{
|
{
|
||||||
START_XFORM_SKIP;
|
START_XFORM_SKIP;
|
||||||
future_t *future;
|
future_t *future;
|
||||||
|
@ -771,22 +783,23 @@ int future_do_runtimecall(
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
/* Functions for primitive invocation */
|
/* Functions for primitive invocation */
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
int rtcall_void_void(void (*f)())
|
int rtcall_void_void_3args(void (*f)())
|
||||||
|
/* Called in future thread */
|
||||||
{
|
{
|
||||||
START_XFORM_SKIP;
|
START_XFORM_SKIP;
|
||||||
future_t *future;
|
future_t *future;
|
||||||
prim_data_t data;
|
prim_data_t data;
|
||||||
memset(&data, 0, sizeof(prim_data_t));
|
|
||||||
if (!IS_WORKER_THREAD)
|
if (!IS_WORKER_THREAD)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.void_void = f;
|
memset(&data, 0, sizeof(prim_data_t));
|
||||||
data.sigtype = SIG_VOID_VOID;
|
data.void_void_3args = f;
|
||||||
|
data.sigtype = SIG_VOID_VOID_3ARGS;
|
||||||
|
|
||||||
future = current_ft;
|
future = current_ft;
|
||||||
future->rt_prim = (void*)f;
|
|
||||||
future->prim_data = data;
|
future->prim_data = data;
|
||||||
|
|
||||||
future_do_runtimecall((void*)f, NULL);
|
future_do_runtimecall((void*)f, NULL);
|
||||||
|
@ -798,23 +811,24 @@ int rtcall_void_void(void (*f)())
|
||||||
|
|
||||||
|
|
||||||
int rtcall_alloc_void_pvoid(void (*f)(), void **retval)
|
int rtcall_alloc_void_pvoid(void (*f)(), void **retval)
|
||||||
|
/* Called in future thread */
|
||||||
{
|
{
|
||||||
START_XFORM_SKIP;
|
START_XFORM_SKIP;
|
||||||
future_t *future;
|
future_t *future;
|
||||||
prim_data_t data;
|
prim_data_t data;
|
||||||
|
|
||||||
while (1) {
|
|
||||||
memset(&data, 0, sizeof(prim_data_t));
|
|
||||||
if (!IS_WORKER_THREAD)
|
if (!IS_WORKER_THREAD)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
memset(&data, 0, sizeof(prim_data_t));
|
||||||
|
|
||||||
data.alloc_void_pvoid = f;
|
data.alloc_void_pvoid = f;
|
||||||
data.sigtype = SIG_ALLOC_VOID_PVOID;
|
data.sigtype = SIG_ALLOC_VOID_PVOID;
|
||||||
|
|
||||||
future = current_ft;
|
future = current_ft;
|
||||||
future->rt_prim = (void*)f;
|
|
||||||
future->prim_data = data;
|
future->prim_data = data;
|
||||||
|
|
||||||
future_do_runtimecall((void*)f, NULL);
|
future_do_runtimecall((void*)f, NULL);
|
||||||
|
@ -838,23 +852,25 @@ int rtcall_obj_int_pobj_obj(
|
||||||
int argc,
|
int argc,
|
||||||
Scheme_Object **argv,
|
Scheme_Object **argv,
|
||||||
Scheme_Object **retval)
|
Scheme_Object **retval)
|
||||||
|
/* Called in future thread */
|
||||||
{
|
{
|
||||||
START_XFORM_SKIP;
|
START_XFORM_SKIP;
|
||||||
future_t *future;
|
future_t *future;
|
||||||
prim_data_t data;
|
prim_data_t data;
|
||||||
memset(&data, 0, sizeof(prim_data_t));
|
|
||||||
if (!IS_WORKER_THREAD)
|
if (!IS_WORKER_THREAD)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_FUTURES
|
memset(&data, 0, sizeof(prim_data_t));
|
||||||
|
|
||||||
|
#ifdef DEBUG_FUTURES
|
||||||
printf("scheme_fuel_counter = %d\n", scheme_fuel_counter);
|
printf("scheme_fuel_counter = %d\n", scheme_fuel_counter);
|
||||||
printf("scheme_jit_stack_boundary = %p\n", (void*)scheme_jit_stack_boundary);
|
printf("scheme_jit_stack_boundary = %p\n", (void*)scheme_jit_stack_boundary);
|
||||||
printf("scheme_current_runstack = %p\n", scheme_current_runstack);
|
printf("scheme_current_runstack = %p\n", scheme_current_runstack);
|
||||||
printf("scheme_current_runstack_start = %p\n", scheme_current_runstack_start);
|
printf("scheme_current_runstack_start = %p\n", scheme_current_runstack_start);
|
||||||
printf("stack address = %p\n", &future);
|
printf("stack address = %p\n", &future);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
data.obj_int_pobj_obj = f;
|
data.obj_int_pobj_obj = f;
|
||||||
data.p = rator;
|
data.p = rator;
|
||||||
|
@ -863,7 +879,6 @@ int rtcall_obj_int_pobj_obj(
|
||||||
data.sigtype = SIG_OBJ_INT_POBJ_OBJ;
|
data.sigtype = SIG_OBJ_INT_POBJ_OBJ;
|
||||||
|
|
||||||
future = current_ft;
|
future = current_ft;
|
||||||
future->rt_prim = (void*)f;
|
|
||||||
future->prim_data = data;
|
future->prim_data = data;
|
||||||
|
|
||||||
future_do_runtimecall((void*)f, NULL);
|
future_do_runtimecall((void*)f, NULL);
|
||||||
|
@ -881,23 +896,25 @@ int rtcall_int_pobj_obj(
|
||||||
int argc,
|
int argc,
|
||||||
Scheme_Object **argv,
|
Scheme_Object **argv,
|
||||||
Scheme_Object **retval)
|
Scheme_Object **retval)
|
||||||
|
/* Called in future thread */
|
||||||
{
|
{
|
||||||
START_XFORM_SKIP;
|
START_XFORM_SKIP;
|
||||||
future_t *future;
|
future_t *future;
|
||||||
prim_data_t data;
|
prim_data_t data;
|
||||||
memset(&data, 0, sizeof(prim_data_t));
|
|
||||||
if (!IS_WORKER_THREAD)
|
if (!IS_WORKER_THREAD)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_FUTURES
|
memset(&data, 0, sizeof(prim_data_t));
|
||||||
|
|
||||||
|
#ifdef DEBUG_FUTURES
|
||||||
printf("scheme_fuel_counter = %d\n", scheme_fuel_counter);
|
printf("scheme_fuel_counter = %d\n", scheme_fuel_counter);
|
||||||
printf("scheme_jit_stack_boundary = %p\n", (void*)scheme_jit_stack_boundary);
|
printf("scheme_jit_stack_boundary = %p\n", (void*)scheme_jit_stack_boundary);
|
||||||
printf("scheme_current_runstack = %p\n", scheme_current_runstack);
|
printf("scheme_current_runstack = %p\n", scheme_current_runstack);
|
||||||
printf("scheme_current_runstack_start = %p\n", scheme_current_runstack_start);
|
printf("scheme_current_runstack_start = %p\n", scheme_current_runstack_start);
|
||||||
printf("stack address = %p\n", &future);
|
printf("stack address = %p\n", &future);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
data.int_pobj_obj = f;
|
data.int_pobj_obj = f;
|
||||||
data.argc = argc;
|
data.argc = argc;
|
||||||
|
@ -905,7 +922,6 @@ int rtcall_int_pobj_obj(
|
||||||
data.sigtype = SIG_INT_OBJARR_OBJ;
|
data.sigtype = SIG_INT_OBJARR_OBJ;
|
||||||
|
|
||||||
future = current_ft;
|
future = current_ft;
|
||||||
future->rt_prim = (void*)f;
|
|
||||||
future->prim_data = data;
|
future->prim_data = data;
|
||||||
|
|
||||||
future_do_runtimecall((void*)f, NULL);
|
future_do_runtimecall((void*)f, NULL);
|
||||||
|
@ -923,23 +939,26 @@ int rtcall_pvoid_pvoid_pvoid(
|
||||||
void *a,
|
void *a,
|
||||||
void *b,
|
void *b,
|
||||||
void **retval)
|
void **retval)
|
||||||
|
/* Called in future thread */
|
||||||
{
|
{
|
||||||
START_XFORM_SKIP;
|
START_XFORM_SKIP;
|
||||||
future_t *future;
|
future_t *future;
|
||||||
prim_data_t data;
|
prim_data_t data;
|
||||||
memset(&data, 0, sizeof(prim_data_t));
|
|
||||||
if (!IS_WORKER_THREAD)
|
if (!IS_WORKER_THREAD)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_FUTURES
|
memset(&data, 0, sizeof(prim_data_t));
|
||||||
|
|
||||||
|
#ifdef DEBUG_FUTURES
|
||||||
printf("scheme_fuel_counter = %d\n", scheme_fuel_counter);
|
printf("scheme_fuel_counter = %d\n", scheme_fuel_counter);
|
||||||
printf("scheme_jit_stack_boundary = %p\n", (void*)scheme_jit_stack_boundary);
|
printf("scheme_jit_stack_boundary = %p\n", (void*)scheme_jit_stack_boundary);
|
||||||
printf("scheme_current_runstack = %p\n", scheme_current_runstack);
|
printf("scheme_current_runstack = %p\n", scheme_current_runstack);
|
||||||
printf("scheme_current_runstack_start = %p\n", scheme_current_runstack_start);
|
printf("scheme_current_runstack_start = %p\n", scheme_current_runstack_start);
|
||||||
printf("stack address = %p\n", &future);
|
printf("stack address = %p\n", &future);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
data.pvoid_pvoid_pvoid = f;
|
data.pvoid_pvoid_pvoid = f;
|
||||||
data.a = a;
|
data.a = a;
|
||||||
|
@ -947,7 +966,6 @@ int rtcall_pvoid_pvoid_pvoid(
|
||||||
data.sigtype = SIG_PVOID_PVOID_PVOID;
|
data.sigtype = SIG_PVOID_PVOID_PVOID;
|
||||||
|
|
||||||
future = current_ft;
|
future = current_ft;
|
||||||
future->rt_prim = (void*)f;
|
|
||||||
future->prim_data = data;
|
future->prim_data = data;
|
||||||
|
|
||||||
future_do_runtimecall((void*)f, NULL);
|
future_do_runtimecall((void*)f, NULL);
|
||||||
|
@ -965,23 +983,26 @@ int rtcall_int_pobj_obj_obj(
|
||||||
Scheme_Object **argv,
|
Scheme_Object **argv,
|
||||||
Scheme_Object *p,
|
Scheme_Object *p,
|
||||||
Scheme_Object **retval)
|
Scheme_Object **retval)
|
||||||
|
/* Called in future thread */
|
||||||
{
|
{
|
||||||
START_XFORM_SKIP;
|
START_XFORM_SKIP;
|
||||||
future_t *future;
|
future_t *future;
|
||||||
prim_data_t data;
|
prim_data_t data;
|
||||||
memset(&data, 0, sizeof(prim_data_t));
|
|
||||||
if (!IS_WORKER_THREAD)
|
if (!IS_WORKER_THREAD)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_FUTURES
|
memset(&data, 0, sizeof(prim_data_t));
|
||||||
|
|
||||||
|
#ifdef DEBUG_FUTURES
|
||||||
printf("scheme_fuel_counter = %d\n", scheme_fuel_counter);
|
printf("scheme_fuel_counter = %d\n", scheme_fuel_counter);
|
||||||
printf("scheme_jit_stack_boundary = %p\n", (void*)scheme_jit_stack_boundary);
|
printf("scheme_jit_stack_boundary = %p\n", (void*)scheme_jit_stack_boundary);
|
||||||
printf("scheme_current_runstack = %p\n", scheme_current_runstack);
|
printf("scheme_current_runstack = %p\n", scheme_current_runstack);
|
||||||
printf("scheme_current_runstack_start = %p\n", scheme_current_runstack_start);
|
printf("scheme_current_runstack_start = %p\n", scheme_current_runstack_start);
|
||||||
printf("stack address = %p\n", &future);
|
printf("stack address = %p\n", &future);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
data.int_pobj_obj_obj = f;
|
data.int_pobj_obj_obj = f;
|
||||||
data.argc = argc;
|
data.argc = argc;
|
||||||
|
@ -990,7 +1011,6 @@ int rtcall_int_pobj_obj_obj(
|
||||||
data.sigtype = SIG_INT_POBJ_OBJ_OBJ;
|
data.sigtype = SIG_INT_POBJ_OBJ_OBJ;
|
||||||
|
|
||||||
future = current_ft;
|
future = current_ft;
|
||||||
future->rt_prim = (void*)f;
|
|
||||||
future->prim_data = data;
|
future->prim_data = data;
|
||||||
|
|
||||||
future_do_runtimecall((void*)f, NULL);
|
future_do_runtimecall((void*)f, NULL);
|
||||||
|
@ -1005,39 +1025,36 @@ int rtcall_int_pobj_obj_obj(
|
||||||
//Does the work of actually invoking a primitive on behalf of a
|
//Does the work of actually invoking a primitive on behalf of a
|
||||||
//future. This function is always invoked on the main (runtime)
|
//future. This function is always invoked on the main (runtime)
|
||||||
//thread.
|
//thread.
|
||||||
void *invoke_rtcall(future_t *future)
|
void invoke_rtcall(future_t *future)
|
||||||
|
/* Called in runtime thread */
|
||||||
{
|
{
|
||||||
void *pret = NULL, *dummy_ret;
|
#ifdef DEBUG_FUTURES
|
||||||
|
|
||||||
//Temporarily use the worker thread's runstack
|
|
||||||
Scheme_Object *ret;
|
|
||||||
Scheme_Object **old_rs = MZ_RUNSTACK, **old_rs_start = MZ_RUNSTACK_START;
|
|
||||||
MZ_RUNSTACK = future->runstack;
|
|
||||||
MZ_RUNSTACK_START = future->runstack_start;
|
|
||||||
#ifdef DEBUG_FUTURES
|
|
||||||
g_rtcall_count++;
|
g_rtcall_count++;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
switch (future->prim_data.sigtype)
|
switch (future->prim_data.sigtype)
|
||||||
{
|
{
|
||||||
case SIG_VOID_VOID:
|
case SIG_VOID_VOID_3ARGS:
|
||||||
{
|
{
|
||||||
prim_void_void_t func = future->prim_data.void_void;
|
prim_void_void_3args_t func = future->prim_data.void_void_3args;
|
||||||
func();
|
|
||||||
|
func(future->runstack);
|
||||||
|
|
||||||
pret = &dummy_ret;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SIG_ALLOC_VOID_PVOID:
|
case SIG_ALLOC_VOID_PVOID:
|
||||||
{
|
{
|
||||||
|
void *ret;
|
||||||
prim_alloc_void_pvoid_t func = future->prim_data.alloc_void_pvoid;
|
prim_alloc_void_pvoid_t func = future->prim_data.alloc_void_pvoid;
|
||||||
ret = func();
|
ret = func();
|
||||||
future->alloc_retval = ret;
|
future->alloc_retval = ret;
|
||||||
|
ret = NULL;
|
||||||
future->alloc_retval_counter = scheme_did_gc_count;
|
future->alloc_retval_counter = scheme_did_gc_count;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SIG_OBJ_INT_POBJ_OBJ:
|
case SIG_OBJ_INT_POBJ_OBJ:
|
||||||
{
|
{
|
||||||
|
Scheme_Object *ret;
|
||||||
prim_obj_int_pobj_obj_t func = future->prim_data.obj_int_pobj_obj;
|
prim_obj_int_pobj_obj_t func = future->prim_data.obj_int_pobj_obj;
|
||||||
ret = func(
|
ret = func(
|
||||||
future->prim_data.p,
|
future->prim_data.p,
|
||||||
|
@ -1055,6 +1072,7 @@ void *invoke_rtcall(future_t *future)
|
||||||
}
|
}
|
||||||
case SIG_INT_OBJARR_OBJ:
|
case SIG_INT_OBJARR_OBJ:
|
||||||
{
|
{
|
||||||
|
Scheme_Object *ret;
|
||||||
prim_int_pobj_obj_t func = future->prim_data.int_pobj_obj;
|
prim_int_pobj_obj_t func = future->prim_data.int_pobj_obj;
|
||||||
ret = func(
|
ret = func(
|
||||||
future->prim_data.argc,
|
future->prim_data.argc,
|
||||||
|
@ -1070,6 +1088,7 @@ void *invoke_rtcall(future_t *future)
|
||||||
}
|
}
|
||||||
case SIG_INT_POBJ_OBJ_OBJ:
|
case SIG_INT_POBJ_OBJ_OBJ:
|
||||||
{
|
{
|
||||||
|
Scheme_Object *ret;
|
||||||
prim_int_pobj_obj_obj_t func = future->prim_data.int_pobj_obj_obj;
|
prim_int_pobj_obj_obj_t func = future->prim_data.int_pobj_obj_obj;
|
||||||
ret = func(
|
ret = func(
|
||||||
future->prim_data.argc,
|
future->prim_data.argc,
|
||||||
|
@ -1086,6 +1105,7 @@ void *invoke_rtcall(future_t *future)
|
||||||
}
|
}
|
||||||
case SIG_PVOID_PVOID_PVOID:
|
case SIG_PVOID_PVOID_PVOID:
|
||||||
{
|
{
|
||||||
|
void *pret = NULL;
|
||||||
prim_pvoid_pvoid_pvoid_t func = future->prim_data.pvoid_pvoid_pvoid;
|
prim_pvoid_pvoid_pvoid_t func = future->prim_data.pvoid_pvoid_pvoid;
|
||||||
pret = func(future->prim_data.a, future->prim_data.b);
|
pret = func(future->prim_data.a, future->prim_data.b);
|
||||||
|
|
||||||
|
@ -1097,12 +1117,6 @@ void *invoke_rtcall(future_t *future)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Restore main thread's runstack
|
|
||||||
MZ_RUNSTACK = old_rs;
|
|
||||||
MZ_RUNSTACK_START = old_rs_start;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1111,6 +1125,7 @@ void *invoke_rtcall(future_t *future)
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
future_t *enqueue_future(void)
|
future_t *enqueue_future(void)
|
||||||
|
/* Called in runtime thread */
|
||||||
{
|
{
|
||||||
future_t *last, *ft;
|
future_t *last, *ft;
|
||||||
last = get_last_future();
|
last = get_last_future();
|
||||||
|
@ -1131,6 +1146,7 @@ future_t *enqueue_future(void)
|
||||||
|
|
||||||
|
|
||||||
future_t *get_pending_future(void)
|
future_t *get_pending_future(void)
|
||||||
|
/* Called in future thread */
|
||||||
{
|
{
|
||||||
START_XFORM_SKIP;
|
START_XFORM_SKIP;
|
||||||
future_t *f;
|
future_t *f;
|
||||||
|
@ -1144,59 +1160,8 @@ future_t *get_pending_future(void)
|
||||||
END_XFORM_SKIP;
|
END_XFORM_SKIP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
future_t *get_future_by_threadid(pthread_t threadid)
|
|
||||||
{
|
|
||||||
START_XFORM_SKIP;
|
|
||||||
future_t *ft = g_future_queue;
|
|
||||||
if (NULL == ft)
|
|
||||||
{
|
|
||||||
printf("Couldn't find a future with thread ID %p!\n", (void*)threadid);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
if (ft->threadid == threadid)
|
|
||||||
{
|
|
||||||
return ft;
|
|
||||||
}
|
|
||||||
|
|
||||||
ft = ft->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("Couldn't find a future with thread ID %p!\n", (void*)threadid);
|
|
||||||
return NULL;
|
|
||||||
END_XFORM_SKIP;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
future_t *get_future(int futureid)
|
|
||||||
{
|
|
||||||
START_XFORM_SKIP;
|
|
||||||
future_t *ft = g_future_queue;
|
|
||||||
if (NULL == ft)
|
|
||||||
{
|
|
||||||
return ft;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (ft->id != futureid)
|
|
||||||
{
|
|
||||||
ft = ft->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Sanity check
|
|
||||||
if (ft->id != futureid)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ft;
|
|
||||||
END_XFORM_SKIP;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
future_t *get_last_future(void)
|
future_t *get_last_future(void)
|
||||||
|
/* Called in runtime thread */
|
||||||
{
|
{
|
||||||
future_t *ft = g_future_queue;
|
future_t *ft = g_future_queue;
|
||||||
if (NULL == ft)
|
if (NULL == ft)
|
||||||
|
|
|
@ -32,7 +32,7 @@ extern Scheme_Object *num_processors(int argc, Scheme_Object *argv[]);
|
||||||
extern int future_do_runtimecall(void *func, void *retval);
|
extern int future_do_runtimecall(void *func, void *retval);
|
||||||
extern void futures_init(void);
|
extern void futures_init(void);
|
||||||
|
|
||||||
typedef void (*prim_void_void_t)(void);
|
typedef void (*prim_void_void_3args_t)(Scheme_Object **);
|
||||||
typedef void *(*prim_alloc_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_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_t)(int, Scheme_Object**);
|
||||||
|
@ -42,7 +42,7 @@ typedef void* (*prim_pvoid_pvoid_pvoid_t)(void*, void*);
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int sigtype;
|
unsigned int sigtype;
|
||||||
|
|
||||||
prim_void_void_t void_void;
|
prim_void_void_3args_t void_void_3args;
|
||||||
prim_alloc_void_pvoid_t alloc_void_pvoid;
|
prim_alloc_void_pvoid_t alloc_void_pvoid;
|
||||||
prim_obj_int_pobj_obj_t obj_int_pobj_obj;
|
prim_obj_int_pobj_obj_t obj_int_pobj_obj;
|
||||||
prim_int_pobj_obj_t int_pobj_obj;
|
prim_int_pobj_obj_t int_pobj_obj;
|
||||||
|
@ -153,7 +153,7 @@ extern void print_ms_and_us(void);
|
||||||
|
|
||||||
//Signature flags for primitive invocations
|
//Signature flags for primitive invocations
|
||||||
//Here the convention is SIG_[arg1type]_[arg2type]..._[return type]
|
//Here the convention is SIG_[arg1type]_[arg2type]..._[return type]
|
||||||
#define SIG_VOID_VOID 1 //void -> void
|
#define SIG_VOID_VOID_3ARGS 1 //void -> void, copy 3 args from runstack
|
||||||
#define SIG_ALLOC_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_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_OBJARR_OBJ 4 //int -> Scheme_Object*[] -> Scheme_Object
|
||||||
|
@ -170,7 +170,7 @@ extern void print_ms_and_us(void);
|
||||||
/*GDB_BREAK;*/ \
|
/*GDB_BREAK;*/ \
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int rtcall_void_void(void (*f)());
|
extern int rtcall_void_void_3args(void (*f)());
|
||||||
extern int rtcall_alloc_void_pvoid(void (*f)(), void **retval);
|
extern int rtcall_alloc_void_pvoid(void (*f)(), void **retval);
|
||||||
extern int rtcall_obj_int_pobj_obj(
|
extern int rtcall_obj_int_pobj_obj(
|
||||||
Scheme_Object* (*f)(Scheme_Object*, int, Scheme_Object**),
|
Scheme_Object* (*f)(Scheme_Object*, int, Scheme_Object**),
|
||||||
|
@ -196,7 +196,7 @@ extern int rtcall_int_pobj_obj(
|
||||||
#define LOG(a...) do { pthread_t self; self = pthread_self(); fprintf(stderr, "%x:%s:%s:%d ", (unsigned) self, __FILE__, __FUNCTION__, __LINE__); fprintf(stderr, a); fprintf(stderr, "\n"); fflush(stdout); } while(0)
|
#define LOG(a...) do { pthread_t self; self = pthread_self(); fprintf(stderr, "%x:%s:%s:%d ", (unsigned) self, __FILE__, __FUNCTION__, __LINE__); fprintf(stderr, a); fprintf(stderr, "\n"); fflush(stdout); } while(0)
|
||||||
#define LOG_THISCALL LOG(__FUNCTION__)
|
#define LOG_THISCALL LOG(__FUNCTION__)
|
||||||
|
|
||||||
#define LOG_RTCALL_VOID_VOID(f) LOG("(function=%p)", f)
|
#define LOG_RTCALL_VOID_VOID_3ARGS(f) LOG("(function=%p)", f)
|
||||||
#define LOG_RTCALL_ALLOC_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_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_OBJ_INT_POBJ_VOID(a,b,c) LOG("(%p, %d, %p)", a, b,c)
|
||||||
|
@ -219,7 +219,7 @@ extern int rtcall_int_pobj_obj(
|
||||||
#define LOG(a...)
|
#define LOG(a...)
|
||||||
#define LOG_THISCALL
|
#define LOG_THISCALL
|
||||||
|
|
||||||
#define LOG_RTCALL_VOID_VOID(f)
|
#define LOG_RTCALL_VOID_VOID_3ARGS(f)
|
||||||
#define LOG_RTCALL_ALLOC_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_OBJ(f,a,b,c)
|
||||||
#define LOG_RTCALL_OBJ_INT_POBJ_VOID(a,b,c)
|
#define LOG_RTCALL_OBJ_INT_POBJ_VOID(a,b,c)
|
||||||
|
|
|
@ -211,6 +211,7 @@ static void *generate_lambda_simple_arity_check(int num_params, int has_rest, in
|
||||||
static void generate_case_lambda(Scheme_Case_Lambda *c, Scheme_Native_Closure_Data *ndata,
|
static void generate_case_lambda(Scheme_Case_Lambda *c, Scheme_Native_Closure_Data *ndata,
|
||||||
int is_method);
|
int is_method);
|
||||||
static void on_demand();
|
static void on_demand();
|
||||||
|
static void on_demand_with_args(Scheme_Object **);
|
||||||
static int generate_non_tail_mark_pos_prefix(mz_jit_state *jitter);
|
static int generate_non_tail_mark_pos_prefix(mz_jit_state *jitter);
|
||||||
static void generate_non_tail_mark_pos_suffix(mz_jit_state *jitter);
|
static void generate_non_tail_mark_pos_suffix(mz_jit_state *jitter);
|
||||||
static void *generate_shared_call(int num_rands, mz_jit_state *old_jitter, int multi_ok, int is_tail,
|
static void *generate_shared_call(int num_rands, mz_jit_state *old_jitter, int multi_ok, int is_tail,
|
||||||
|
@ -2235,7 +2236,7 @@ static Scheme_Object *ts_scheme_tail_apply_from_native(Scheme_Object *rator, int
|
||||||
static void ts_on_demand(void)
|
static void ts_on_demand(void)
|
||||||
{
|
{
|
||||||
START_XFORM_SKIP;
|
START_XFORM_SKIP;
|
||||||
if (rtcall_void_void(on_demand)) {
|
if (rtcall_void_void_3args(on_demand_with_args)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9471,18 +9472,23 @@ void scheme_on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Schem
|
||||||
ndata->max_let_depth = max_depth;
|
ndata->max_let_depth = max_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_demand()
|
static void on_demand_with_args(Scheme_Object **in_argv)
|
||||||
{
|
{
|
||||||
/* On runstack: closure (nearest), argc, argv (deepest) */
|
/* On runstack: closure (nearest), argc, argv (deepest) */
|
||||||
Scheme_Object *c, *argc, **argv;
|
Scheme_Object *c, *argc, **argv;
|
||||||
|
|
||||||
c = MZ_RUNSTACK[0];
|
c = in_argv[0];
|
||||||
argc = MZ_RUNSTACK[1];
|
argc = in_argv[1];
|
||||||
argv = (Scheme_Object **)MZ_RUNSTACK[2];
|
argv = (Scheme_Object **)in_argv[2];
|
||||||
|
|
||||||
scheme_on_demand_generate_lambda((Scheme_Native_Closure *)c, SCHEME_INT_VAL(argc), argv);
|
scheme_on_demand_generate_lambda((Scheme_Native_Closure *)c, SCHEME_INT_VAL(argc), argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void on_demand()
|
||||||
|
{
|
||||||
|
return on_demand_with_args(MZ_RUNSTACK);
|
||||||
|
}
|
||||||
|
|
||||||
Scheme_Native_Closure_Data *scheme_generate_lambda(Scheme_Closure_Data *data, int clear_code_after_jit,
|
Scheme_Native_Closure_Data *scheme_generate_lambda(Scheme_Closure_Data *data, int clear_code_after_jit,
|
||||||
Scheme_Native_Closure_Data *case_lam)
|
Scheme_Native_Closure_Data *case_lam)
|
||||||
{
|
{
|
||||||
|
|
|
@ -428,6 +428,8 @@ void scheme_block_child_signals(int block);
|
||||||
void scheme_check_child_done(void);
|
void scheme_check_child_done(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void scheme_prepare_this_thread_for_GC(Scheme_Thread *t);
|
||||||
|
|
||||||
Scheme_Object **scheme_alloc_runstack(long len);
|
Scheme_Object **scheme_alloc_runstack(long len);
|
||||||
void scheme_set_runstack_limits(Scheme_Object **rs, long len, long start, long end);
|
void scheme_set_runstack_limits(Scheme_Object **rs, long len, long start, long end);
|
||||||
|
|
||||||
|
|
|
@ -281,8 +281,6 @@ typedef struct {
|
||||||
static void register_traversers(void);
|
static void register_traversers(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void prepare_this_thread_for_GC(Scheme_Thread *t);
|
|
||||||
|
|
||||||
static Scheme_Object *custodian_require_mem(int argc, Scheme_Object *args[]);
|
static Scheme_Object *custodian_require_mem(int argc, Scheme_Object *args[]);
|
||||||
static Scheme_Object *custodian_limit_mem(int argc, Scheme_Object *args[]);
|
static Scheme_Object *custodian_limit_mem(int argc, Scheme_Object *args[]);
|
||||||
static Scheme_Object *custodian_can_mem(int argc, Scheme_Object *args[]);
|
static Scheme_Object *custodian_can_mem(int argc, Scheme_Object *args[]);
|
||||||
|
@ -3279,7 +3277,7 @@ Scheme_Object *scheme_call_as_nested_thread(int argc, Scheme_Object *argv[], voi
|
||||||
|
|
||||||
/* zero out anything we need now, because nestee disables
|
/* zero out anything we need now, because nestee disables
|
||||||
GC cleaning for this thread: */
|
GC cleaning for this thread: */
|
||||||
prepare_this_thread_for_GC(p);
|
scheme_prepare_this_thread_for_GC(p);
|
||||||
|
|
||||||
if (!p->runstack_owner) {
|
if (!p->runstack_owner) {
|
||||||
Scheme_Thread **owner;
|
Scheme_Thread **owner;
|
||||||
|
@ -4428,7 +4426,7 @@ void scheme_weak_suspend_thread(Scheme_Thread *r)
|
||||||
|
|
||||||
r->running |= MZTHREAD_SUSPENDED;
|
r->running |= MZTHREAD_SUSPENDED;
|
||||||
|
|
||||||
prepare_this_thread_for_GC(r);
|
scheme_prepare_this_thread_for_GC(r);
|
||||||
|
|
||||||
if (r == scheme_current_thread) {
|
if (r == scheme_current_thread) {
|
||||||
select_thread();
|
select_thread();
|
||||||
|
@ -7329,7 +7327,7 @@ static void prepare_thread_for_GC(Scheme_Object *t)
|
||||||
scheme_clean_list_stack(p);
|
scheme_clean_list_stack(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prepare_this_thread_for_GC(Scheme_Thread *p)
|
void scheme_prepare_this_thread_for_GC(Scheme_Thread *p)
|
||||||
{
|
{
|
||||||
if (p == scheme_current_thread) {
|
if (p == scheme_current_thread) {
|
||||||
#ifdef RUNSTACK_IS_GLOBAL
|
#ifdef RUNSTACK_IS_GLOBAL
|
||||||
|
|
Loading…
Reference in New Issue
Block a user