more futures fixes

svn: r16874
This commit is contained in:
James Swaine 2009-11-18 17:13:50 +00:00
parent 54f5c14657
commit da1a171ebe
3 changed files with 158 additions and 44 deletions

View File

@ -621,14 +621,13 @@ void *worker_thread_future_loop(void *arg)
sema_signal(&ready_sema); sema_signal(&ready_sema);
wait_for_work: wait_for_work:
//LOG("Waiting for new future work..."); start_gc_not_ok();
start_gc_not_ok();
pthread_mutex_lock(&g_future_queue_mutex); pthread_mutex_lock(&g_future_queue_mutex);
while (!(ft = get_pending_future())) while (!(ft = get_pending_future()))
{ {
end_gc_not_ok(); end_gc_not_ok();
pthread_cond_wait(&g_future_pending_cv, &g_future_queue_mutex); pthread_cond_wait(&g_future_pending_cv, &g_future_queue_mutex);
start_gc_not_ok(); start_gc_not_ok();
} }
LOG("Got a signal that a future is pending..."); LOG("Got a signal that a future is pending...");
@ -690,11 +689,12 @@ void *worker_thread_future_loop(void *arg)
//call invocation. //call invocation.
int future_do_runtimecall( int future_do_runtimecall(
void *func, void *func,
int sigtype, //int sigtype,
void *args, //void *args,
void *retval) void *retval)
{ {
future_t *future; future_t *future;
//If already running on the main thread //If already running on the main thread
//or no future is involved, do nothing //or no future is involved, do nothing
//and return FALSE //and return FALSE
@ -726,9 +726,12 @@ int future_do_runtimecall(
scheme_signal_received_at(g_signal_handle); scheme_signal_received_at(g_signal_handle);
//Wait for the signal that the RT call is finished //Wait for the signal that the RT call is finished
start_gc_not_ok(); end_gc_not_ok();
pthread_cond_wait(&future->can_continue_cv, &g_future_queue_mutex); pthread_cond_wait(&future->can_continue_cv, &g_future_queue_mutex);
end_gc_not_ok(); start_gc_not_ok();
//Fetch the future instance again, in case the GC has moved the pointer
future = get_my_future();
//Clear rt call fields before releasing the lock on the descriptor //Clear rt call fields before releasing the lock on the descriptor
future->rt_prim = NULL; future->rt_prim = NULL;
@ -753,14 +756,14 @@ int rtcall_void_void(void (*f)())
return 0; return 0;
} }
data.prim_void_void = f; data.void_void = f;
data.sigtype = SIG_VOID_VOID; data.sigtype = SIG_VOID_VOID;
future = get_my_future(); future = get_my_future();
future->rt_prim = (void*)f; future->rt_prim = (void*)f;
future->prim_data = data; future->prim_data = data;
future_do_runtimecall((void*)f, SIG_VOID_VOID, NULL, NULL); future_do_runtimecall((void*)f, NULL);
return 1; return 1;
END_XFORM_SKIP; END_XFORM_SKIP;
@ -768,7 +771,7 @@ int rtcall_void_void(void (*f)())
int rtcall_obj_int_pobj_obj( int rtcall_obj_int_pobj_obj(
Scheme_Object* (*f)(Scheme_Object*, int, Scheme_Object**), prim_obj_int_pobj_obj_t f,
Scheme_Object *rator, Scheme_Object *rator,
int argc, int argc,
Scheme_Object **argv, Scheme_Object **argv,
@ -791,7 +794,7 @@ int rtcall_obj_int_pobj_obj(
printf("stack address = %p\n", &future); printf("stack address = %p\n", &future);
#endif #endif
data.prim_obj_int_pobj_obj = f; data.obj_int_pobj_obj = f;
data.p = rator; data.p = rator;
data.argc = argc; data.argc = argc;
data.argv = argv; data.argv = argv;
@ -801,7 +804,7 @@ int rtcall_obj_int_pobj_obj(
future->rt_prim = (void*)f; future->rt_prim = (void*)f;
future->prim_data = data; future->prim_data = data;
future_do_runtimecall((void*)f, SIG_OBJ_INT_POBJ_OBJ, NULL, NULL); future_do_runtimecall((void*)f, NULL);
*retval = future->prim_data.retval; *retval = future->prim_data.retval;
return 1; return 1;
@ -810,7 +813,7 @@ int rtcall_obj_int_pobj_obj(
int rtcall_int_pobj_obj( int rtcall_int_pobj_obj(
Scheme_Object* (*f)(int, Scheme_Object**), prim_int_pobj_obj_t f,
int argc, int argc,
Scheme_Object **argv, Scheme_Object **argv,
Scheme_Object **retval) Scheme_Object **retval)
@ -832,7 +835,7 @@ int rtcall_int_pobj_obj(
printf("stack address = %p\n", &future); printf("stack address = %p\n", &future);
#endif #endif
data.prim_int_pobj_obj = f; data.int_pobj_obj = f;
data.argc = argc; data.argc = argc;
data.argv = argv; data.argv = argv;
data.sigtype = SIG_INT_OBJARR_OBJ; data.sigtype = SIG_INT_OBJARR_OBJ;
@ -841,7 +844,7 @@ int rtcall_int_pobj_obj(
future->rt_prim = (void*)f; future->rt_prim = (void*)f;
future->prim_data = data; future->prim_data = data;
future_do_runtimecall((void*)f, SIG_INT_OBJARR_OBJ, NULL, NULL); future_do_runtimecall((void*)f, NULL);
*retval = future->prim_data.retval; *retval = future->prim_data.retval;
return 1; return 1;
@ -849,8 +852,48 @@ int rtcall_int_pobj_obj(
} }
int rtcall_pvoid_pvoid_pvoid(
prim_pvoid_pvoid_pvoid_t f,
void *a,
void *b,
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;
}
#ifdef DEBUG_FUTURES
printf("scheme_fuel_counter = %d\n", scheme_fuel_counter);
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_start = %p\n", scheme_current_runstack_start);
printf("stack address = %p\n", &future);
#endif
data.pvoid_pvoid_pvoid = f;
data.a = a;
data.b = b;
data.sigtype = SIG_PVOID_PVOID_PVOID;
future = get_my_future();
future->rt_prim = (void*)f;
future->prim_data = data;
future_do_runtimecall((void*)f, NULL);
*retval = future->prim_data.c;
return 1;
END_XFORM_SKIP;
}
int rtcall_int_pobj_obj_obj( int rtcall_int_pobj_obj_obj(
Scheme_Object* (*f)(int, Scheme_Object**, Scheme_Object*), prim_int_pobj_obj_obj_t f,
int argc, int argc,
Scheme_Object **argv, Scheme_Object **argv,
Scheme_Object *p, Scheme_Object *p,
@ -873,7 +916,7 @@ int rtcall_int_pobj_obj_obj(
printf("stack address = %p\n", &future); printf("stack address = %p\n", &future);
#endif #endif
data.prim_int_pobj_obj_obj = f; data.int_pobj_obj_obj = f;
data.argc = argc; data.argc = argc;
data.argv = argv; data.argv = argv;
data.p = p; data.p = p;
@ -883,26 +926,23 @@ int rtcall_int_pobj_obj_obj(
future->rt_prim = (void*)f; future->rt_prim = (void*)f;
future->prim_data = data; future->prim_data = data;
future_do_runtimecall((void*)f, SIG_INT_POBJ_OBJ_OBJ, NULL, NULL); future_do_runtimecall((void*)f, NULL);
*retval = future->prim_data.retval; *retval = future->prim_data.retval;
return 1; return 1;
END_XFORM_SKIP; END_XFORM_SKIP;
} }
//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)
{ {
START_XFORM_SKIP; void *pret = NULL, *dummy_ret;
void *ret = NULL, *dummy_ret;
void **arr = NULL;
prim_data_t *pdata; prim_data_t *pdata;
MZ_MARK_STACK_TYPE lret = 0;
//Temporarily use the worker thread's runstack //Temporarily use the worker thread's runstack
Scheme_Object *ret;
Scheme_Object **old_rs = MZ_RUNSTACK, **old_rs_start = MZ_RUNSTACK_START; Scheme_Object **old_rs = MZ_RUNSTACK, **old_rs_start = MZ_RUNSTACK_START;
MZ_RUNSTACK = future->runstack; MZ_RUNSTACK = future->runstack;
MZ_RUNSTACK_START = future->runstack_start; MZ_RUNSTACK_START = future->runstack_start;
@ -910,48 +950,84 @@ void *invoke_rtcall(future_t *future)
g_rtcall_count++; g_rtcall_count++;
#endif #endif
pdata = &future->prim_data;
switch (future->prim_data.sigtype) switch (future->prim_data.sigtype)
{ {
case SIG_VOID_VOID: case SIG_VOID_VOID:
{ {
pdata = &future->prim_data; prim_void_void_t func = pdata->void_void;
pdata->prim_void_void(); func();
ret = &dummy_ret; pret = &dummy_ret;
break; break;
} }
case SIG_OBJ_INT_POBJ_OBJ: case SIG_OBJ_INT_POBJ_OBJ:
{ {
pdata = &future->prim_data; prim_obj_int_pobj_obj_t func = pdata->obj_int_pobj_obj;
pdata->retval = pdata->prim_obj_int_pobj_obj( ret = func(
pdata->p, pdata->p,
pdata->argc, pdata->argc,
pdata->argv); pdata->argv);
pdata->retval = ret;
/*pdata->retval = pdata->prim_obj_int_pobj_obj(
pdata->p,
pdata->argc,
pdata->argv); */
break; break;
} }
case SIG_INT_OBJARR_OBJ: case SIG_INT_OBJARR_OBJ:
pdata = &future->prim_data; {
pdata->retval = pdata->prim_int_pobj_obj( prim_int_pobj_obj_t func = pdata->int_pobj_obj;
ret = func(
pdata->argc, pdata->argc,
pdata->argv); pdata->argv);
pdata->retval = ret;
/*pdata->retval = pdata->prim_int_pobj_obj(
pdata->argc,
pdata->argv);
*/
break; break;
}
case SIG_INT_POBJ_OBJ_OBJ: case SIG_INT_POBJ_OBJ_OBJ:
pdata = &future->prim_data; {
pdata->retval = pdata->prim_int_pobj_obj_obj( prim_int_pobj_obj_obj_t func = pdata->int_pobj_obj_obj;
ret = func(
pdata->argc, pdata->argc,
pdata->argv, pdata->argv,
pdata->p); pdata->p);
break;
} pdata->retval = ret;
/*pdata->retval = pdata->prim_int_pobj_obj_obj(
pdata->argc,
pdata->argv,
pdata->p);
*/
break;
}
case SIG_PVOID_PVOID_PVOID:
{
prim_pvoid_pvoid_pvoid_t func = pdata->pvoid_pvoid_pvoid;
pret = func(pdata->a, pdata->b);
pdata->c = pret;
/*pdata->c = pdata->prim_pvoid_pvoid_pvoid(
pdata->a,
pdata->b);
*/
break;
}
}
//Restore main thread's runstack //Restore main thread's runstack
MZ_RUNSTACK = old_rs; MZ_RUNSTACK = old_rs;
MZ_RUNSTACK_START = old_rs_start; MZ_RUNSTACK_START = old_rs_start;
return ret; return ret;
END_XFORM_SKIP;
} }

View File

@ -29,22 +29,39 @@ extern Scheme_Object *end_primitive_tracking(int argc, Scheme_Object *argv[]);
extern Scheme_Object *future(int argc, Scheme_Object *argv[]); extern Scheme_Object *future(int argc, Scheme_Object *argv[]);
extern Scheme_Object *touch(int argc, Scheme_Object *argv[]); extern Scheme_Object *touch(int argc, Scheme_Object *argv[]);
extern Scheme_Object *num_processors(int argc, Scheme_Object *argv[]); extern Scheme_Object *num_processors(int argc, Scheme_Object *argv[]);
extern int future_do_runtimecall(void *func, int sigtype, void *args, 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 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*);
typedef void* (*prim_pvoid_pvoid_pvoid_t)(void*, void*);
typedef struct { typedef struct {
unsigned int sigtype; unsigned int sigtype;
Scheme_Object* (*prim_obj_int_pobj_obj)(Scheme_Object* rator, int argc, Scheme_Object** argv); prim_void_void_t void_void;
Scheme_Object* (*prim_int_pobj_obj)(int argc, Scheme_Object** argv); prim_obj_int_pobj_obj_t obj_int_pobj_obj;
Scheme_Object* (*prim_int_pobj_obj_obj)(int argc, Scheme_Object** argv, Scheme_Object* p); prim_int_pobj_obj_t int_pobj_obj;
void (*prim_void_void)(void); prim_int_pobj_obj_obj_t int_pobj_obj_obj;
prim_pvoid_pvoid_pvoid_t pvoid_pvoid_pvoid;
//Scheme_Object* (*prim_obj_int_pobj_obj)(Scheme_Object* rator, int argc, Scheme_Object** argv);
//Scheme_Object* (*prim_int_pobj_obj)(int argc, Scheme_Object** argv);
//Scheme_Object* (*prim_int_pobj_obj_obj)(int argc, Scheme_Object** argv, Scheme_Object* p);
//void (*prim_void_void)(void);
//void* (*prim_pvoid_pvoid_pvoid)(void *a, void *b);
Scheme_Object *p; Scheme_Object *p;
int argc; int argc;
Scheme_Object **argv; Scheme_Object **argv;
Scheme_Object *retval; Scheme_Object *retval;
void *a;
void *b;
void *c;
} prim_data_t; } prim_data_t;
#define PENDING 0 #define PENDING 0
@ -136,6 +153,7 @@ extern void print_ms_and_us(void);
#define SIG_OBJ_INT_POBJ_OBJ 2 //Scheme_Object* -> int -> Scheme_Object** -> Scheme_Object* #define SIG_OBJ_INT_POBJ_OBJ 2 //Scheme_Object* -> int -> Scheme_Object** -> Scheme_Object*
#define SIG_INT_OBJARR_OBJ 3 //int -> Scheme_Object*[] -> Scheme_Object #define SIG_INT_OBJARR_OBJ 3 //int -> Scheme_Object*[] -> Scheme_Object
#define SIG_INT_POBJ_OBJ_OBJ 17 //int -> Scheme_Object** -> Scheme_Object* -> Scheme_Object* #define SIG_INT_POBJ_OBJ_OBJ 17 //int -> Scheme_Object** -> Scheme_Object* -> Scheme_Object*
#define SIG_PVOID_PVOID_PVOID 18 //void* -> void* -> void*
//Helper macros for argument marshaling //Helper macros for argument marshaling
#ifdef FUTURES_ENABLED #ifdef FUTURES_ENABLED

View File

@ -1378,6 +1378,7 @@ static int generate_alloc_retry(mz_jit_state *jitter, int i);
THREAD_LOCAL_DECL(static double save_fp); THREAD_LOCAL_DECL(static double save_fp);
#endif #endif
static void *prepare_retry_alloc(void *p, void *p2) static void *prepare_retry_alloc(void *p, void *p2)
{ {
/* Alocate enough to trigger a new page */ /* Alocate enough to trigger a new page */
@ -2233,6 +2234,25 @@ static void ts_on_demand(void)
on_demand(); on_demand();
} }
#ifdef MZ_PRECISE_GC
static void *ts_prepare_retry_alloc(void *p, void *p2)
{
void *ret;
LOG_PRIM_START(&prepare_retry_alloc);
if (rtcall_pvoid_pvoid_pvoid(prepare_retry_alloc,
p,
p2,
&ret))
{
return ret;
}
ret = prepare_retry_alloc(p, p2);
LOG_PRIM_END(&prepare_retry_alloc);
return ret;
}
#endif
#else #else
/* futures not enabled */ /* futures not enabled */
# define mz_prepare_direct_prim(n) mz_prepare(n) # define mz_prepare_direct_prim(n) mz_prepare(n)
@ -9080,7 +9100,7 @@ static int generate_alloc_retry(mz_jit_state *jitter, int i)
jit_pusharg_p(JIT_R0); jit_pusharg_p(JIT_R0);
jit_pusharg_p(JIT_R0); jit_pusharg_p(JIT_R0);
} }
(void)mz_finish(prepare_retry_alloc); (void)mz_finish(ts_prepare_retry_alloc);
jit_retval(JIT_R0); jit_retval(JIT_R0);
if (i == 1) { if (i == 1) {
mz_tl_ldi_l(JIT_R1, tl_retry_alloc_r1); mz_tl_ldi_l(JIT_R1, tl_retry_alloc_r1);