From 67c3aa4b2d9701e9b946cb13a43a28a2da7ebebb Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 2 Dec 2011 09:58:22 -0700 Subject: [PATCH] improve comments on `future_t' fields; remove a redundant field --- src/racket/src/future.c | 15 +++++----- src/racket/src/future.h | 50 ++++++++++++++++++++++++++++---- src/racket/src/mzmark_future.inc | 2 -- src/racket/src/mzmarksrc.c | 1 - 4 files changed, 52 insertions(+), 16 deletions(-) diff --git a/src/racket/src/future.c b/src/racket/src/future.c index e0cf7d510f..67095d1e5e 100644 --- a/src/racket/src/future.c +++ b/src/racket/src/future.c @@ -1454,7 +1454,6 @@ Scheme_Object *scheme_fsemaphore_wait(int argc, Scheme_Object **argv) scheme_fill_lwc_end(); future->lwc = scheme_current_lwc; future->fts = fts; - future->arg_p = scheme_current_thread; /* Try to capture it locally (on this thread) */ if (GC_gen0_alloc_page_ptr @@ -2186,7 +2185,8 @@ static Scheme_Object *apply_future_lw(future_t *ft) static int capture_future_continuation(Scheme_Future_State *fs, future_t *ft, void **storage, int need_lock) XFORM_SKIP_PROC -/* This function explicitly cooperates with the GC by storing the +/* The lock is *not* help when calling this function. + This function explicitly cooperates with the GC by storing the pointers it needs to save across a collection in `storage', so it can be used in a future thread. If future-thread-local allocation fails, the result is 0. */ @@ -2196,7 +2196,7 @@ static int capture_future_continuation(Scheme_Future_State *fs, future_t *ft, vo storage[2] = ft; - lw = scheme_capture_lightweight_continuation(ft->arg_p, ft->lwc, storage); + lw = scheme_capture_lightweight_continuation(ft->fts->thread, ft->lwc, storage); if (!lw) return 0; ft = (future_t *)storage[2]; @@ -2212,9 +2212,10 @@ static int capture_future_continuation(Scheme_Future_State *fs, future_t *ft, vo continuation. */ return 1; } + + ft->want_lw = 0; } - ft->want_lw = 0; ft->fts->thread->current_ft = NULL; /* tells worker thread that it no longer needs to handle the future */ @@ -2392,7 +2393,6 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, scheme_fill_lwc_end(); future->lwc = scheme_current_lwc; future->fts = fts; - future->arg_p = scheme_current_thread; fid = future->id; @@ -2744,8 +2744,8 @@ static int push_marks(future_t *f, Scheme_Cont_Frame_Data *d) { if (f->suspended_lw) { return scheme_push_marks_from_lightweight_continuation(f->suspended_lw, d); - } else if (f->arg_p) { - return scheme_push_marks_from_thread(f->arg_p, d); + } else if (f->fts->thread) { + return scheme_push_marks_from_thread(f->fts->thread, d); } return 0; @@ -2866,7 +2866,6 @@ static void do_invoke_rtcall(Scheme_Future_State *fs, future_t *future, int is_a need_pop = push_marks(future, &mark_d); else need_pop = 0; - future->arg_p = NULL; switch (future->prim_protocol) { diff --git a/src/racket/src/future.h b/src/racket/src/future.h index 92048f9586..73f6569995 100644 --- a/src/racket/src/future.h +++ b/src/racket/src/future.h @@ -59,13 +59,16 @@ typedef struct future_t { int id; int thread_short_id; + int status; /* The status field is the main locking mechanism. It should only be read and written when holding a lock (and all associated fields for a status should be set at the same time). */ - int status; mzrt_sema *can_continue_sema; + /* this semcpahore is non_NULL when a future thread is blocked + while trying to run the future; th want_lw flag may be set in + that case */ Scheme_Object *orig_lambda; void *code; @@ -74,11 +77,34 @@ typedef struct future_t { thread if this custodian is shut down */ /* Runtime call stuff */ - int want_lw; /* flag to indicate waiting for lw capture */ - /* flag to indicate whether the future is in the "waiting for lwc" queue */ - int in_queue_waiting_for_lwc; + + int want_lw; + /* flag to indicate waiting for lw capture; if this flag is set, + then the future thread currently running the future must be + blocked, and the runtime thread must not already be working on + behalf of the future; since a future thread is blocked on this + future, then can_continue_sema is normally set, but the runtime + thread sets can_continue_sema to NULL while trying to capture the + continuation --- in case anoter thread tries to let the original + future thread continue because it was blocked on a touch for a + future that completed; the `want_lw' flag should be changed only + while holding a lock */ + + int in_queue_waiting_for_lwc; + /* flag to indicate whether the future is in the "waiting for lwc" + queue; the future might be in the queue even if want_lw is set to + 0, and so this flag just prevents */ + int in_touch_queue; + /* like `in_queue_waiting_for_lwc' but for being in a `touch' + future */ + int rt_prim_is_atomic; + /* when a future thread is blocked on this future, it sets + `rt_prim_is_atomic' if the blocking operation can run + in any thread atomically (i.e., it's a "synchronizing" + operation insteda of a general blocking operation) */ + double time_of_request; const char *source_of_request; int source_type; @@ -113,11 +139,25 @@ typedef struct future_t { Scheme_Object **arg_S4; Scheme_Thread *arg_p; + /* when a future thread is blocked while running this future, + `arg_p' s set along with the blocking-operation arguments to + indicate the future thread's (fake) Racket thread, which has the + runstack, etc. */ struct Scheme_Current_LWC *lwc; + /* when a future thread is blocked while running this future, + if `want_lw' is set, then `lwc' points to information for + capturing a lightweight continuation */ struct Scheme_Future_Thread_State *fts; + /* when a future thread is blocked while running this future, + `fts' is set to identify the future thread */ struct Scheme_Lightweight_Continuation *suspended_lw; - int maybe_suspended_lw; /* set to 1 with suspended_lw untl test in runtime thread */ + /* holds a lightweight continuation captured for the operation, + if any */ + int maybe_suspended_lw; + /* set to 1 with suspended_lw untl test in runtime thread; this + extra flag avoids spinning if the suspended continuation + cannot be resumed in the main thread for some reason */ Scheme_Object *retval_s; void *retval_p; /* use only with conservative GC */ diff --git a/src/racket/src/mzmark_future.inc b/src/racket/src/mzmark_future.inc index 6faac56aa0..87821e97e8 100644 --- a/src/racket/src/mzmark_future.inc +++ b/src/racket/src/mzmark_future.inc @@ -21,7 +21,6 @@ static int future_MARK(void *p, struct NewGC *gc) { gcMARK2(f->arg_S1, gc); gcMARK2(f->arg_s2, gc); gcMARK2(f->arg_S2, gc); - gcMARK2(f->arg_p, gc); gcMARK2(f->arg_S4, gc); gcMARK2(f->retval_s, gc); gcMARK2(f->retval, gc); @@ -55,7 +54,6 @@ static int future_FIXUP(void *p, struct NewGC *gc) { gcFIXUP2(f->arg_S1, gc); gcFIXUP2(f->arg_s2, gc); gcFIXUP2(f->arg_S2, gc); - gcFIXUP2(f->arg_p, gc); gcFIXUP2(f->arg_S4, gc); gcFIXUP2(f->retval_s, gc); gcFIXUP2(f->retval, gc); diff --git a/src/racket/src/mzmarksrc.c b/src/racket/src/mzmarksrc.c index 618983e5f6..3c4616fe0e 100644 --- a/src/racket/src/mzmarksrc.c +++ b/src/racket/src/mzmarksrc.c @@ -2444,7 +2444,6 @@ future { gcMARK2(f->arg_S1, gc); gcMARK2(f->arg_s2, gc); gcMARK2(f->arg_S2, gc); - gcMARK2(f->arg_p, gc); gcMARK2(f->arg_S4, gc); gcMARK2(f->retval_s, gc); gcMARK2(f->retval, gc);