diff --git a/collects/scribblings/guide/futures.scrbl b/collects/scribblings/guide/futures.scrbl index 38977fc02a..07b39b125d 100644 --- a/collects/scribblings/guide/futures.scrbl +++ b/collects/scribblings/guide/futures.scrbl @@ -166,10 +166,12 @@ the following output in the @racket['debug] log level: @exec{racket} with @Flag{W} @tt{debug}.} @verbatim[#:indent 2]|{ - future: 0 waiting for runtime at 1267392979341.989: * + future 1, process 1: BLOCKING on process 0; time: .... + .... + future 1, process 0: HANDLING: *; time: .... }| -The message indicates which internal future-running task became +The messages indicate which internal future-running task became blocked on an unsafe operation, the time it blocked (in terms of @racket[current-inexact-miliseconds]), and the operation that caused the computation it to block. @@ -178,5 +180,8 @@ The first revision to @racket[mandelbrot] avoids suspending at @racket[*], but produces many log entries of the form @verbatim[#:indent 2]|{ - future: 0 waiting for runtime at 1267392980465.066: [acquire_gc_page] + future 1, process 0: synchronizing: [allocate memory]; time: .... }| + +The @tt{[allocate memory]} part of the message indicates that +synchronization was needed for memory allocation. diff --git a/collects/scribblings/reference/futures.scrbl b/collects/scribblings/reference/futures.scrbl index 90d94ebbf3..82b94fc7c9 100644 --- a/collects/scribblings/reference/futures.scrbl +++ b/collects/scribblings/reference/futures.scrbl @@ -5,6 +5,8 @@ @(define future-eval (make-base-eval)) @(interaction-eval #:eval future-eval (require racket/future)) +@(define time-id @racketidfont{time}) + @title[#:tag "futures"]{Futures} @guideintro["effective-futures"]{futures} @@ -147,6 +149,92 @@ execute through a call to @racket[touch], however. } +@; ------------------------------------------------------------ + +@section[#:tag "future-logging"]{Future Performance Logging} + +Racket futures use logging (see @secref["logging"]) extensively to +report information about how futures are evaluated. Logging output is +useful for debugging the performance of programs that use futures. + +In addition to its string message, each event logged for a future has +a data value that is an instance of a @racket[future-event] +@tech{prefab} structure: + +@racketblock[ +(define-struct future-event (future-id proc-id action time) + #:prefab) +] + +The @racket[future-id] field is an exact integer that identifies a +future, or it is @racket[#f] when @racket[action] is +@racket['missing]. The @racket[future-id] field is particularly useful +for correlating logged events. + +The @racket[proc-id] fields is an exact, non-negative integer that +identifies a parallel process. Process 0 is the main Racket process, +where all expressions other than future thunks evaluate. + +The @|time-id| field is an inexact number that represents time in +the same way as @racket[current-inexact-milliseconds]. + +The @racket[action] field is a symbol: + +@itemlist[ + + @item{@racket['create]: a future was created.} + + @item{@racket['complete]: a future's thunk evaluated successfully, so + that @racket[touch] will produce a value for the future + immediately.} + + @item{@racket['start-work] and @racket['end-work]: a particular + process started and ended working on a particular future.} + + @item{@racket['start-0-work]: like @racket['start-work], but for a + future thunk that for some structural reason could not be + started in a process other than 0 (e.g., the thunk requires too + much local storage to start).} + + @item{@racket['sync]: blocking (processes other than 0) or initiation + of handing (process 0) for an ``unsafe'' operation in a future + thunk's evaluation; the operation must run in process 0.} + + @item{@racket['block]: like @racket['sync], but for a part of + evaluation that must be delayed until the future is + @racket[touch]ed, because the evaluation may depend on the + current continuation.} + + @item{@racket['result] or @racket['abort]: waiting or handling for + @racket['sync] or @racket['block] ended with a value or an + error, respectively.} + + @item{@racket['suspend] (never in process 0): a process blocked by + @racket['sync] or @racket['block] abandoned evaluation of a + future; some other process may pick up the future later.} + + @item{@racket['touch-pause] and @racket['touch-resume] (in process 0, + only): waiting in @racket[touch] for a future whose thunk is + being evaluated in another process.} + + @item{@racket['missing]: one or more events for the process were lost + due to internal buffer limits before they could be reported, + and the @|time-id| field reports an upper limit on the time + of the missing events; this kind of event is rare.} + +] + +Assuming no @racket['missing] events, then @racket['start-work] or +@racket['start-0-work] is always paired with @racket['end-work], +@racket['sync] and @racket['block] are always paired with +@racket['result], @racket['abort], or @racket['suspend], and +@racket['touch-pause] is always paired with @racket['touch-resume]. + +In process 0, some event pairs can be nested within other event pairs: +@racket['sync] or @racket['block] with @racket['result] or +@racket['abort], and @racket['touch-pause] with +@racket['touch-resume].} + @; ---------------------------------------------------------------------- @close-eval[future-eval] diff --git a/collects/scribblings/reference/runtime.scrbl b/collects/scribblings/reference/runtime.scrbl index 7bca50ae8c..e6eeb34562 100644 --- a/collects/scribblings/reference/runtime.scrbl +++ b/collects/scribblings/reference/runtime.scrbl @@ -139,12 +139,12 @@ statistics. If @racket[thd] is not @racket[#f], a particular set of thread-specific statistics are reported, otherwise a different set of global statics are reported. -For global statistics, up to @math{10} elements are set in the vector, -starting from the beginning. (In future versions of Racket, additional -elements will be set.) If @racket[results] has @math{n} elements where -@math{n < 8}, then the @math{n} elements are set to the first @math{n} -performance-statistics values. The reported statistics values are as -follows, in the order that they are set within @racket[results]: +For global statistics, up to @math{11} elements are set in the vector, +starting from the beginning. If @racket[results] has @math{n} elements +where @math{n < 11}, then the @math{n} elements are set to the first +@math{n} performance-statistics values. The reported statistics values +are as follows, in the order that they are set within +@racket[results]: @itemize[ diff --git a/collects/tests/future/future.rkt b/collects/tests/future/future.rkt index 7b9fb86cad..0e4436ba0d 100644 --- a/collects/tests/future/future.rkt +++ b/collects/tests/future/future.rkt @@ -494,3 +494,22 @@ We should also test deep continuations. (sleep 0.1) (custodian-shutdown-all c) (sleep 0.1)) + +;; Stress test: +(for-each + (lambda (v) (check-equal? 10 (touch (touch v)))) + (for/list ([i (in-range 10000)]) + (future (lambda () (future (lambda () 10)))))) + +;; Stress test: +(check-equal? + 0 + (touch + (for/fold ([t (future (lambda () 0))]) ([i (in-range 10000)]) + (future (lambda () (touch t)))))) + + + + + + diff --git a/src/racket/gc2/gc2.h b/src/racket/gc2/gc2.h index 957186bcf8..7c0ea09eb1 100644 --- a/src/racket/gc2/gc2.h +++ b/src/racket/gc2/gc2.h @@ -438,13 +438,14 @@ GC2_EXTERN intptr_t GC_alloc_alignment(); can be called from any thread. */ -GC2_EXTERN uintptr_t GC_make_jit_nursery_page(int count); +GC2_EXTERN uintptr_t GC_make_jit_nursery_page(int count, uintptr_t *sz); /* Obtains nursery pages from the GC for thread local allocation; resulting space is count times the allocation alignment. The result is an uintptr_t because it's not a valid pointer to a GCable object. The result becomes invalid (i.e. it's collected) - with the next GC. + with the next GC. If non-NULL, the `sz' argument is filled + with the length of the allocation area after the result. */ GC2_EXTERN void GC_check_master_gc_request(); diff --git a/src/racket/gc2/newgc.c b/src/racket/gc2/newgc.c index 7188f5a475..373b8b2945 100644 --- a/src/racket/gc2/newgc.c +++ b/src/racket/gc2/newgc.c @@ -1022,7 +1022,7 @@ inline static void gen0_free_nursery_mpage(NewGC *gc, mpage *page, const size_t /* Needs to be consistent with GC_alloc_alignment(): */ #define THREAD_LOCAL_PAGE_SIZE APAGE_SIZE -uintptr_t GC_make_jit_nursery_page(int count) { +uintptr_t GC_make_jit_nursery_page(int count, uintptr_t *sz) { NewGC *gc = GC_get_GC(); mpage *new_mpage; intptr_t size = count * THREAD_LOCAL_PAGE_SIZE; @@ -1055,6 +1055,8 @@ uintptr_t GC_make_jit_nursery_page(int count) { new_mpage->size = WORD_SIZE; #endif } + if (sz) + *sz = size - new_mpage->size; return (NUM(new_mpage->addr) + new_mpage->size); } diff --git a/src/racket/include/mzwin.def b/src/racket/include/mzwin.def index 9dde09cf63..4064ca015c 100644 --- a/src/racket/include/mzwin.def +++ b/src/racket/include/mzwin.def @@ -97,6 +97,7 @@ EXPORTS scheme_raise scheme_log_level_p scheme_log + scheme_log_w_data scheme_log_message scheme_log_abort scheme_log_warning diff --git a/src/racket/include/mzwin3m.def b/src/racket/include/mzwin3m.def index b38a0c7c83..4cdbe20d4b 100644 --- a/src/racket/include/mzwin3m.def +++ b/src/racket/include/mzwin3m.def @@ -97,6 +97,7 @@ EXPORTS scheme_raise scheme_log_level_p scheme_log + scheme_log_w_data scheme_log_message scheme_log_abort scheme_log_warning diff --git a/src/racket/include/racket.exp b/src/racket/include/racket.exp index e1a80b149b..0a8dd3a8e1 100644 --- a/src/racket/include/racket.exp +++ b/src/racket/include/racket.exp @@ -95,6 +95,7 @@ scheme_warning scheme_raise scheme_log_level_p scheme_log +scheme_log_w_data scheme_log_message scheme_log_abort scheme_log_warning diff --git a/src/racket/include/racket3m.exp b/src/racket/include/racket3m.exp index b32ba6cb22..79adea4d10 100644 --- a/src/racket/include/racket3m.exp +++ b/src/racket/include/racket3m.exp @@ -95,6 +95,7 @@ scheme_warning scheme_raise scheme_log_level_p scheme_log +scheme_log_w_data scheme_log_message scheme_log_abort scheme_log_warning diff --git a/src/racket/src/cstartup.inc b/src/racket/src/cstartup.inc index 928059308d..d8f7dcdbd5 100644 --- a/src/racket/src/cstartup.inc +++ b/src/racket/src/cstartup.inc @@ -1,44 +1,44 @@ { - SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,48,46,50,51,0,0,0,1,0,0,10,0,13,0, -22,0,29,0,34,0,38,0,41,0,46,0,59,0,66,0,70,0,75,0,82, + SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,48,46,54,51,0,0,0,1,0,0,10,0,13,0, +22,0,27,0,31,0,36,0,49,0,54,0,58,0,65,0,68,0,75,0,82, 0,88,0,102,0,116,0,119,0,125,0,129,0,131,0,142,0,144,0,158,0, 165,0,187,0,189,0,203,0,14,1,43,1,54,1,65,1,75,1,111,1,144, 1,177,1,236,1,46,2,124,2,190,2,195,2,215,2,106,3,126,3,177,3, 243,3,128,4,14,5,66,5,89,5,168,5,0,0,109,7,0,0,69,35,37, -109,105,110,45,115,116,120,29,11,11,68,104,101,114,101,45,115,116,120,66,108, -101,116,114,101,99,64,108,101,116,42,63,97,110,100,62,111,114,64,119,104,101, -110,72,112,97,114,97,109,101,116,101,114,105,122,101,66,100,101,102,105,110,101, -63,108,101,116,64,99,111,110,100,66,117,110,108,101,115,115,65,113,117,111,116, +109,105,110,45,115,116,120,29,11,11,68,104,101,114,101,45,115,116,120,64,108, +101,116,42,63,108,101,116,64,119,104,101,110,72,112,97,114,97,109,101,116,101, +114,105,122,101,64,99,111,110,100,63,97,110,100,66,108,101,116,114,101,99,62, +111,114,66,100,101,102,105,110,101,66,117,110,108,101,115,115,65,113,117,111,116, 101,29,94,2,14,68,35,37,107,101,114,110,101,108,11,29,94,2,14,68,35, 37,112,97,114,97,109,122,11,62,105,102,65,98,101,103,105,110,63,115,116,120, 61,115,70,108,101,116,45,118,97,108,117,101,115,61,120,73,108,101,116,114,101, 99,45,118,97,108,117,101,115,66,108,97,109,98,100,97,1,20,112,97,114,97, 109,101,116,101,114,105,122,97,116,105,111,110,45,107,101,121,61,118,73,100,101, -102,105,110,101,45,118,97,108,117,101,115,97,36,11,8,240,144,82,0,0,95, -159,2,16,36,36,159,2,15,36,36,159,2,15,36,36,16,20,2,4,2,2, -2,5,2,2,2,6,2,2,2,7,2,2,2,8,2,2,2,9,2,2,2, -10,2,2,2,11,2,2,2,12,2,2,2,13,2,2,97,37,11,8,240,144, -82,0,0,93,159,2,15,36,37,16,2,2,3,161,2,2,37,2,3,2,2, -2,3,96,38,11,8,240,144,82,0,0,16,0,96,11,11,8,240,144,82,0, +102,105,110,101,45,118,97,108,117,101,115,97,36,11,8,240,24,83,0,0,95, +159,2,16,36,36,159,2,15,36,36,159,2,15,36,36,16,20,2,11,2,2, +2,4,2,2,2,5,2,2,2,6,2,2,2,8,2,2,2,9,2,2,2, +7,2,2,2,10,2,2,2,12,2,2,2,13,2,2,97,37,11,8,240,24, +83,0,0,93,159,2,15,36,37,16,2,2,3,161,2,2,37,2,3,2,2, +2,3,96,38,11,8,240,24,83,0,0,16,0,96,11,11,8,240,24,83,0, 0,16,0,13,16,4,36,29,11,11,2,2,11,18,16,2,99,64,104,101,114, -101,8,32,8,31,8,30,8,29,8,28,93,8,224,151,82,0,0,95,9,8, -224,151,82,0,0,2,2,27,248,22,155,4,195,249,22,148,4,80,158,39,36, +101,8,32,8,31,8,30,8,29,8,28,93,8,224,31,83,0,0,95,9,8, +224,31,83,0,0,2,2,27,248,22,155,4,195,249,22,148,4,80,158,39,36, 251,22,83,2,17,248,22,98,199,12,249,22,73,2,18,248,22,100,201,27,248, 22,155,4,195,249,22,148,4,80,158,39,36,251,22,83,2,17,248,22,98,199, 249,22,73,2,18,248,22,100,201,12,27,248,22,75,248,22,155,4,196,28,248, 22,81,193,20,15,159,37,36,37,28,248,22,81,248,22,75,194,248,22,74,193, 249,22,148,4,80,158,39,36,251,22,83,2,17,248,22,74,199,249,22,73,2, -6,248,22,75,201,11,18,16,2,101,10,8,32,8,31,8,30,8,29,8,28, -16,4,11,11,2,19,3,1,8,101,110,118,49,51,52,54,49,16,4,11,11, -2,20,3,1,8,101,110,118,49,51,52,54,50,93,8,224,152,82,0,0,95, -9,8,224,152,82,0,0,2,2,27,248,22,75,248,22,155,4,196,28,248,22, +9,248,22,75,201,11,18,16,2,101,10,8,32,8,31,8,30,8,29,8,28, +16,4,11,11,2,19,3,1,8,101,110,118,49,51,54,49,49,16,4,11,11, +2,20,3,1,8,101,110,118,49,51,54,49,50,93,8,224,32,83,0,0,95, +9,8,224,32,83,0,0,2,2,27,248,22,75,248,22,155,4,196,28,248,22, 81,193,20,15,159,37,36,37,28,248,22,81,248,22,75,194,248,22,74,193,249, 22,148,4,80,158,39,36,250,22,83,2,21,248,22,83,249,22,83,248,22,83, -2,22,248,22,74,201,251,22,83,2,17,2,22,2,22,249,22,73,2,7,248, +2,22,248,22,74,201,251,22,83,2,17,2,22,2,22,249,22,73,2,11,248, 22,75,204,18,16,2,101,11,8,32,8,31,8,30,8,29,8,28,16,4,11, -11,2,19,3,1,8,101,110,118,49,51,52,54,52,16,4,11,11,2,20,3, -1,8,101,110,118,49,51,52,54,53,93,8,224,153,82,0,0,95,9,8,224, -153,82,0,0,2,2,248,22,155,4,193,27,248,22,155,4,194,249,22,73,248, +11,2,19,3,1,8,101,110,118,49,51,54,49,52,16,4,11,11,2,20,3, +1,8,101,110,118,49,51,54,49,53,93,8,224,33,83,0,0,95,9,8,224, +33,83,0,0,2,2,248,22,155,4,193,27,248,22,155,4,194,249,22,73,248, 22,83,248,22,74,196,248,22,75,195,27,248,22,75,248,22,155,4,23,197,1, 249,22,148,4,80,158,39,36,28,248,22,58,248,22,149,4,248,22,74,23,198, 2,27,249,22,2,32,0,89,162,8,44,37,43,9,222,33,40,248,22,155,4, @@ -52,7 +52,7 @@ 37,47,9,222,33,43,248,22,155,4,248,22,74,201,248,22,75,198,27,248,22, 75,248,22,155,4,196,27,248,22,155,4,248,22,74,195,249,22,148,4,80,158, 40,36,28,248,22,81,195,250,22,84,2,21,9,248,22,75,199,250,22,83,2, -11,248,22,83,248,22,74,199,250,22,84,2,5,248,22,75,201,248,22,75,202, +5,248,22,83,248,22,74,199,250,22,84,2,4,248,22,75,201,248,22,75,202, 27,248,22,75,248,22,155,4,23,197,1,27,249,22,1,22,87,249,22,2,22, 155,4,248,22,155,4,248,22,74,199,249,22,148,4,80,158,40,36,251,22,83, 1,22,119,105,116,104,45,99,111,110,116,105,110,117,97,116,105,111,110,45,109, @@ -63,13 +63,13 @@ 155,4,196,28,248,22,81,193,20,15,159,37,36,37,249,22,148,4,80,158,39, 36,27,248,22,155,4,248,22,74,197,28,249,22,134,9,62,61,62,248,22,149, 4,248,22,98,196,250,22,83,2,21,248,22,83,249,22,83,21,93,2,26,248, -22,74,199,250,22,84,2,12,249,22,83,2,26,249,22,83,248,22,107,203,2, +22,74,199,250,22,84,2,8,249,22,83,2,26,249,22,83,248,22,107,203,2, 26,248,22,75,202,251,22,83,2,17,28,249,22,134,9,248,22,149,4,248,22, 74,200,64,101,108,115,101,10,248,22,74,197,250,22,84,2,21,9,248,22,75, -200,249,22,73,2,12,248,22,75,202,100,8,32,8,31,8,30,8,29,8,28, -16,4,11,11,2,19,3,1,8,101,110,118,49,51,52,56,55,16,4,11,11, -2,20,3,1,8,101,110,118,49,51,52,56,56,93,8,224,154,82,0,0,18, -16,2,158,94,10,64,118,111,105,100,8,48,95,9,8,224,154,82,0,0,2, +200,249,22,73,2,8,248,22,75,202,100,8,32,8,31,8,30,8,29,8,28, +16,4,11,11,2,19,3,1,8,101,110,118,49,51,54,51,55,16,4,11,11, +2,20,3,1,8,101,110,118,49,51,54,51,56,93,8,224,34,83,0,0,18, +16,2,158,94,10,64,118,111,105,100,8,48,95,9,8,224,34,83,0,0,2, 2,27,248,22,75,248,22,155,4,196,249,22,148,4,80,158,39,36,28,248,22, 58,248,22,149,4,248,22,74,197,250,22,83,2,27,248,22,83,248,22,74,199, 248,22,98,198,27,248,22,149,4,248,22,74,197,250,22,83,2,27,248,22,83, @@ -83,23 +83,23 @@ 11,11,16,0,16,0,16,0,36,36,16,11,16,5,2,3,20,15,159,36,36, 36,36,20,105,159,36,16,0,16,1,33,33,10,16,5,2,13,89,162,8,44, 37,53,9,223,0,33,34,36,20,105,159,36,16,1,2,3,16,0,11,16,5, -2,8,89,162,8,44,37,53,9,223,0,33,35,36,20,105,159,36,16,1,2, -3,16,0,11,16,5,2,6,89,162,8,44,37,53,9,223,0,33,36,36,20, -105,159,36,16,1,2,3,16,1,33,37,11,16,5,2,7,89,162,8,44,37, +2,6,89,162,8,44,37,53,9,223,0,33,35,36,20,105,159,36,16,1,2, +3,16,0,11,16,5,2,9,89,162,8,44,37,53,9,223,0,33,36,36,20, +105,159,36,16,1,2,3,16,1,33,37,11,16,5,2,11,89,162,8,44,37, 56,9,223,0,33,38,36,20,105,159,36,16,1,2,3,16,1,33,39,11,16, -5,2,11,89,162,8,44,37,58,9,223,0,33,42,36,20,105,159,36,16,1, -2,3,16,0,11,16,5,2,4,89,162,8,44,37,53,9,223,0,33,44,36, -20,105,159,36,16,1,2,3,16,0,11,16,5,2,5,89,162,8,44,37,54, -9,223,0,33,45,36,20,105,159,36,16,1,2,3,16,0,11,16,5,2,9, +5,2,5,89,162,8,44,37,58,9,223,0,33,42,36,20,105,159,36,16,1, +2,3,16,0,11,16,5,2,10,89,162,8,44,37,53,9,223,0,33,44,36, +20,105,159,36,16,1,2,3,16,0,11,16,5,2,4,89,162,8,44,37,54, +9,223,0,33,45,36,20,105,159,36,16,1,2,3,16,0,11,16,5,2,7, 89,162,8,44,37,55,9,223,0,33,46,36,20,105,159,36,16,1,2,3,16, -0,11,16,5,2,12,89,162,8,44,37,58,9,223,0,33,47,36,20,105,159, -36,16,1,2,3,16,1,33,49,11,16,5,2,10,89,162,8,44,37,54,9, +0,11,16,5,2,8,89,162,8,44,37,58,9,223,0,33,47,36,20,105,159, +36,16,1,2,3,16,1,33,49,11,16,5,2,12,89,162,8,44,37,54,9, 223,0,33,50,36,20,105,159,36,16,1,2,3,16,0,11,16,0,94,2,15, 2,16,93,2,15,9,9,36,0}; EVAL_ONE_SIZED_STR((char *)expr, 2024); } { - SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,48,46,50,74,0,0,0,1,0,0,8,0,21,0, + SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,48,46,54,74,0,0,0,1,0,0,8,0,21,0, 26,0,43,0,58,0,76,0,92,0,106,0,128,0,146,0,166,0,182,0,200, 0,231,0,4,1,26,1,40,1,46,1,60,1,65,1,75,1,83,1,111,1, 143,1,188,1,194,1,201,1,207,1,252,1,20,2,59,2,61,2,63,2,229, @@ -522,7 +522,7 @@ EVAL_ONE_SIZED_STR((char *)expr, 8817); } { - SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,48,46,50,12,0,0,0,1,0,0,15,0,40,0, + SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,48,46,54,12,0,0,0,1,0,0,15,0,40,0, 57,0,75,0,97,0,120,0,140,0,162,0,169,0,176,0,183,0,0,0,183, 1,0,0,74,35,37,112,108,97,99,101,45,115,116,114,117,99,116,1,23,115, 116,114,117,99,116,58,84,72,45,112,108,97,99,101,45,99,104,97,110,110,101, @@ -549,7 +549,7 @@ EVAL_ONE_SIZED_STR((char *)expr, 484); } { - SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,48,46,50,74,0,0,0,1,0,0,7,0,18,0, + SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,48,46,54,74,0,0,0,1,0,0,7,0,18,0, 45,0,51,0,64,0,73,0,80,0,102,0,124,0,150,0,162,0,180,0,200, 0,212,0,228,0,251,0,7,1,38,1,45,1,50,1,55,1,60,1,65,1, 70,1,79,1,84,1,88,1,94,1,101,1,107,1,115,1,124,1,145,1,166, @@ -953,14 +953,14 @@ EVAL_ONE_SIZED_STR((char *)expr, 8402); } { - SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,48,46,50,11,0,0,0,1,0,0,10,0,16,0, + SHARED_OK static MZCOMPILED_STRING_FAR unsigned char expr[] = {35,126,7,53,46,49,46,48,46,54,11,0,0,0,1,0,0,10,0,16,0, 29,0,44,0,58,0,78,0,90,0,104,0,118,0,170,0,0,0,103,1,0, 0,69,35,37,98,117,105,108,116,105,110,65,113,117,111,116,101,29,94,2,2, 67,35,37,117,116,105,108,115,11,29,94,2,2,69,35,37,110,101,116,119,111, 114,107,11,29,94,2,2,68,35,37,112,97,114,97,109,122,11,29,94,2,2, 74,35,37,112,108,97,99,101,45,115,116,114,117,99,116,11,29,94,2,2,66, 35,37,98,111,111,116,11,29,94,2,2,68,35,37,101,120,112,111,98,115,11, -29,94,2,2,68,35,37,107,101,114,110,101,108,11,97,36,11,8,240,252,83, +29,94,2,2,68,35,37,107,101,114,110,101,108,11,97,36,11,8,240,132,84, 0,0,100,159,2,3,36,36,159,2,4,36,36,159,2,5,36,36,159,2,6, 36,36,159,2,7,36,36,159,2,8,36,36,159,2,9,36,36,159,2,9,36, 36,16,0,159,36,20,105,159,36,16,1,11,16,0,83,158,42,20,103,145,2, diff --git a/src/racket/src/error.c b/src/racket/src/error.c index e11b936ac9..3f395a8cf5 100644 --- a/src/racket/src/error.c +++ b/src/racket/src/error.c @@ -198,7 +198,8 @@ Scheme_Config *scheme_init_error_escape_proc(Scheme_Config *config) %Q = truncated-to-256 Scheme string %V = scheme_value %D = scheme value to display - %_ = skip + %_ = skip pointer + %- = skip int %L = line number as intptr_t, -1 means no line %e = error number for strerror() @@ -238,6 +239,7 @@ static intptr_t sch_vsprintf(char *s, intptr_t maxlen, const char *msg, va_list break; case 'd': case 'o': + case '-': ints[ip++] = mzVA_ARG(args, int); break; case 'g': @@ -331,6 +333,13 @@ static intptr_t sch_vsprintf(char *s, intptr_t maxlen, const char *msg, va_list tlen = strlen(t); } break; + case '-': + { + ip++; + t = ""; + tlen = 0; + } + break; case 'o': { int d; @@ -838,7 +847,7 @@ void scheme_warning(char *msg, ...) } void scheme_log(Scheme_Logger *logger, int level, int flags, - char *msg, ...) + const char *msg, ...) { GC_CAN_IGNORE va_list args; char *buffer; @@ -859,6 +868,29 @@ void scheme_log(Scheme_Logger *logger, int level, int flags, scheme_log_message(logger, level, buffer, len, NULL); } +void scheme_log_w_data(Scheme_Logger *logger, int level, int flags, + Scheme_Object *data, + const char *msg, ...) +{ + GC_CAN_IGNORE va_list args; + char *buffer; + intptr_t len; + + if (logger) { + if (logger->local_timestamp == *logger->timestamp) + if (logger->want_level < level) + return; + } + + HIDE_FROM_XFORM(va_start(args, msg)); + len = sch_vsprintf(NULL, 0, msg, args, &buffer); + HIDE_FROM_XFORM(va_end(args)); + + buffer[len] = 0; + + scheme_log_message(logger, level, buffer, len, data); +} + int scheme_log_level_p(Scheme_Logger *logger, int level) { if (!logger) { diff --git a/src/racket/src/fun.c b/src/racket/src/fun.c index eebc7ba024..6171345327 100644 --- a/src/racket/src/fun.c +++ b/src/racket/src/fun.c @@ -8527,6 +8527,7 @@ Scheme_Lightweight_Continuation *scheme_capture_lightweight_continuation(Scheme_ if (!runstack_slice) return NULL; lw = (Scheme_Lightweight_Continuation *)storage[0]; + lwc = lw->saved_lwc; lw->runstack_slice = runstack_slice; memcpy(runstack_slice, lw->saved_lwc->runstack_end, len * sizeof(Scheme_Object *)); @@ -8540,7 +8541,6 @@ Scheme_Lightweight_Continuation *scheme_capture_lightweight_continuation(Scheme_ runstack_slice[i] = 0; } - lwc = lw->saved_lwc; len = lwc->cont_mark_stack_end - lwc->cont_mark_stack_start; if (len) { @@ -8586,7 +8586,7 @@ static void *apply_lwc_k() p->ku.k.p1 = NULL; p->ku.k.p2 = NULL; - return scheme_apply_lightweight_continuation(lw, result); + return scheme_apply_lightweight_continuation(lw, result, p->ku.k.i1); } int scheme_can_apply_lightweight_continuation(Scheme_Lightweight_Continuation *lw) @@ -8611,12 +8611,14 @@ int scheme_can_apply_lightweight_continuation(Scheme_Lightweight_Continuation *l } Scheme_Object *scheme_apply_lightweight_continuation(Scheme_Lightweight_Continuation *lw, - Scheme_Object *result) XFORM_SKIP_PROC + Scheme_Object *result, + int result_is_rs_argv) + XFORM_SKIP_PROC { intptr_t len, cm_len, cm_pos_delta, cm_delta, i, cm; Scheme_Cont_Mark *seg; Scheme_Object **rs; - + len = lw->saved_lwc->runstack_start - lw->saved_lwc->runstack_end; if (!scheme_check_runstack(len)) { @@ -8624,6 +8626,7 @@ Scheme_Object *scheme_apply_lightweight_continuation(Scheme_Lightweight_Continua continuation in a future thread. */ scheme_current_thread->ku.k.p1 = lw; scheme_current_thread->ku.k.p2 = result; + scheme_current_thread->ku.k.i1 = result_is_rs_argv; return (Scheme_Object *)scheme_enlarge_runstack(len, apply_lwc_k); } @@ -8662,6 +8665,9 @@ Scheme_Object *scheme_apply_lightweight_continuation(Scheme_Lightweight_Continua } } + if (result_is_rs_argv) + result = (Scheme_Object *)(rs + 2); + return scheme_apply_lightweight_continuation_stack(lw->saved_lwc, lw->stack_slice, result); } diff --git a/src/racket/src/future.c b/src/racket/src/future.c index e813bc4c00..7ad27ab5e3 100644 --- a/src/racket/src/future.c +++ b/src/racket/src/future.c @@ -19,6 +19,7 @@ */ #include "schpriv.h" +#include "schmach.h" static Scheme_Object *future_p(int argc, Scheme_Object *argv[]) { @@ -271,7 +272,7 @@ void scheme_init_futures_per_place() #define LOG_THISCALL #endif -#define LOG_RTCALL_VOID_VOID_3ARGS(f) LOG("(function=%p)", f) +#define LOG_RTCALL_ON_DEMAND(f) LOG("(function=%p)", f) #define LOG_RTCALL_ALLOC(f) LOG("(function=%p)", f) #define LOG_RTCALL_OBJ_INT_POBJ_OBJ(f,a,b,c) LOG4("(function = %p, a=%p, b=%d, c=%p)", f, a, b, c) #define LOG_RTCALL_OBJ_INT_POBJ_VOID(a,b,c) LOG3("(%p, %d, %p)", a, b,c) @@ -311,6 +312,56 @@ static void future_raise_wrong_type_exn(const char *who, #define INITIAL_C_STACK_SIZE 500000 #define FUTURE_RUNSTACK_SIZE 10000 +#define FEVENT_BUFFER_SIZE 512 + +enum { + FEVENT_CREATE, + FEVENT_COMPLETE, + FEVENT_START_WORK, + FEVENT_START_RTONLY_WORK, + FEVENT_END_WORK, + FEVENT_RTCALL_ATOMIC, + FEVENT_HANDLE_RTCALL_ATOMIC, + FEVENT_RTCALL, + FEVENT_HANDLE_RTCALL, + FEVENT_RTCALL_RESULT, + FEVENT_HANDLE_RTCALL_RESULT, + FEVENT_RTCALL_ABORT, + FEVENT_HANDLE_RTCALL_ABORT, + FEVENT_RTCALL_SUSPEND, + FEVENT_TOUCH_PAUSE, + FEVENT_TOUCH_RESUME, + FEVENT_MISSING, + _FEVENT_COUNT_ +}; + +static const char * const fevent_strs[] = { "create", "complete", + "start-work", "start-0-work", "end-work", + "sync", "sync", "block", "block", + "result", "result", "abort", "abort", + "suspend", + "touch-pause", "touch-resume", "missing" }; +static const char * const fevent_long_strs[] = { "created", "completed", + "started work", "started (process 0, only)", "ended work", + "synchronizing with process 0", "synchronizing", + "BLOCKING on process 0", "HANDLING", + "result from process 0", "result determined", + "abort from process 0", "abort determined", + "suspended", + "paused for touch", "resumed for touch", + "events missing" }; + +typedef struct Fevent { + double timestamp; + int what, fid; +} Fevent; + +typedef struct Fevent_Buffer { + Fevent *a; + int pos, overflow; + int i, count; /* used during flush */ +} Fevent_Buffer; + typedef struct Scheme_Future_State { struct Scheme_Future_Thread_State *pool_threads[THREAD_POOL_SIZE]; @@ -333,6 +384,10 @@ typedef struct Scheme_Future_State { int *gc_counter_ptr; int future_threads_created; + + Fevent_Buffer runtime_fevents; + Scheme_Object **fevent_syms; + Scheme_Struct_Type *fevent_prefab; } Scheme_Future_State; typedef struct Scheme_Future_Thread_State { @@ -350,6 +405,10 @@ typedef struct Scheme_Future_Thread_State { uintptr_t gen0_start; uintptr_t gen0_size; uintptr_t gen0_initial_offset; + + int use_fevents1; + Fevent_Buffer fevents1; + Fevent_Buffer fevents2; } Scheme_Future_Thread_State; THREAD_LOCAL_DECL(static Scheme_Future_State *scheme_future_state); @@ -367,7 +426,7 @@ static void end_gc_not_ok(Scheme_Future_Thread_State *fts, Scheme_Object **current_rs); static void *worker_thread_future_loop(void *arg); -static void invoke_rtcall(Scheme_Future_State * volatile fs, future_t * volatile future); +static void invoke_rtcall(Scheme_Future_State * volatile fs, future_t * volatile future, volatile int is_atomic); static future_t *enqueue_future(Scheme_Future_State *fs, future_t *ft);; static future_t *get_pending_future(Scheme_Future_State *fs); static void receive_special_result(future_t *f, Scheme_Object *retval, int clear); @@ -375,6 +434,8 @@ static void send_special_result(future_t *f, Scheme_Object *retval); static Scheme_Object *_apply_future_lw(future_t *ft); static Scheme_Object *apply_future_lw(future_t *ft); static int fsemaphore_ready(Scheme_Object *obj); +static void init_fevent(Fevent_Buffer *b); + READ_ONLY static int cpucount; static void init_cpucount(void); @@ -423,14 +484,9 @@ void scheme_init_futures(Scheme_Env *newenv) 1), newenv); - scheme_add_global_constant( - "future", - scheme_make_prim_w_arity( - scheme_future, - "future", - 1, - 1), - newenv); + p = scheme_make_prim_w_arity(scheme_future, "future", 1, 1); + SCHEME_PRIM_PROC_FLAGS(p) |= SCHEME_PRIM_IS_UNARY_INLINED; + scheme_add_global_constant("future", p, newenv); scheme_add_global_constant( "processor-count", @@ -525,6 +581,8 @@ void futures_init(void) { Scheme_Future_State *fs; void *hand; + Scheme_Object **syms, *sym; + Scheme_Struct_Type *stype; fs = (Scheme_Future_State *)malloc(sizeof(Scheme_Future_State)); memset(fs, 0, sizeof(Scheme_Future_State)); @@ -534,6 +592,8 @@ void futures_init(void) REGISTER_SO(fs->future_queue_end); REGISTER_SO(fs->future_waiting_atomic); REGISTER_SO(fs->future_waiting_lwc); + REGISTER_SO(fs->fevent_syms); + REGISTER_SO(fs->fevent_prefab); REGISTER_SO(jit_future_storage); mzrt_mutex_create(&fs->future_mutex); @@ -546,6 +606,19 @@ void futures_init(void) hand = scheme_get_signal_handle(); fs->signal_handle = hand; + syms = MALLOC_N(Scheme_Object*, _FEVENT_COUNT_); + fs->fevent_syms = syms; + sym = scheme_intern_symbol(fevent_strs[FEVENT_HANDLE_RTCALL_ATOMIC]); + syms[FEVENT_HANDLE_RTCALL_ATOMIC] = sym; + sym = scheme_intern_symbol(fevent_strs[FEVENT_HANDLE_RTCALL]); + syms[FEVENT_HANDLE_RTCALL] = sym; + + sym = scheme_intern_symbol("future-event"); + stype = scheme_lookup_prefab_type(sym, 4); + fs->fevent_prefab = stype; + + init_fevent(&fs->runtime_fevents); + #ifdef MZ_PRECISE_GC register_traversers(); #endif @@ -567,6 +640,10 @@ static void init_future_thread(Scheme_Future_State *fs, int i) fts->gen0_size = 1; + fts->use_fevents1 = 1; + init_fevent(&fts->fevents1); + init_fevent(&fts->fevents2); + params.shared_GC = GC_instance; params.fts = fts; params.fs = fs; @@ -604,6 +681,22 @@ static void init_future_thread(Scheme_Future_State *fs, int i) fs->pool_threads[i] = fts; } +static void check_future_thread_creation(Scheme_Future_State *fs) +{ + if (fs->future_threads_created < (cpucount * 2)) { + int count; + + mzrt_mutex_lock(fs->future_mutex); + count = fs->future_queue_count; + mzrt_mutex_unlock(fs->future_mutex); + + if (count >= fs->future_threads_created) { + init_future_thread(fs, fs->future_threads_created); + fs->future_threads_created++; + } + } +} + static void start_gc_not_ok(Scheme_Future_State *fs) /* must have mutex_lock */ { @@ -621,6 +714,7 @@ static void start_gc_not_ok(Scheme_Future_State *fs) Scheme_Future_Thread_State *fts = scheme_future_thread_state; if (fts->worker_gc_counter != *fs->gc_counter_ptr) { GC_gen0_alloc_page_ptr = 0; /* forces future to ask for memory */ + GC_gen0_alloc_page_end = 0; fts->gen0_start = 0; if (fts->gen0_size > 1) fts->gen0_size >>= 1; @@ -773,34 +867,232 @@ void scheme_future_check_custodians() scheme_future_continue_after_gc(); } +/**********************************************************************/ +/* Future-event logging */ +/**********************************************************************/ + +static double get_future_timestamp() XFORM_SKIP_PROC { +#if 1 + return scheme_get_inexact_milliseconds(); +#else + return 0.0; +#endif +} + +static void init_fevent(Fevent_Buffer *b) XFORM_SKIP_PROC +{ + if (b->a) free(b->a); + + b->pos = 0; + b->overflow = 0; + b->a = (Fevent *)malloc(FEVENT_BUFFER_SIZE * sizeof(Fevent)); + memset(b->a, 0, FEVENT_BUFFER_SIZE * sizeof(Fevent)); +} + +static void record_fevent(int what, int fid) XFORM_SKIP_PROC +/* call with the lock or in the runtime thread */ +{ + Scheme_Future_Thread_State *fts = scheme_future_thread_state; + Fevent_Buffer *b; + + if (fts) { + if (fts->use_fevents1) + b = &fts->fevents1; + else + b = &fts->fevents2; + } else + b = &scheme_future_state->runtime_fevents; + + b->a[b->pos].timestamp = get_future_timestamp(); + b->a[b->pos].what = what; + b->a[b->pos].fid = fid; + + b->pos++; + if (b->pos == FEVENT_BUFFER_SIZE) { + b->overflow = 1; + b->pos = 0; + } +} + +static void init_traversal(Fevent_Buffer *b) +{ + if (b->overflow) { + b->count = FEVENT_BUFFER_SIZE; + b->i = b->pos; + } else { + b->i = 0; + b->count = b->pos; + } +} + +static void end_traversal(Fevent_Buffer *b) +{ + b->overflow = 0; + b->pos = 0; +} + +static void log_future_event(Scheme_Future_State *fs, + const char *msg_str, + const char *extra_str, + int which, + int what, + double timestamp, + int fid) +{ + Scheme_Object *data, *v; + + data = scheme_make_blank_prefab_struct_instance(fs->fevent_prefab); + if (what == FEVENT_MISSING) + ((Scheme_Structure *)data)->slots[0] = scheme_false; + else + ((Scheme_Structure *)data)->slots[0] = scheme_make_integer(fid); + ((Scheme_Structure *)data)->slots[1] = scheme_make_integer((which+1)); + v = fs->fevent_syms[what]; + if (!v) { + v = scheme_intern_symbol(fevent_strs[what]); + fs->fevent_syms[what] = v; + } + ((Scheme_Structure *)data)->slots[2] = v; + v = scheme_make_double(timestamp); + ((Scheme_Structure *)data)->slots[3] = v; + + scheme_log_w_data(scheme_main_logger, SCHEME_LOG_DEBUG, 0, + data, + msg_str, + fid, + which+1, + fevent_long_strs[what], + extra_str, + timestamp); +} + +static void log_overflow_event(Scheme_Future_State *fs, int which, double timestamp) +{ + log_future_event(fs, + "future ??%-, process %d: %s%s; before time: %f", + "", + which, + FEVENT_MISSING, + timestamp, + 0); +} + +static void flush_future_logs(Scheme_Future_State *fs) +{ + Scheme_Future_Thread_State *fts; + double t, min_t; + int i, min_which, min_set; + Fevent_Buffer *b, *min_b; + + if (scheme_log_level_p(scheme_main_logger, SCHEME_LOG_DEBUG)) { + /* Hold lock while swapping buffers: */ + mzrt_mutex_lock(fs->future_mutex); + for (i = 0; i < THREAD_POOL_SIZE; i++) { + fts = fs->pool_threads[i]; + if (fts) { + fts->use_fevents1 = !fts->use_fevents1; + if (fts->use_fevents1) + b = &fts->fevents2; + else + b = &fts->fevents1; + init_traversal(b); + } + } + mzrt_mutex_unlock(fs->future_mutex); + init_traversal(&fs->runtime_fevents); + + if (fs->runtime_fevents.overflow) + log_overflow_event(fs, -1, fs->runtime_fevents.a[fs->runtime_fevents.i].timestamp); + for (i = 0; i < THREAD_POOL_SIZE; i++) { + fts = fs->pool_threads[i]; + if (fts) { + if (fts->use_fevents1) + b = &fts->fevents2; + else + b = &fts->fevents1; + if (b->overflow) + log_overflow_event(fs, i, b->a[b->i].timestamp); + } + } + + while (1) { + min_set = 0; + min_t = 0; + min_b = NULL; + min_which = -1; + if (fs->runtime_fevents.count) { + t = fs->runtime_fevents.a[fs->runtime_fevents.i].timestamp; + if (!min_set || (t < min_t)) { + min_t = t; + min_b = &fs->runtime_fevents; + min_set = 1; + } + } + for (i = 0; i < THREAD_POOL_SIZE; i++) { + fts = fs->pool_threads[i]; + if (fts) { + if (fts->use_fevents1) + b = &fts->fevents2; + else + b = &fts->fevents1; + + if (b->count) { + t = b->a[i].timestamp; + if (!min_set || (t < min_t)) { + min_t = t; + min_b = b; + min_which = i; + min_set = 1; + } + } + } + } + + if (!min_b) + break; + + log_future_event(fs, + "future %d, process %d: %s%s; time: %f", + "", + min_which, + min_b->a[min_b->i].what, + min_b->a[min_b->i].timestamp, + min_b->a[min_b->i].fid); + + --min_b->count; + min_b->i++; + if (min_b->i == FEVENT_BUFFER_SIZE) + min_b->i = 0; + } + + for (i = 0; i < THREAD_POOL_SIZE; i++) { + fts = fs->pool_threads[i]; + if (fts) { + if (fts->use_fevents1) + b = &fts->fevents2; + else + b = &fts->fevents1; + end_traversal(b); + } + } + end_traversal(&fs->runtime_fevents); + } +} + /**********************************************************************/ /* Primitive implementations */ /**********************************************************************/ -Scheme_Object *scheme_future(int argc, Scheme_Object *argv[]) -/* Called in runtime thread */ +static Scheme_Object *make_future(Scheme_Object *lambda) +/* Called in runtime thread --- as atomic on behalf of a future thread + if `lambda' is known to be a thunk */ { Scheme_Future_State *fs = scheme_future_state; - int futureid, count; + int futureid; future_t *ft; Scheme_Native_Closure *nc; Scheme_Native_Closure_Data *ncd; Scheme_Custodian *c; - Scheme_Object *lambda = argv[0]; - double time_of_start; - - /* Input validation */ - scheme_check_proc_arity("future", 0, 0, argc, argv); - - if (fs->future_threads_created < THREAD_POOL_SIZE) { - mzrt_mutex_lock(fs->future_mutex); - count = fs->future_queue_count; - mzrt_mutex_unlock(fs->future_mutex); - if (count >= fs->future_threads_created) { - init_future_thread(fs, fs->future_threads_created); - fs->future_threads_created++; - } - } if (SAME_TYPE(SCHEME_TYPE(lambda), scheme_native_closure_type)) { nc = (Scheme_Native_Closure*)lambda; @@ -814,8 +1106,6 @@ Scheme_Object *scheme_future(int argc, Scheme_Object *argv[]) ft = MALLOC_ONE_TAGGED(future_t); ft->so.type = scheme_future_type; - futureid = ++fs->next_futureid; - ft->id = futureid; ft->orig_lambda = lambda; ft->status = PENDING; @@ -841,25 +1131,68 @@ Scheme_Object *scheme_future(int argc, Scheme_Object *argv[]) } else ft->status = PENDING_OVERSIZE; - if (ft->status != PENDING_OVERSIZE) { - mzrt_mutex_lock(fs->future_mutex); + mzrt_mutex_lock(fs->future_mutex); + futureid = ++fs->next_futureid; + ft->id = futureid; + record_fevent(FEVENT_CREATE, futureid); + if (ft->status != PENDING_OVERSIZE) enqueue_future(fs, ft); - - /* Log the spawn time */ - time_of_start = scheme_get_inexact_milliseconds(); - ft->time_of_start = time_of_start; + mzrt_mutex_unlock(fs->future_mutex); - /* Signal that a future is pending */ - mzrt_sema_post(fs->future_pending_sema); - /* Alert the runtime thread, in case it wants to - run the future itself: */ - scheme_signal_received_at(fs->signal_handle); - mzrt_mutex_unlock(fs->future_mutex); - } + check_future_thread_creation(fs); return (Scheme_Object*)ft; } +static Scheme_Object *do_make_future(int argc, Scheme_Object *argv[]) +{ + scheme_check_proc_arity("future", 0, 0, argc, argv); + return make_future(argv[0]); +} + +Scheme_Object *scheme_future(int argc, Scheme_Object *argv[]) + XFORM_SKIP_PROC /* can be called from future thread */ +{ + Scheme_Future_Thread_State *fts = scheme_future_thread_state; + if (!fts) + return do_make_future(argc, argv); + else { + Scheme_Object *proc = argv[0]; + if (SAME_TYPE(SCHEME_TYPE(proc), scheme_native_closure_type) + && scheme_native_arity_check(proc, 0) + && (((Scheme_Native_Closure *)proc)->code->code != scheme_on_demand_jit_code) + && (((Scheme_Native_Closure *)proc)->code->max_let_depth < FUTURE_RUNSTACK_SIZE * sizeof(void*))) { + /* try to alocate a future in the future thread */ + future_t *ft; + ft = MALLOC_ONE_TAGGED(future_t); + if (ft) { + Scheme_Future_State *fs = scheme_future_state; + + ft->so.type = scheme_future_type; + ft->orig_lambda = proc; + ft->status = PENDING; + ft->cust = scheme_current_thread->current_ft->cust; + ft->code = ((Scheme_Native_Closure *)proc)->code->code; + + mzrt_mutex_lock(fs->future_mutex); + ft->id = ++fs->next_futureid; + record_fevent(FEVENT_CREATE, ft->id); + enqueue_future(fs, ft); + mzrt_mutex_unlock(fs->future_mutex); + + return (Scheme_Object *)ft; + } else { + /* It would be nice to encourage allocation of a page for + the future thread in this case, since it might try to + allocate more futures. */ + return scheme_rtcall_make_future("future", FSRC_OTHER, proc); + } + } else { + return scheme_rtcall_make_future("future", FSRC_OTHER, proc); + } + } +} + void fsemaphore_finalize(void *p, void *data) { fsemaphore_t *sema; @@ -917,8 +1250,6 @@ static void requeue_future_within_lock(future_t *future, Scheme_Future_State *fs if (scheme_custodian_is_available(future->cust)) { future->status = PENDING; enqueue_future(fs, future); - /* Signal that a future is pending */ - mzrt_sema_post(fs->future_pending_sema); } else { /* The future's constodian is shut down, so don't try to run it in a future thread anymore */ @@ -1071,15 +1402,17 @@ Scheme_Object *scheme_fsemaphore_wait(int argc, Scheme_Object **argv) future->lwc = scheme_current_lwc; future->fts = fts; future->arg_p = scheme_current_thread; - future->status = WAITING_FOR_FSEMA; /* Try to capture it locally (on this thread) */ if (GC_gen0_alloc_page_ptr && capture_future_continuation(future, storage)) { /* This will set fts->thread->current_ft to NULL */ + mzrt_mutex_lock(fs->future_mutex); + future->status = WAITING_FOR_FSEMA; } else { /* Can't capture the continuation locally, so ask the runtime thread to do it */ + mzrt_mutex_lock(fs->future_mutex); future->next_waiting_lwc = fs->future_waiting_lwc; fs->future_waiting_lwc = future; future->want_lw = 1; @@ -1094,12 +1427,12 @@ Scheme_Object *scheme_fsemaphore_wait(int argc, Scheme_Object **argv) end_gc_not_ok(fts, fs, MZ_RUNSTACK); mzrt_mutex_unlock(fs->future_mutex); - mzrt_sema_wait(fts->worker_can_continue_sema); + mzrt_sema_wait(fts->worker_can_continue_sema); mzrt_mutex_lock(fs->future_mutex); start_gc_not_ok(fs); - mzrt_mutex_unlock(fs->future_mutex); } + mzrt_mutex_unlock(fs->future_mutex); if (fts->thread->current_ft) { /* Should never get here, cont. capture should remove it */ @@ -1185,7 +1518,9 @@ int future_ready(Scheme_Object *obj) future_t *ft = (future_t*)obj; mzrt_mutex_lock(fs->future_mutex); - if (ft->work_completed || ft->rt_prim || ft->maybe_suspended_lw) { + if ((ft->status != RUNNING) + && (ft->status != WAITING_FOR_FSEMA) + && (ft->status != HANDLING_PRIM)) { ret = 1; } mzrt_mutex_unlock(fs->future_mutex); @@ -1213,13 +1548,12 @@ static void dequeue_future(Scheme_Future_State *fs, future_t *ft) --fs->future_queue_count; } -static void future_in_runtime(future_t * volatile ft) +static void future_in_runtime(future_t * volatile ft, int what) { mz_jmp_buf newbuf, * volatile savebuf; Scheme_Thread *p = scheme_current_thread; Scheme_Object * volatile retval; future_t * volatile old_ft; - double time_of_completion; old_ft = p->current_ft; p->current_ft = ft; @@ -1227,6 +1561,8 @@ static void future_in_runtime(future_t * volatile ft) savebuf = p->error_buf; p->error_buf = &newbuf; + record_fevent(what, ft->id); + if (scheme_setjmp(newbuf)) { ft->no_retval = 1; retval = NULL; @@ -1242,11 +1578,11 @@ static void future_in_runtime(future_t * volatile ft) p->error_buf = savebuf; p->current_ft = old_ft; - time_of_completion = scheme_get_inexact_milliseconds(); - ft->time_of_completion = time_of_completion; - ft->work_completed = 1; ft->retval = retval; ft->status = FINISHED; + record_fevent(FEVENT_COMPLETE, ft->id); + + record_fevent(FEVENT_END_WORK, ft->id); if (!retval) { scheme_longjmp(*savebuf, 1); @@ -1291,21 +1627,23 @@ Scheme_Object *touch(int argc, Scheme_Object *argv[]) || (ft->status == SUSPENDED)) && (!ft->suspended_lw || scheme_can_apply_lightweight_continuation(ft->suspended_lw))) { + int what = FEVENT_START_WORK; if (ft->status == PENDING_OVERSIZE) { - scheme_log(scheme_main_logger, SCHEME_LOG_DEBUG, 0, - "future: oversize procedure deferred to runtime thread"); + what = FEVENT_START_RTONLY_WORK; } else if (ft->status != SUSPENDED) { dequeue_future(fs, ft); } ft->status = RUNNING; mzrt_mutex_unlock(fs->future_mutex); - future_in_runtime(ft); + future_in_runtime(ft, what); retval = ft->retval; receive_special_result(ft, retval, 0); + flush_future_logs(fs); + return retval; } mzrt_mutex_unlock(fs->future_mutex); @@ -1313,56 +1651,61 @@ Scheme_Object *touch(int argc, Scheme_Object *argv[]) /* Spin waiting for primitive calls or a return value from the worker thread */ while (1) { - scheme_block_until(future_ready, NULL, (Scheme_Object*)ft, 0); + if (!future_ready((Scheme_Object *)ft)) { + record_fevent(FEVENT_TOUCH_PAUSE, ft->id); + scheme_block_until(future_ready, NULL, (Scheme_Object*)ft, 0); + record_fevent(FEVENT_TOUCH_RESUME, ft->id); + } + mzrt_mutex_lock(fs->future_mutex); - if (ft->work_completed) + if ((ft->status == RUNNING) + || (ft->status == WAITING_FOR_FSEMA) + || (ft->status == HANDLING_PRIM)) + { + /* someone else got to it first */ + mzrt_mutex_unlock(fs->future_mutex); + } + else if (ft->status == FINISHED) { int id; - double time_of_start; - double time_of_completion; retval = ft->retval; id = ft->id; - time_of_start = ft->time_of_start; - time_of_completion = ft->time_of_completion; mzrt_mutex_unlock(fs->future_mutex); - - /* Log execution time */ - if (scheme_log_level_p(scheme_main_logger, SCHEME_LOG_DEBUG)) { - scheme_log(scheme_main_logger, SCHEME_LOG_DEBUG, 0, - "future: %d finished. start time: %f, finish time: %f (%f ms)", - id, - time_of_start, - time_of_completion, - time_of_completion - time_of_start); - } break; } - else if (ft->rt_prim) + else if (ft->status == WAITING_FOR_PRIM) { /* Invoke the primitive and stash the result. Release the lock so other threads can manipulate the queue while the runtime call executes. */ + ft->status = HANDLING_PRIM; mzrt_mutex_unlock(fs->future_mutex); - LOG2("Invoking primitive %p on behalf of future %d...", ft->rt_prim, ft->id); - invoke_rtcall(fs, ft); + LOG("Invoking primitive on behalf of future %d...", ft->id); + invoke_rtcall(fs, ft, 0); LOG0("done.\n"); } - else if (ft->maybe_suspended_lw && ft->status != WAITING_FOR_FSEMA) + else if (ft->maybe_suspended_lw && (ft->status != WAITING_FOR_FSEMA)) { ft->maybe_suspended_lw = 0; - if (ft->suspended_lw - && scheme_can_apply_lightweight_continuation(ft->suspended_lw) - && prefer_to_apply_future_in_runtime()) { - if (ft->status != SUSPENDED) - dequeue_future(fs, ft); - ft->status = RUNNING; - /* may raise an exception or escape: */ - mzrt_mutex_unlock(fs->future_mutex); - future_in_runtime(ft); + if (ft->suspended_lw) { + if (scheme_can_apply_lightweight_continuation(ft->suspended_lw) + && prefer_to_apply_future_in_runtime()) { + if (ft->status != SUSPENDED) + dequeue_future(fs, ft); + ft->status = RUNNING; + /* may raise an exception or escape: */ + mzrt_mutex_unlock(fs->future_mutex); + future_in_runtime(ft, FEVENT_START_WORK); + } else { + /* Someone needs to handle the future. We're banking on some + future thread eventually picking up the future, which is + not actually guaranteed if they're all busy looping... */ + mzrt_mutex_unlock(fs->future_mutex); + } } else { mzrt_mutex_unlock(fs->future_mutex); } @@ -1379,6 +1722,8 @@ Scheme_Object *touch(int argc, Scheme_Object *argv[]) receive_special_result(ft, retval, 0); + flush_future_logs(fs); + return retval; } @@ -1443,6 +1788,7 @@ void *worker_thread_future_loop(void *arg) Scheme_Closed_Prim *jitcode; future_t *ft; mz_jmp_buf newbuf; + int fid; scheme_future_state = fs; scheme_future_thread_state = fts; @@ -1501,6 +1847,9 @@ void *worker_thread_future_loop(void *arg) if (ft) { LOG0("Got a signal that a future is pending..."); + fid = ft->id; + record_fevent(FEVENT_START_WORK, fid); + /* Work is available for this thread */ ft->status = RUNNING; ft->maybe_suspended_lw = 0; @@ -1517,7 +1866,6 @@ void *worker_thread_future_loop(void *arg) MZ_CONT_MARK_STACK = 0; MZ_CONT_MARK_POS = (MZ_MARK_POS_TYPE)1; - if (ft->suspended_lw) { /* invoke a lightweight continuation */ scheme_current_thread->error_buf = &newbuf; @@ -1526,7 +1874,7 @@ void *worker_thread_future_loop(void *arg) v = NULL; } else { v = _apply_future_lw(ft); - } + } } else { jitcode = ft->code; @@ -1566,17 +1914,15 @@ void *worker_thread_future_loop(void *arg) thread can do something else */ } else { /* Set the return val in the descriptor */ - ft->work_completed = 1; ft->retval = v; - /* Log future completion time */ - ft->time_of_completion = scheme_get_inexact_milliseconds(); - /* In case of multiple values: */ send_special_result(ft, v); /* Update the status */ ft->status = FINISHED; + + record_fevent(FEVENT_COMPLETE, fid); } /* Clear stacks */ @@ -1585,7 +1931,10 @@ void *worker_thread_future_loop(void *arg) if (ft) scheme_signal_received_at(fs->signal_handle); + + record_fevent(FEVENT_END_WORK, fid); } + end_gc_not_ok(fts, fs, NULL); mzrt_mutex_unlock(fs->future_mutex); } @@ -1599,14 +1948,21 @@ static Scheme_Object *_apply_future_lw(future_t *ft) { struct Scheme_Lightweight_Continuation *lw = ft->suspended_lw; Scheme_Object *v; + int result_is_rs_argv; ft->suspended_lw = NULL; v = ft->retval_s; - ft->retval_s = NULL; - receive_special_result(ft, v, 1); - - v = scheme_apply_lightweight_continuation(lw, v); + if (ft->retval_is_rs_argv) { + result_is_rs_argv = 1; + ft->retval_is_rs_argv = 0; + } else { + ft->retval_s = NULL; + receive_special_result(ft, v, 1); + result_is_rs_argv = 0; + } + + v = scheme_apply_lightweight_continuation(lw, v, result_is_rs_argv); if (SAME_OBJ(v, SCHEME_TAIL_CALL_WAITING)) { v = scheme_ts_scheme_force_value_same_mark(v); @@ -1639,7 +1995,10 @@ static int capture_future_continuation(future_t *ft, void **storage) /* 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. */ + allocation fails, the result is 0. + + It also grabs the future-modification lock as needed to modify the + future. */ { Scheme_Lightweight_Continuation *lw; Scheme_Object **arg_S; @@ -1648,13 +2007,11 @@ static int capture_future_continuation(future_t *ft, void **storage) lw = scheme_capture_lightweight_continuation(ft->arg_p, ft->lwc, storage); if (!lw) return 0; - + ft = (future_t *)storage[2]; ft->suspended_lw = lw; ft->maybe_suspended_lw = 1; - if (ft->status != WAITING_FOR_FSEMA) - ft->status = WAITING_FOR_REQUEUE; ft->want_lw = 0; ft->fts->thread->current_ft = NULL; /* tells worker thread that it no longer @@ -1685,25 +2042,34 @@ void scheme_check_future_work() for allocation). */ future_t *ft; Scheme_Future_State *fs = scheme_future_state; + int more = 1; if (!fs) return; - while (1) { + flush_future_logs(fs); + + check_future_thread_creation(fs); + + while (more) { /* Try to get a future waiting on a atomic operation */ mzrt_mutex_lock(fs->future_mutex); ft = fs->future_waiting_atomic; if (ft) { fs->future_waiting_atomic = ft->next_waiting_atomic; ft->next_waiting_atomic = NULL; - } + if ((ft->status == WAITING_FOR_PRIM) && ft->rt_prim_is_atomic) { + ft->status = HANDLING_PRIM; + ft->want_lw = 0; /* we expect to handle it quickly, + so the future thread should just wait */ + } else + ft = NULL; + more = 1; + } else + more = 0; mzrt_mutex_unlock(fs->future_mutex); - if (ft) { - if (ft->rt_prim && ft->rt_prim_is_atomic) { - invoke_rtcall(fs, ft); - } - } else - break; + if (ft) + invoke_rtcall(fs, ft, 1); } while (1) { @@ -1743,31 +2109,17 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, future_t *future; Scheme_Future_State *fs = scheme_future_state; void *storage[3]; - int insist_to_suspend, prefer_to_suspend; + int insist_to_suspend, prefer_to_suspend, fid; /* Fetch the future descriptor for this thread */ future = fts->thread->current_ft; - if (!is_atomic) { - scheme_fill_lwc_end(); - future->lwc = scheme_current_lwc; - future->fts = fts; - } else - future->lwc = NULL; - - /* Set up the arguments for the runtime call - to be picked up by the main rt thread */ - mzrt_mutex_lock(fs->future_mutex); - - future->prim_func = func; - future->rt_prim = 1; - future->rt_prim_is_atomic = is_atomic; + scheme_fill_lwc_end(); + future->lwc = scheme_current_lwc; + future->fts = fts; future->arg_p = scheme_current_thread; - if (is_atomic) { - future->next_waiting_atomic = fs->future_waiting_atomic; - fs->future_waiting_atomic = future; - } + fid = future->id; /* Policy question: When should the future thread suspend the current future? It costs something to suspend and @@ -1788,17 +2140,34 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, } if (prefer_to_suspend - && GC_gen0_alloc_page_ptr + && GC_gen0_alloc_page_ptr && capture_future_continuation(future, storage)) { /* this future thread will suspend handling the future continuation until the result of the blocking call is ready; fts->thread->current_ft was set to NULL */ - } else if (insist_to_suspend) { - /* couldn't capture the continuation locally, so ask - the runtime thread to capture it: */ - future->next_waiting_lwc = fs->future_waiting_lwc; - fs->future_waiting_lwc = future; - future->want_lw = 1; + } + + mzrt_mutex_lock(fs->future_mutex); + + record_fevent(is_atomic ? FEVENT_RTCALL_ATOMIC : FEVENT_RTCALL, fid); + + /* Set up the arguments for the runtime call + to be picked up by the main rt thread */ + future->prim_func = func; + future->rt_prim_is_atomic = is_atomic; + future->status = WAITING_FOR_PRIM; + + if (fts->thread->current_ft) { + if (insist_to_suspend) { + /* couldn't capture the continuation locally, so ask + the runtime thread to capture it: */ + future->next_waiting_lwc = fs->future_waiting_lwc; + fs->future_waiting_lwc = future; + future->want_lw = 1; + } else if (is_atomic) { + future->next_waiting_atomic = fs->future_waiting_atomic; + fs->future_waiting_atomic = future; + } } scheme_signal_received_at(fs->signal_handle); @@ -1806,7 +2175,6 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, if (fts->thread->current_ft) { /* Wait for the signal that the RT call is finished or a lightweight continuation has been captured: */ - future->status = WAITING_FOR_PRIM; future->can_continue_sema = fts->worker_can_continue_sema; end_gc_not_ok(fts, fs, MZ_RUNSTACK); /* we rely on this putting MZ_CONT_MARK_STACK into the thread record */ mzrt_mutex_unlock(fs->future_mutex); @@ -1814,15 +2182,27 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, mzrt_sema_wait(fts->worker_can_continue_sema); mzrt_mutex_lock(fs->future_mutex); - start_gc_not_ok(fs); + start_gc_not_ok(fs); } - - mzrt_mutex_unlock(fs->future_mutex); /* Fetch the future instance again, in case the GC has moved the pointer or the future has been requeued. */ future = fts->thread->current_ft; + if (future) { + if (future->no_retval) { + record_fevent(FEVENT_RTCALL_ABORT, fid); + future->status = FINISHED; + } else { + record_fevent(FEVENT_RTCALL_RESULT, fid); + future->status = RUNNING; + } + } else { + record_fevent(FEVENT_RTCALL_SUSPEND, fid); + } + + mzrt_mutex_unlock(fs->future_mutex); + if (!future) { /* future continuation was requeued */ scheme_future_longjmp(*scheme_current_thread->error_buf, 1); @@ -1850,7 +2230,7 @@ static void future_raise_wrong_type_exn(const char *who, const char *expected_ty future->arg_i3 = argc; future->arg_S4 = argv; - future->time_of_request = scheme_get_inexact_milliseconds(); + future->time_of_request = get_future_timestamp(); future->source_of_request = who; future_do_runtimecall(fts, (void*)scheme_wrong_type, 0); @@ -1863,18 +2243,23 @@ static void future_raise_wrong_type_exn(const char *who, const char *expected_ty future->arg_S4 = NULL; } -void scheme_rtcall_void_void_3args(const char *who, int src_type, prim_void_void_3args_t f) +Scheme_Object **scheme_rtcall_on_demand(const char *who, int src_type, prim_on_demand_t f, Scheme_Object **argv) XFORM_SKIP_PROC /* Called in future thread */ { Scheme_Future_Thread_State *fts = scheme_future_thread_state; future_t *future = fts->thread->current_ft; - future->prim_protocol = SIG_VOID_VOID_3ARGS; + future->prim_protocol = SIG_ON_DEMAND; + + if ((MZ_RUNSTACK + 2) != argv) { + fprintf(stderr, "internal error: expected arguments on runstack"); + abort(); + } future->arg_S0 = MZ_RUNSTACK; - future->time_of_request = scheme_get_inexact_milliseconds(); + future->time_of_request = get_future_timestamp(); future->source_of_request = who; future->source_type = src_type; @@ -1884,6 +2269,9 @@ void scheme_rtcall_void_void_3args(const char *who, int src_type, prim_void_void future = fts->thread->current_ft; future->arg_S0 = NULL; + future->retval_is_rs_argv = 0; + + return MZ_RUNSTACK + 2; } Scheme_Object *scheme_rtcall_make_fsemaphore(const char *who, int src_type, Scheme_Object *ready) @@ -1893,29 +2281,64 @@ Scheme_Object *scheme_rtcall_make_fsemaphore(const char *who, int src_type, Sche Scheme_Object *retval; Scheme_Future_Thread_State *fts = scheme_future_thread_state; future_t *future = fts->thread->current_ft; + int is_atomic; future->prim_protocol = SIG_MAKE_FSEMAPHORE; future->arg_s1 = ready; - future->time_of_request = scheme_get_inexact_milliseconds(); + future->time_of_request = get_future_timestamp(); future->source_of_request = who; future->source_type = src_type; + + /* conservative check for when creation can succeed atomically: */ + if (SCHEME_INT_VAL(ready) + && (SCHEME_INT_VAL(ready) >= 0) + && (SCHEME_INT_VAL(ready) < 1024)) + is_atomic = 1; + else + is_atomic = 0; - future_do_runtimecall(fts, (void*)scheme_make_fsemaphore_inl, 1); + future_do_runtimecall(fts, (void*)scheme_make_fsemaphore_inl, is_atomic); /* Fetch the future again, in case moved by a GC */ future = fts->thread->current_ft; -#ifdef MZ_PRECISE_GC retval = future->retval_s; future->retval_s = NULL; -#else - retval = (Scheme_Object*)future->retval_p; - future->retval_p = NULL; -#endif return retval; } +Scheme_Object *scheme_rtcall_make_future(const char *who, int src_type, Scheme_Object *proc) + XFORM_SKIP_PROC +/* Called in future thread */ +{ + Scheme_Object *retval; + Scheme_Future_Thread_State *fts = scheme_future_thread_state; + future_t *future = fts->thread->current_ft; + int is_atomic = 0; + + if (SAME_TYPE(SCHEME_TYPE(proc), scheme_native_closure_type) + && scheme_native_arity_check(proc, 0)) { + is_atomic = 1; + } + + future->prim_protocol = SIG_FUTURE; + future->arg_s1 = proc; + future->time_of_request = get_future_timestamp(); + future->source_of_request = who; + future->source_type = src_type; + + future_do_runtimecall(fts, (void*)scheme_future, is_atomic); + + /* Fetch the future again, in case moved by a GC */ + future = fts->thread->current_ft; + + retval = future->retval_s; + future->retval_s = NULL; + + return retval; +} + void scheme_rtcall_allocate_values(const char *who, int src_type, int count, Scheme_Thread *t, prim_allocate_values_t f) XFORM_SKIP_PROC @@ -1929,7 +2352,7 @@ void scheme_rtcall_allocate_values(const char *who, int src_type, int count, Sch future->arg_i0 = count; future->arg_s0 = (Scheme_Object *)t; - future->time_of_request = scheme_get_inexact_milliseconds(); + future->time_of_request = get_future_timestamp(); future->source_of_request = who; future->source_type = src_type; @@ -1950,7 +2373,7 @@ uintptr_t scheme_rtcall_alloc(const char *who, int src_type) future_t *future; uintptr_t retval; Scheme_Future_Thread_State *fts = scheme_future_thread_state; - intptr_t align; + intptr_t align, sz; align = GC_alloc_alignment(); @@ -1969,13 +2392,13 @@ uintptr_t scheme_rtcall_alloc(const char *who, int src_type) } } - /* Grow nursery size as intptr_t as we don't trigger a GC */ + /* Grow nursery size as long as we don't trigger a GC */ if (fts->gen0_size < 16) fts->gen0_size <<= 1; while (1) { future = fts->thread->current_ft; - future->time_of_request = scheme_get_inexact_milliseconds(); + future->time_of_request = get_future_timestamp(); future->source_of_request = who; future->source_type = src_type; @@ -1986,6 +2409,7 @@ uintptr_t scheme_rtcall_alloc(const char *who, int src_type) future = fts->thread->current_ft; retval = future->alloc_retval; + sz = future->alloc_sz_retval; future->alloc_retval = 0; if (fts->worker_gc_counter == future->alloc_retval_counter) { @@ -1995,7 +2419,7 @@ uintptr_t scheme_rtcall_alloc(const char *who, int src_type) } } - GC_gen0_alloc_page_end = retval + fts->gen0_size; + GC_gen0_alloc_page_end = retval + sz; return retval; } @@ -2010,7 +2434,7 @@ void scheme_rtcall_new_mark_segment(Scheme_Thread *p) Scheme_Future_Thread_State *fts = scheme_future_thread_state; future = fts->thread->current_ft; - future->time_of_request = scheme_get_inexact_milliseconds(); + future->time_of_request = get_future_timestamp(); future->source_of_request = "[allocate_mark_segment]"; future->source_type = FSRC_OTHER; @@ -2088,7 +2512,7 @@ static void send_special_result(future_t *f, Scheme_Object *retval) /* Does the work of actually invoking a primitive on behalf of a future. This function is always invoked on the main (runtime) thread. */ -static void do_invoke_rtcall(Scheme_Future_State *fs, future_t *future) +static void do_invoke_rtcall(Scheme_Future_State *fs, future_t *future, int is_atomic) /* Called in runtime thread */ { Scheme_Cont_Frame_Data mark_d; @@ -2098,10 +2522,6 @@ static void do_invoke_rtcall(Scheme_Future_State *fs, future_t *future) g_rtcall_count++; #endif - future->rt_prim = 0; - future->want_lw = 0; /* in case we got to the call before we got around - to capturing an LWC */ - if (scheme_log_level_p(scheme_main_logger, SCHEME_LOG_DEBUG)) { const char *src; @@ -2119,11 +2539,16 @@ static void do_invoke_rtcall(Scheme_Future_State *fs, future_t *future) if (src2) src = src2; } - scheme_log(scheme_main_logger, SCHEME_LOG_DEBUG, 0, - "future: %d waiting for runtime at %f: %s", - (intptr_t)future->thread_short_id, - future->time_of_request, - src); + flush_future_logs(fs); + + /* use lg_future_event so we can include `str' in the message: */ + log_future_event(fs, + "future %d, process %d: %s: %s; time: %f", + src, + -1, + (is_atomic ? FEVENT_HANDLE_RTCALL_ATOMIC : FEVENT_HANDLE_RTCALL), + get_future_timestamp(), + future->id); } if ((future->source_type == FSRC_RATOR) @@ -2133,26 +2558,29 @@ static void do_invoke_rtcall(Scheme_Future_State *fs, future_t *future) else need_pop = 0; future->arg_p = NULL; - + switch (future->prim_protocol) { - case SIG_VOID_VOID_3ARGS: + case SIG_ON_DEMAND: { - prim_void_void_3args_t func = (prim_void_void_3args_t)future->prim_func; + prim_on_demand_t func = (prim_on_demand_t)future->prim_func; GC_CAN_IGNORE Scheme_Object **arg_S0 = future->arg_S0; future->arg_S0 = NULL; - func(arg_S0); + func(arg_S0, arg_S0 + 2); + + future->retval_is_rs_argv = 1; break; } #ifdef MZ_PRECISE_GC case SIG_ALLOC: { - uintptr_t ret; - ret = GC_make_jit_nursery_page(future->arg_i0); + uintptr_t ret, sz; + ret = GC_make_jit_nursery_page(future->arg_i0, &sz); future->alloc_retval = ret; + future->alloc_sz_retval = sz; future->alloc_retval_counter = scheme_did_gc_count; break; } @@ -2168,11 +2596,19 @@ static void do_invoke_rtcall(Scheme_Future_State *fs, future_t *future) case SIG_MAKE_FSEMAPHORE: { Scheme_Object *s = future->arg_s1; - future->arg_s0 = NULL; + future->arg_s1 = NULL; s = scheme_make_fsemaphore_inl(s); future->retval_s = s; break; } + case SIG_FUTURE: + { + Scheme_Object *s = future->arg_s1; + future->arg_s1 = NULL; + s = make_future(s); + future->retval_s = s; + break; + } case SIG_ALLOC_VALUES: { prim_allocate_values_t func = (prim_allocate_values_t)future->prim_func; @@ -2193,6 +2629,7 @@ static void do_invoke_rtcall(Scheme_Future_State *fs, future_t *future) future->arg_S4); } # define JIT_TS_LOCALIZE(t, f) GC_CAN_IGNORE t f = future->f +# define ADJUST_RS_ARG(ft, arg_Sx) if (ft->suspended_lw) arg_Sx = scheme_adjust_runstack_argument(ft->suspended_lw, arg_Sx) # include "jit_ts_runtime_glue.c" default: scheme_signal_error("unknown protocol %d", future->prim_protocol); @@ -2209,6 +2646,7 @@ static void do_invoke_rtcall(Scheme_Future_State *fs, future_t *future) } else { /* Signal the waiting worker thread that it can continue running machine code */ + future->want_lw = 0; if (future->can_continue_sema) { mzrt_sema_post(future->can_continue_sema); future->can_continue_sema = NULL; @@ -2217,21 +2655,31 @@ static void do_invoke_rtcall(Scheme_Future_State *fs, future_t *future) mzrt_mutex_unlock(fs->future_mutex); } +typedef Scheme_Object *(*overflow_k_t)(void); + static void *do_invoke_rtcall_k(void) { Scheme_Thread *p = scheme_current_thread; Scheme_Future_State *fs = (Scheme_Future_State *)p->ku.k.p1; future_t *future = (future_t *)p->ku.k.p2; +#ifdef DO_STACK_CHECK + { +# include "mzstkchk.h" + return scheme_handle_stack_overflow((overflow_k_t)do_invoke_rtcall_k); + } +#endif + p->ku.k.p1 = NULL; p->ku.k.p2 = NULL; - do_invoke_rtcall(fs, future); + do_invoke_rtcall(fs, future, p->ku.k.i1); return scheme_void; } -static void invoke_rtcall(Scheme_Future_State * volatile fs, future_t * volatile future) +static void invoke_rtcall(Scheme_Future_State * volatile fs, future_t * volatile future, + volatile int is_atomic) { Scheme_Thread *p = scheme_current_thread; mz_jmp_buf newbuf, * volatile savebuf; @@ -2239,13 +2687,14 @@ static void invoke_rtcall(Scheme_Future_State * volatile fs, future_t * volatile savebuf = p->error_buf; p->error_buf = &newbuf; if (scheme_setjmp(newbuf)) { + record_fevent(FEVENT_HANDLE_RTCALL_ABORT, future->id); mzrt_mutex_lock(fs->future_mutex); future->no_retval = 1; if (future->suspended_lw) { /* Abandon the future */ future->status = FINISHED; - future->work_completed = 1; future->retval = 0; + future->suspended_lw = NULL; mzrt_mutex_unlock(fs->future_mutex); } else { /* Signal the waiting worker thread that it @@ -2253,18 +2702,24 @@ static void invoke_rtcall(Scheme_Future_State * volatile fs, future_t * volatile mzrt_sema_post(future->can_continue_sema); future->can_continue_sema = NULL; mzrt_mutex_unlock(fs->future_mutex); - scheme_longjmp(*savebuf, 1); } + if (is_atomic) { + scheme_log_abort("internal error: failure during atomic"); + abort(); + } + scheme_longjmp(*savebuf, 1); } else { if (future->rt_prim_is_atomic) { - do_invoke_rtcall(fs, future); + do_invoke_rtcall(fs, future, is_atomic); } else { /* call with continuation barrier. */ p->ku.k.p1 = fs; p->ku.k.p2 = future; + p->ku.k.i1 = is_atomic; (void)scheme_top_level_do(do_invoke_rtcall_k, 1); } + record_fevent(FEVENT_HANDLE_RTCALL_RESULT, future->id); } p->error_buf = savebuf; } @@ -2285,7 +2740,10 @@ future_t *enqueue_future(Scheme_Future_State *fs, future_t *ft) if (!fs->future_queue) fs->future_queue = ft; fs->future_queue_count++; - + + /* Signal that a future is pending */ + mzrt_sema_post(fs->future_pending_sema); + return ft; } diff --git a/src/racket/src/future.h b/src/racket/src/future.h index 61a50d6a8c..bbcdcc666d 100644 --- a/src/racket/src/future.h +++ b/src/racket/src/future.h @@ -24,7 +24,7 @@ int scheme_make_prim_w_arity(prim_t func, char *name, int arg1, int arg2); #include -typedef void (*prim_void_void_3args_t)(Scheme_Object **); +typedef Scheme_Object **(*prim_on_demand_t)(Scheme_Object **, 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_obj_t)(int, Scheme_Object**, Scheme_Object*); @@ -36,7 +36,7 @@ typedef void (*prim_allocate_values_t)(int, Scheme_Thread *); #define WAITING_FOR_PRIM 2 #define FINISHED 3 #define PENDING_OVERSIZE 4 -#define WAITING_FOR_REQUEUE 5 +#define HANDLING_PRIM 5 #define WAITING_FOR_FSEMA 6 #define SUSPENDED 7 @@ -61,7 +61,6 @@ typedef struct future_t { thread if this custodian is shut down */ /* Runtime call stuff */ - int rt_prim; /* flag to indicate waiting for a prim call */ int want_lw; /* flag to indicate waiting for lw capture */ int rt_prim_is_atomic; double time_of_request; @@ -69,12 +68,9 @@ typedef struct future_t { int source_type; uintptr_t alloc_retval; + uintptr_t alloc_sz_retval; int alloc_retval_counter; - /* For logging the future's execution time */ - double time_of_start; - double time_of_completion; - void *prim_func; int prim_protocol; Scheme_Object *arg_s0; @@ -109,7 +105,7 @@ typedef struct future_t { Scheme_Object *retval_s; void *retval_p; /* use only with conservative GC */ MZ_MARK_STACK_TYPE retval_m; - int no_retval; + int no_retval, retval_is_rs_argv; Scheme_Object **multiple_array; int multiple_count; @@ -142,12 +138,13 @@ typedef struct fsemaphore_t { /* Primitive instrumentation stuff */ /* Signature flags for primitive invocations */ -#define SIG_VOID_VOID_3ARGS 1 +#define SIG_ON_DEMAND 1 #define SIG_ALLOC 2 #define SIG_ALLOC_MARK_SEGMENT 3 #define SIG_ALLOC_VALUES 4 #define SIG_MAKE_FSEMAPHORE 5 -#define SIG_WRONG_TYPE_EXN 200 +#define SIG_FUTURE 6 +#define SIG_WRONG_TYPE_EXN 7 # include "jit_ts_protos.h" @@ -163,13 +160,14 @@ extern Scheme_Object *scheme_ts_scheme_force_value_same_mark(Scheme_Object *v); /*GDB_BREAK;*/ \ } -extern void scheme_rtcall_void_void_3args(const char *who, int src_type, prim_void_void_3args_t f); +extern Scheme_Object **scheme_rtcall_on_demand(const char *who, int src_type, prim_on_demand_t f, Scheme_Object **argv); extern uintptr_t scheme_rtcall_alloc(const char *who, int src_type); extern void scheme_rtcall_new_mark_segment(Scheme_Thread *p); extern void scheme_rtcall_allocate_values(const char *who, int src_type, int count, Scheme_Thread *t, prim_allocate_values_t f); extern Scheme_Object *scheme_rtcall_make_fsemaphore(const char *who, int src_type, Scheme_Object *ready); -#else +extern Scheme_Object *scheme_rtcall_make_future(const char *who, int src_type, Scheme_Object *proc); +#else #define IS_WORKER_THREAD 0 #define ASSERT_CORRECT_THREAD diff --git a/src/racket/src/gen-jit-ts.rkt b/src/racket/src/gen-jit-ts.rkt index fee9082784..96352383b4 100644 --- a/src/racket/src/gen-jit-ts.rkt +++ b/src/racket/src/gen-jit-ts.rkt @@ -87,7 +87,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_@|ts|; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -133,6 +133,12 @@ #:when (is-pointer-type? t)) @string-append{future->arg_@|(string t)|@|(number->string i)| = NULL;}) " ") + @(string-join + (for/list ([t (in-string (type->arg-string t))] + [i (in-naturals)] + #:when (eq? t #\S)) + @string-append{ADJUST_RS_ARG(future, arg_@|(string t)|@|(number->string i)|);}) + " ") @(if (string=? result-type "void") "" "retval = ") f(@(string-join (for/list ([t (in-string (type->arg-string t))] @@ -146,7 +152,7 @@ }) (newline)) -(define proto-counter 5) +(define proto-counter 10) (define (gen-protos t) (define-values (arg-types result-type) (parse-type t)) diff --git a/src/racket/src/jit.c b/src/racket/src/jit.c index fedef240d9..26eb7c871b 100644 --- a/src/racket/src/jit.c +++ b/src/racket/src/jit.c @@ -3300,22 +3300,23 @@ void scheme_on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Schem on_demand_generate_lambda(nc, argc, argv); } -void scheme_on_demand_with_args(Scheme_Object **in_argv) +Scheme_Object **scheme_on_demand_with_args(Scheme_Object **in_argv, Scheme_Object **argv) { /* On runstack: closure (nearest), argc, argv (deepest) */ - Scheme_Object *c, *argc, **argv; + Scheme_Object *c, *argc; c = in_argv[0]; argc = in_argv[1]; - argv = (Scheme_Object **)in_argv[2]; if (((Scheme_Native_Closure *)c)->code->code == scheme_on_demand_jit_code) scheme_on_demand_generate_lambda((Scheme_Native_Closure *)c, SCHEME_INT_VAL(argc), argv); + + return argv; } -void scheme_on_demand() +Scheme_Object **scheme_on_demand(Scheme_Object **rs) { - scheme_on_demand_with_args(MZ_RUNSTACK); + return scheme_on_demand_with_args(MZ_RUNSTACK, rs); } static Scheme_Native_Closure_Data *create_native_lambda(Scheme_Closure_Data *data, int clear_code_after_jit, @@ -3622,12 +3623,14 @@ static void generate_case_lambda(Scheme_Case_Lambda *c, Scheme_Native_Closure_Da /* native arity queries */ /*========================================================================*/ -static int lambda_has_been_jitted(Scheme_Native_Closure_Data *ndata) +XFORM_NONGCING static int lambda_has_been_jitted(Scheme_Native_Closure_Data *ndata) +/* called by scheme_native_arity_check(), which is not XFORMed */ { return (ndata->code != scheme_on_demand_jit_code); } int scheme_native_arity_check(Scheme_Object *closure, int argc) + XFORM_SKIP_PROC /* called in a future thread for `future' argument arity check */ { int cnt; @@ -3652,10 +3655,19 @@ int scheme_native_arity_check(Scheme_Object *closure, int argc) } if (!lambda_has_been_jitted(((Scheme_Native_Closure *)closure)->code)) { - Scheme_Closure c; - c.so.type = scheme_closure_type; - c.code = ((Scheme_Native_Closure *)closure)->code->u2.orig_code; - return SCHEME_TRUEP(scheme_get_or_check_arity((Scheme_Object *)&c, argc)); + Scheme_Closure_Data *data = ((Scheme_Native_Closure *)closure)->code->u2.orig_code; + int mina, maxa; + mina = maxa = data->num_params; + if (SCHEME_CLOSURE_DATA_FLAGS(data) & CLOS_HAS_REST) { + if (mina) + --mina; + maxa = -1; + } + if (argc < mina) + return 0; + if ((maxa > -1) && (argc > maxa)) + return 0; + return 1; } return sjc.check_arity_code(closure, argc + 1, 0); diff --git a/src/racket/src/jit.h b/src/racket/src/jit.h index 807e9014f1..65b78ee9a0 100644 --- a/src/racket/src/jit.h +++ b/src/racket/src/jit.h @@ -1180,8 +1180,8 @@ int scheme_generate_unboxed(Scheme_Object *obj, mz_jit_state *jitter, int inline int scheme_generate_non_tail_mark_pos_prefix(mz_jit_state *jitter); void scheme_generate_non_tail_mark_pos_suffix(mz_jit_state *jitter); -void scheme_on_demand(); -void scheme_on_demand_with_args(Scheme_Object **in_argv); +Scheme_Object **scheme_on_demand(Scheme_Object **argv); +Scheme_Object **scheme_on_demand_with_args(Scheme_Object **in_argv, Scheme_Object **argv); void scheme_prepare_branch_jump(mz_jit_state *jitter, Branch_Info *for_branch); void scheme_branch_for_true(mz_jit_state *jitter, Branch_Info *for_branch); diff --git a/src/racket/src/jit_ts_future_glue.c b/src/racket/src/jit_ts_future_glue.c index 724e836262..c6eb7dec4f 100644 --- a/src/racket/src/jit_ts_future_glue.c +++ b/src/racket/src/jit_ts_future_glue.c @@ -9,7 +9,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_siS_s; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -35,7 +35,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_iSs_s; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -61,7 +61,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_s_s; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -85,7 +85,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_n_s; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -109,7 +109,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG__s; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -133,7 +133,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_ss_s; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -158,7 +158,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_tt_s; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -183,7 +183,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_ss_m; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -208,7 +208,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_Sl_s; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -233,7 +233,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_l_s; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -257,7 +257,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_bsi_v; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -283,7 +283,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_iiS_v; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -309,7 +309,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_ss_v; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -334,7 +334,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_b_v; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -358,7 +358,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_sl_s; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -383,7 +383,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_iS_s; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -408,7 +408,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_S_s; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -432,7 +432,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_s_v; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -456,7 +456,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_iSi_s; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -482,7 +482,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_siS_v; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -508,7 +508,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_z_p; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -532,7 +532,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_si_s; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; @@ -557,7 +557,7 @@ future = fts->thread->current_ft; future->prim_protocol = SIG_sis_v; future->prim_func = f; - tm = scheme_get_inexact_milliseconds(); + tm = get_future_timestamp(); future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; diff --git a/src/racket/src/jit_ts_protos.h b/src/racket/src/jit_ts_protos.h index b64e0711a7..b031b7f4b9 100644 --- a/src/racket/src/jit_ts_protos.h +++ b/src/racket/src/jit_ts_protos.h @@ -1,69 +1,69 @@ -#define SIG_iSs_s 6 -typedef Scheme_Object* (*prim_iSs_s)(int, Scheme_Object**, Scheme_Object*); -Scheme_Object* scheme_rtcall_iSs_s(const char *who, int src_type, prim_iSs_s f, int g142, Scheme_Object** g143, Scheme_Object* g144); -#define SIG_s_s 7 -typedef Scheme_Object* (*prim_s_s)(Scheme_Object*); -Scheme_Object* scheme_rtcall_s_s(const char *who, int src_type, prim_s_s f, Scheme_Object* g145); -#define SIG_n_s 8 -typedef Scheme_Object* (*prim_n_s)(Scheme_Native_Closure_Data*); -Scheme_Object* scheme_rtcall_n_s(const char *who, int src_type, prim_n_s f, Scheme_Native_Closure_Data* g146); -#define SIG__s 9 -typedef Scheme_Object* (*prim__s)(); -Scheme_Object* scheme_rtcall__s(const char *who, int src_type, prim__s f ); -#define SIG_ss_s 10 -typedef Scheme_Object* (*prim_ss_s)(Scheme_Object*, Scheme_Object*); -Scheme_Object* scheme_rtcall_ss_s(const char *who, int src_type, prim_ss_s f, Scheme_Object* g147, Scheme_Object* g148); -#define SIG_tt_s 11 -typedef Scheme_Object* (*prim_tt_s)(const Scheme_Object*, const Scheme_Object*); -Scheme_Object* scheme_rtcall_tt_s(const char *who, int src_type, prim_tt_s f, const Scheme_Object* g149, const Scheme_Object* g150); -#define SIG_ss_m 12 -typedef MZ_MARK_STACK_TYPE (*prim_ss_m)(Scheme_Object*, Scheme_Object*); -MZ_MARK_STACK_TYPE scheme_rtcall_ss_m(const char *who, int src_type, prim_ss_m f, Scheme_Object* g151, Scheme_Object* g152); -#define SIG_Sl_s 13 -typedef Scheme_Object* (*prim_Sl_s)(Scheme_Object**, intptr_t); -Scheme_Object* scheme_rtcall_Sl_s(const char *who, int src_type, prim_Sl_s f, Scheme_Object** g153, intptr_t g154); -#define SIG_l_s 14 -typedef Scheme_Object* (*prim_l_s)(intptr_t); -Scheme_Object* scheme_rtcall_l_s(const char *who, int src_type, prim_l_s f, intptr_t g155); -#define SIG_bsi_v 15 -typedef void (*prim_bsi_v)(Scheme_Bucket*, Scheme_Object*, int); -void scheme_rtcall_bsi_v(const char *who, int src_type, prim_bsi_v f, Scheme_Bucket* g156, Scheme_Object* g157, int g158); -#define SIG_iiS_v 16 -typedef void (*prim_iiS_v)(int, int, Scheme_Object**); -void scheme_rtcall_iiS_v(const char *who, int src_type, prim_iiS_v f, int g159, int g160, Scheme_Object** g161); -#define SIG_ss_v 17 -typedef void (*prim_ss_v)(Scheme_Object*, Scheme_Object*); -void scheme_rtcall_ss_v(const char *who, int src_type, prim_ss_v f, Scheme_Object* g162, Scheme_Object* g163); -#define SIG_b_v 18 -typedef void (*prim_b_v)(Scheme_Bucket*); -void scheme_rtcall_b_v(const char *who, int src_type, prim_b_v f, Scheme_Bucket* g164); -#define SIG_sl_s 19 -typedef Scheme_Object* (*prim_sl_s)(Scheme_Object*, intptr_t); -Scheme_Object* scheme_rtcall_sl_s(const char *who, int src_type, prim_sl_s f, Scheme_Object* g165, intptr_t g166); -#define SIG_iS_s 20 -typedef Scheme_Object* (*prim_iS_s)(int, Scheme_Object**); -Scheme_Object* scheme_rtcall_iS_s(const char *who, int src_type, prim_iS_s f, int g167, Scheme_Object** g168); -#define SIG_S_s 21 -typedef Scheme_Object* (*prim_S_s)(Scheme_Object**); -Scheme_Object* scheme_rtcall_S_s(const char *who, int src_type, prim_S_s f, Scheme_Object** g169); -#define SIG_s_v 22 -typedef void (*prim_s_v)(Scheme_Object*); -void scheme_rtcall_s_v(const char *who, int src_type, prim_s_v f, Scheme_Object* g170); -#define SIG_iSi_s 23 -typedef Scheme_Object* (*prim_iSi_s)(int, Scheme_Object**, int); -Scheme_Object* scheme_rtcall_iSi_s(const char *who, int src_type, prim_iSi_s f, int g171, Scheme_Object** g172, int g173); -#define SIG_siS_v 24 -typedef void (*prim_siS_v)(Scheme_Object*, int, Scheme_Object**); -void scheme_rtcall_siS_v(const char *who, int src_type, prim_siS_v f, Scheme_Object* g174, int g175, Scheme_Object** g176); -#define SIG_z_p 25 -typedef void* (*prim_z_p)(size_t); -void* scheme_rtcall_z_p(const char *who, int src_type, prim_z_p f, size_t g177); -#define SIG_si_s 26 -typedef Scheme_Object* (*prim_si_s)(Scheme_Object*, int); -Scheme_Object* scheme_rtcall_si_s(const char *who, int src_type, prim_si_s f, Scheme_Object* g178, int g179); -#define SIG_sis_v 27 -typedef void (*prim_sis_v)(Scheme_Object*, int, Scheme_Object*); -void scheme_rtcall_sis_v(const char *who, int src_type, prim_sis_v f, Scheme_Object* g180, int g181, Scheme_Object* g182); -#define SIG_siS_s 28 +#define SIG_siS_s 10 typedef Scheme_Object* (*prim_siS_s)(Scheme_Object*, int, Scheme_Object**); Scheme_Object* scheme_rtcall_siS_s(const char *who, int src_type, prim_siS_s f, Scheme_Object* g139, int g140, Scheme_Object** g141); +#define SIG_iSs_s 11 +typedef Scheme_Object* (*prim_iSs_s)(int, Scheme_Object**, Scheme_Object*); +Scheme_Object* scheme_rtcall_iSs_s(const char *who, int src_type, prim_iSs_s f, int g142, Scheme_Object** g143, Scheme_Object* g144); +#define SIG_s_s 12 +typedef Scheme_Object* (*prim_s_s)(Scheme_Object*); +Scheme_Object* scheme_rtcall_s_s(const char *who, int src_type, prim_s_s f, Scheme_Object* g145); +#define SIG_n_s 13 +typedef Scheme_Object* (*prim_n_s)(Scheme_Native_Closure_Data*); +Scheme_Object* scheme_rtcall_n_s(const char *who, int src_type, prim_n_s f, Scheme_Native_Closure_Data* g146); +#define SIG__s 14 +typedef Scheme_Object* (*prim__s)(); +Scheme_Object* scheme_rtcall__s(const char *who, int src_type, prim__s f ); +#define SIG_ss_s 15 +typedef Scheme_Object* (*prim_ss_s)(Scheme_Object*, Scheme_Object*); +Scheme_Object* scheme_rtcall_ss_s(const char *who, int src_type, prim_ss_s f, Scheme_Object* g147, Scheme_Object* g148); +#define SIG_tt_s 16 +typedef Scheme_Object* (*prim_tt_s)(const Scheme_Object*, const Scheme_Object*); +Scheme_Object* scheme_rtcall_tt_s(const char *who, int src_type, prim_tt_s f, const Scheme_Object* g149, const Scheme_Object* g150); +#define SIG_ss_m 17 +typedef MZ_MARK_STACK_TYPE (*prim_ss_m)(Scheme_Object*, Scheme_Object*); +MZ_MARK_STACK_TYPE scheme_rtcall_ss_m(const char *who, int src_type, prim_ss_m f, Scheme_Object* g151, Scheme_Object* g152); +#define SIG_Sl_s 18 +typedef Scheme_Object* (*prim_Sl_s)(Scheme_Object**, intptr_t); +Scheme_Object* scheme_rtcall_Sl_s(const char *who, int src_type, prim_Sl_s f, Scheme_Object** g153, intptr_t g154); +#define SIG_l_s 19 +typedef Scheme_Object* (*prim_l_s)(intptr_t); +Scheme_Object* scheme_rtcall_l_s(const char *who, int src_type, prim_l_s f, intptr_t g155); +#define SIG_bsi_v 20 +typedef void (*prim_bsi_v)(Scheme_Bucket*, Scheme_Object*, int); +void scheme_rtcall_bsi_v(const char *who, int src_type, prim_bsi_v f, Scheme_Bucket* g156, Scheme_Object* g157, int g158); +#define SIG_iiS_v 21 +typedef void (*prim_iiS_v)(int, int, Scheme_Object**); +void scheme_rtcall_iiS_v(const char *who, int src_type, prim_iiS_v f, int g159, int g160, Scheme_Object** g161); +#define SIG_ss_v 22 +typedef void (*prim_ss_v)(Scheme_Object*, Scheme_Object*); +void scheme_rtcall_ss_v(const char *who, int src_type, prim_ss_v f, Scheme_Object* g162, Scheme_Object* g163); +#define SIG_b_v 23 +typedef void (*prim_b_v)(Scheme_Bucket*); +void scheme_rtcall_b_v(const char *who, int src_type, prim_b_v f, Scheme_Bucket* g164); +#define SIG_sl_s 24 +typedef Scheme_Object* (*prim_sl_s)(Scheme_Object*, intptr_t); +Scheme_Object* scheme_rtcall_sl_s(const char *who, int src_type, prim_sl_s f, Scheme_Object* g165, intptr_t g166); +#define SIG_iS_s 25 +typedef Scheme_Object* (*prim_iS_s)(int, Scheme_Object**); +Scheme_Object* scheme_rtcall_iS_s(const char *who, int src_type, prim_iS_s f, int g167, Scheme_Object** g168); +#define SIG_S_s 26 +typedef Scheme_Object* (*prim_S_s)(Scheme_Object**); +Scheme_Object* scheme_rtcall_S_s(const char *who, int src_type, prim_S_s f, Scheme_Object** g169); +#define SIG_s_v 27 +typedef void (*prim_s_v)(Scheme_Object*); +void scheme_rtcall_s_v(const char *who, int src_type, prim_s_v f, Scheme_Object* g170); +#define SIG_iSi_s 28 +typedef Scheme_Object* (*prim_iSi_s)(int, Scheme_Object**, int); +Scheme_Object* scheme_rtcall_iSi_s(const char *who, int src_type, prim_iSi_s f, int g171, Scheme_Object** g172, int g173); +#define SIG_siS_v 29 +typedef void (*prim_siS_v)(Scheme_Object*, int, Scheme_Object**); +void scheme_rtcall_siS_v(const char *who, int src_type, prim_siS_v f, Scheme_Object* g174, int g175, Scheme_Object** g176); +#define SIG_z_p 30 +typedef void* (*prim_z_p)(size_t); +void* scheme_rtcall_z_p(const char *who, int src_type, prim_z_p f, size_t g177); +#define SIG_si_s 31 +typedef Scheme_Object* (*prim_si_s)(Scheme_Object*, int); +Scheme_Object* scheme_rtcall_si_s(const char *who, int src_type, prim_si_s f, Scheme_Object* g178, int g179); +#define SIG_sis_v 32 +typedef void (*prim_sis_v)(Scheme_Object*, int, Scheme_Object*); +void scheme_rtcall_sis_v(const char *who, int src_type, prim_sis_v f, Scheme_Object* g180, int g181, Scheme_Object* g182); diff --git a/src/racket/src/jit_ts_runtime_glue.c b/src/racket/src/jit_ts_runtime_glue.c index cc56e5031b..461ddaba84 100644 --- a/src/racket/src/jit_ts_runtime_glue.c +++ b/src/racket/src/jit_ts_runtime_glue.c @@ -5,6 +5,7 @@ case SIG_siS_s: JIT_TS_LOCALIZE(Scheme_Object*, arg_s0); JIT_TS_LOCALIZE(int, arg_i1); JIT_TS_LOCALIZE(Scheme_Object**, arg_S2); future->arg_s0 = NULL; future->arg_S2 = NULL; + ADJUST_RS_ARG(future, arg_S2); retval = f(arg_s0, arg_i1, arg_S2); future->retval_s = retval; @@ -18,6 +19,7 @@ case SIG_iSs_s: JIT_TS_LOCALIZE(int, arg_i0); JIT_TS_LOCALIZE(Scheme_Object**, arg_S1); JIT_TS_LOCALIZE(Scheme_Object*, arg_s2); future->arg_S1 = NULL; future->arg_s2 = NULL; + ADJUST_RS_ARG(future, arg_S1); retval = f(arg_i0, arg_S1, arg_s2); future->retval_s = retval; @@ -31,6 +33,7 @@ case SIG_s_s: JIT_TS_LOCALIZE(Scheme_Object*, arg_s0); receive_special_result(future, future->arg_s0, 1); future->arg_s0 = NULL; + retval = f(arg_s0); future->retval_s = retval; @@ -44,6 +47,7 @@ case SIG_n_s: JIT_TS_LOCALIZE(Scheme_Native_Closure_Data*, arg_n0); future->arg_n0 = NULL; + retval = f(arg_n0); future->retval_s = retval; @@ -57,6 +61,7 @@ case SIG__s: + retval = f(); future->retval_s = retval; @@ -70,6 +75,7 @@ case SIG_ss_s: JIT_TS_LOCALIZE(Scheme_Object*, arg_s0); JIT_TS_LOCALIZE(Scheme_Object*, arg_s1); future->arg_s0 = NULL; future->arg_s1 = NULL; + retval = f(arg_s0, arg_s1); future->retval_s = retval; @@ -83,6 +89,7 @@ case SIG_tt_s: JIT_TS_LOCALIZE(const Scheme_Object*, arg_t0); JIT_TS_LOCALIZE(const Scheme_Object*, arg_t1); future->arg_t0 = NULL; future->arg_t1 = NULL; + retval = f(arg_t0, arg_t1); future->retval_s = retval; @@ -96,6 +103,7 @@ case SIG_ss_m: JIT_TS_LOCALIZE(Scheme_Object*, arg_s0); JIT_TS_LOCALIZE(Scheme_Object*, arg_s1); future->arg_s0 = NULL; future->arg_s1 = NULL; + retval = f(arg_s0, arg_s1); future->retval_m = retval; @@ -109,6 +117,7 @@ case SIG_Sl_s: JIT_TS_LOCALIZE(Scheme_Object**, arg_S0); JIT_TS_LOCALIZE(intptr_t, arg_l1); future->arg_S0 = NULL; + ADJUST_RS_ARG(future, arg_S0); retval = f(arg_S0, arg_l1); future->retval_s = retval; @@ -122,6 +131,7 @@ case SIG_l_s: JIT_TS_LOCALIZE(intptr_t, arg_l0); + retval = f(arg_l0); future->retval_s = retval; @@ -136,6 +146,7 @@ case SIG_bsi_v: future->arg_b0 = NULL; future->arg_s1 = NULL; + f(arg_b0, arg_s1, arg_i2); @@ -148,6 +159,7 @@ case SIG_iiS_v: JIT_TS_LOCALIZE(int, arg_i0); JIT_TS_LOCALIZE(int, arg_i1); JIT_TS_LOCALIZE(Scheme_Object**, arg_S2); future->arg_S2 = NULL; + ADJUST_RS_ARG(future, arg_S2); f(arg_i0, arg_i1, arg_S2); @@ -162,6 +174,7 @@ case SIG_ss_v: future->arg_s0 = NULL; future->arg_s1 = NULL; + f(arg_s0, arg_s1); @@ -175,6 +188,7 @@ case SIG_b_v: future->arg_b0 = NULL; + f(arg_b0); @@ -187,6 +201,7 @@ case SIG_sl_s: JIT_TS_LOCALIZE(Scheme_Object*, arg_s0); JIT_TS_LOCALIZE(intptr_t, arg_l1); future->arg_s0 = NULL; + retval = f(arg_s0, arg_l1); future->retval_s = retval; @@ -200,6 +215,7 @@ case SIG_iS_s: JIT_TS_LOCALIZE(int, arg_i0); JIT_TS_LOCALIZE(Scheme_Object**, arg_S1); future->arg_S1 = NULL; + ADJUST_RS_ARG(future, arg_S1); retval = f(arg_i0, arg_S1); future->retval_s = retval; @@ -213,6 +229,7 @@ case SIG_S_s: JIT_TS_LOCALIZE(Scheme_Object**, arg_S0); future->arg_S0 = NULL; + ADJUST_RS_ARG(future, arg_S0); retval = f(arg_S0); future->retval_s = retval; @@ -227,6 +244,7 @@ case SIG_s_v: receive_special_result(future, future->arg_s0, 1); future->arg_s0 = NULL; + f(arg_s0); @@ -239,6 +257,7 @@ case SIG_iSi_s: JIT_TS_LOCALIZE(int, arg_i0); JIT_TS_LOCALIZE(Scheme_Object**, arg_S1); JIT_TS_LOCALIZE(int, arg_i2); future->arg_S1 = NULL; + ADJUST_RS_ARG(future, arg_S1); retval = f(arg_i0, arg_S1, arg_i2); future->retval_s = retval; @@ -252,6 +271,7 @@ case SIG_siS_v: JIT_TS_LOCALIZE(Scheme_Object*, arg_s0); JIT_TS_LOCALIZE(int, arg_i1); JIT_TS_LOCALIZE(Scheme_Object**, arg_S2); future->arg_s0 = NULL; future->arg_S2 = NULL; + ADJUST_RS_ARG(future, arg_S2); f(arg_s0, arg_i1, arg_S2); @@ -265,6 +285,7 @@ case SIG_z_p: JIT_TS_LOCALIZE(size_t, arg_z0); + retval = f(arg_z0); future->retval_p = retval; @@ -278,6 +299,7 @@ case SIG_si_s: JIT_TS_LOCALIZE(Scheme_Object*, arg_s0); JIT_TS_LOCALIZE(int, arg_i1); future->arg_s0 = NULL; + retval = f(arg_s0, arg_i1); future->retval_s = retval; @@ -292,6 +314,7 @@ case SIG_sis_v: future->arg_s0 = NULL; future->arg_s2 = NULL; + f(arg_s0, arg_i1, arg_s2); diff --git a/src/racket/src/jitalloc.c b/src/racket/src/jitalloc.c index 444ca5586c..8181f0536b 100644 --- a/src/racket/src/jitalloc.c +++ b/src/racket/src/jitalloc.c @@ -46,7 +46,7 @@ THREAD_LOCAL_DECL(double scheme_jit_save_fp); static void *prepare_retry_alloc(void *p, void *p2) { - /* Alocate enough to trigger a new page */ + /* Allocate enough to trigger a new page */ intptr_t avail, algn; algn = GC_alloc_alignment(); @@ -76,7 +76,7 @@ static void *ts_prepare_retry_alloc(void *p, void *p2) XFORM_SKIP_PROC jit_future_storage[0] = p; jit_future_storage[1] = p2; - ret = scheme_rtcall_alloc("[acquire_gc_page]", FSRC_OTHER); + ret = scheme_rtcall_alloc("[allocate memory]", FSRC_OTHER); GC_gen0_alloc_page_ptr = ret; retry_alloc_r1 = jit_future_storage[1]; p = jit_future_storage[0]; diff --git a/src/racket/src/jitcall.c b/src/racket/src/jitcall.c index 07fd0bfe63..fbe44aa48d 100644 --- a/src/racket/src/jitcall.c +++ b/src/racket/src/jitcall.c @@ -737,7 +737,7 @@ int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direc if (need_set_rs) { JIT_UPDATE_THREAD_RSPTR(); } - mz_prepare_direct_prim(3); + mz_prepare_direct_prim(3); jit_pusharg_p(JIT_V1); CHECK_LIMIT(); if (num_rands < 0) { jit_movr_p(JIT_V1, JIT_R0); } /* save argc to manually pop runstack */ diff --git a/src/racket/src/jitcommon.c b/src/racket/src/jitcommon.c index 93df07e0ef..69c722ed0a 100644 --- a/src/racket/src/jitcommon.c +++ b/src/racket/src/jitcommon.c @@ -140,12 +140,12 @@ static void ts_allocate_values(int count, Scheme_Thread *p) XFORM_SKIP_PROC #include "jit_ts.c" #ifdef MZ_USE_FUTURES -static void ts_scheme_on_demand(void) XFORM_SKIP_PROC +static Scheme_Object **ts_scheme_on_demand(Scheme_Object **rs) XFORM_SKIP_PROC { if (scheme_use_rtcall) { - scheme_rtcall_void_void_3args("[jit_on_demand]", FSRC_OTHER, scheme_on_demand_with_args); + return scheme_rtcall_on_demand("[jit_on_demand]", FSRC_OTHER, scheme_on_demand_with_args, rs); } else - scheme_on_demand(); + return scheme_on_demand(rs); } #endif @@ -635,25 +635,25 @@ static int common2(mz_jit_state *jitter, void *_data) mz_push_threadlocal(); mz_tl_ldi_p(JIT_RUNSTACK, tl_MZ_RUNSTACK); sjc.on_demand_jit_arity_code = jit_get_ip().ptr; /* <<<- arity variant starts here */ - jit_subi_p(JIT_RUNSTACK, JIT_RUNSTACK, WORDS_TO_BYTES(3)); + jit_subi_p(JIT_RUNSTACK, JIT_RUNSTACK, WORDS_TO_BYTES(2)); CHECK_RUNSTACK_OVERFLOW(); jit_str_p(JIT_RUNSTACK, JIT_R0); jit_lshi_ul(JIT_R1, JIT_R1, 0x1); jit_ori_ul(JIT_R1, JIT_R1, 0x1); CHECK_LIMIT(); jit_stxi_p(WORDS_TO_BYTES(1), JIT_RUNSTACK, JIT_R1); - jit_stxi_p(WORDS_TO_BYTES(2), JIT_RUNSTACK, JIT_R2); JIT_UPDATE_THREAD_RSPTR(); - mz_prepare(0); + mz_prepare(1); + jit_pusharg_p(JIT_R2); /* argv is threaded through as an argument (for lwc handling) */ (void)mz_finish_lwe(ts_scheme_on_demand, ref); CHECK_LIMIT(); /* Restore registers and runstack, and jump to arity checking of newly-created code when argv == runstack (i.e., a tail call): */ + jit_retval(JIT_R2); jit_ldr_p(JIT_R0, JIT_RUNSTACK); jit_ldxi_p(JIT_R1, JIT_RUNSTACK, WORDS_TO_BYTES(1)); jit_rshi_ul(JIT_R1, JIT_R1, 0x1); - jit_ldxi_p(JIT_R2, JIT_RUNSTACK, WORDS_TO_BYTES(2)); - jit_addi_p(JIT_RUNSTACK, JIT_RUNSTACK, WORDS_TO_BYTES(3)); + jit_addi_p(JIT_RUNSTACK, JIT_RUNSTACK, WORDS_TO_BYTES(2)); CHECK_LIMIT(); ref = jit_bner_p(jit_forward(), JIT_RUNSTACK, JIT_R2); /* Also, check that the runstack is big enough with the revised diff --git a/src/racket/src/jitinline.c b/src/racket/src/jitinline.c index 5cdc2962ad..f85ad7cbf7 100644 --- a/src/racket/src/jitinline.c +++ b/src/racket/src/jitinline.c @@ -1130,7 +1130,8 @@ int scheme_generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in } else if (IS_NAMED_PRIM(rator, "fsemaphore?")) { generate_inlined_type_test(jitter, app, scheme_fsemaphore_type, scheme_fsemaphore_type, 1, for_branch, branch_short, need_sync); return 1; - } else if (IS_NAMED_PRIM(rator, "fsemaphore-count") + } else if (IS_NAMED_PRIM(rator, "future") + | IS_NAMED_PRIM(rator, "fsemaphore-count") || IS_NAMED_PRIM(rator, "make-fsemaphore") || IS_NAMED_PRIM(rator, "fsemaphore-post") || IS_NAMED_PRIM(rator, "fsemaphore-wait") @@ -1144,9 +1145,6 @@ int scheme_generate_inlined_unary(mz_jit_state *jitter, Scheme_App2_Rec *app, in CHECK_LIMIT(); mz_runstack_unskipped(jitter, 1); - mz_rs_sync(); - JIT_UPDATE_THREAD_RSPTR_IF_NEEDED(); - /* Push the arg onto the runstack */ mz_pushr_p(JIT_R0); mz_rs_sync(); diff --git a/src/racket/src/schemef.h b/src/racket/src/schemef.h index e4fa097b8a..b9dfc2c73d 100644 --- a/src/racket/src/schemef.h +++ b/src/racket/src/schemef.h @@ -201,7 +201,10 @@ MZ_EXTERN void scheme_raise(Scheme_Object *exn); MZ_EXTERN int scheme_log_level_p(Scheme_Logger *logger, int level); MZ_EXTERN void scheme_log(Scheme_Logger *logger, int level, int flags, - char *msg, ...); + const char *msg, ...); +MZ_EXTERN void scheme_log_w_data(Scheme_Logger *logger, int level, int flags, + Scheme_Object *data, + const char *msg, ...); MZ_EXTERN void scheme_log_message(Scheme_Logger *logger, int level, char *buffer, intptr_t len, Scheme_Object *data); MZ_EXTERN void scheme_log_abort(char *buffer); MZ_EXTERN void scheme_log_warning(char *buffer); diff --git a/src/racket/src/schemex.h b/src/racket/src/schemex.h index 99081b1191..a534cafc36 100644 --- a/src/racket/src/schemex.h +++ b/src/racket/src/schemex.h @@ -158,7 +158,10 @@ void (*scheme_warning)(char *msg, ...); void (*scheme_raise)(Scheme_Object *exn); int (*scheme_log_level_p)(Scheme_Logger *logger, int level); void (*scheme_log)(Scheme_Logger *logger, int level, int flags, - char *msg, ...); + const char *msg, ...); +void (*scheme_log_w_data)(Scheme_Logger *logger, int level, int flags, + Scheme_Object *data, + const char *msg, ...); void (*scheme_log_message)(Scheme_Logger *logger, int level, char *buffer, intptr_t len, Scheme_Object *data); void (*scheme_log_abort)(char *buffer); void (*scheme_log_warning)(char *buffer); diff --git a/src/racket/src/schemex.inc b/src/racket/src/schemex.inc index 911b38ea61..bcb847cff3 100644 --- a/src/racket/src/schemex.inc +++ b/src/racket/src/schemex.inc @@ -103,6 +103,7 @@ scheme_extension_table->scheme_raise = scheme_raise; scheme_extension_table->scheme_log_level_p = scheme_log_level_p; scheme_extension_table->scheme_log = scheme_log; + scheme_extension_table->scheme_log_w_data = scheme_log_w_data; scheme_extension_table->scheme_log_message = scheme_log_message; scheme_extension_table->scheme_log_abort = scheme_log_abort; scheme_extension_table->scheme_log_warning = scheme_log_warning; diff --git a/src/racket/src/schemexm.h b/src/racket/src/schemexm.h index e1c74e981b..505e2e2085 100644 --- a/src/racket/src/schemexm.h +++ b/src/racket/src/schemexm.h @@ -103,6 +103,7 @@ #define scheme_raise (scheme_extension_table->scheme_raise) #define scheme_log_level_p (scheme_extension_table->scheme_log_level_p) #define scheme_log (scheme_extension_table->scheme_log) +#define scheme_log_w_data (scheme_extension_table->scheme_log_w_data) #define scheme_log_message (scheme_extension_table->scheme_log_message) #define scheme_log_abort (scheme_extension_table->scheme_log_abort) #define scheme_log_warning (scheme_extension_table->scheme_log_warning) diff --git a/src/racket/src/schpriv.h b/src/racket/src/schpriv.h index e0b1ab3bda..364d89bcf1 100644 --- a/src/racket/src/schpriv.h +++ b/src/racket/src/schpriv.h @@ -2309,7 +2309,8 @@ Scheme_Lightweight_Continuation *scheme_capture_lightweight_continuation(Scheme_ Scheme_Current_LWC *p_lwc, void **storage); Scheme_Object *scheme_apply_lightweight_continuation(Scheme_Lightweight_Continuation *captured, - Scheme_Object *result); + Scheme_Object *result, + int result_is_rs_argv); Scheme_Object **scheme_adjust_runstack_argument(Scheme_Lightweight_Continuation *captured, Scheme_Object **arg); diff --git a/src/racket/src/schvers.h b/src/racket/src/schvers.h index c5815b352d..c123e613cc 100644 --- a/src/racket/src/schvers.h +++ b/src/racket/src/schvers.h @@ -13,12 +13,12 @@ consistently.) */ -#define MZSCHEME_VERSION "5.1.0.5" +#define MZSCHEME_VERSION "5.1.0.6" #define MZSCHEME_VERSION_X 5 #define MZSCHEME_VERSION_Y 1 #define MZSCHEME_VERSION_Z 0 -#define MZSCHEME_VERSION_W 5 +#define MZSCHEME_VERSION_W 6 #define MZSCHEME_VERSION_MAJOR ((MZSCHEME_VERSION_X * 100) + MZSCHEME_VERSION_Y) #define MZSCHEME_VERSION_MINOR ((MZSCHEME_VERSION_Z * 1000) + MZSCHEME_VERSION_W)