Change do-callback to register the current thread with the callback, instead of busy waiting for the current callback to become the right one before returning. Fixes 100% CPU usage issue with system-alert. Thanks to Blei and ex-rzr for doing preliminary analysis of the issue

db4
Slava Pestov 2011-04-10 22:00:43 -04:00
parent 07f2d75316
commit c36d73e242
10 changed files with 50 additions and 31 deletions

View File

@ -1,9 +1,6 @@
! Copyright (C) 2008, 2009 Slava Pestov. ! Copyright (C) 2008, 2011 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: vocabs.loader kernel io.thread threads USE: vocabs.loader
compiler.utilities namespaces ;
IN: bootstrap.threads
{ "bootstrap.threads" "debugger" } "debugger.threads" require-when "threads" require
"io.thread" require
[ yield ] yield-hook set-global

View File

@ -4,6 +4,7 @@ USING: accessors kernel namespaces arrays sequences io words fry
continuations vocabs assocs definitions math graphs generic continuations vocabs assocs definitions math graphs generic
generic.single combinators combinators.smart macros generic.single combinators combinators.smart macros
source-files.errors combinators.short-circuit classes.algebra source-files.errors combinators.short-circuit classes.algebra
vocabs.loader
stack-checker stack-checker.dependencies stack-checker.inlining stack-checker stack-checker.dependencies stack-checker.inlining
stack-checker.errors stack-checker.errors
@ -181,3 +182,5 @@ M: optimizing-compiler process-forgotten-words
: disable-optimizer ( -- ) : disable-optimizer ( -- )
f compiler-impl set-global ; f compiler-impl set-global ;
{ "threads" "compiler" } "compiler.threads" require-when

View File

@ -0,0 +1 @@
Slava Pestov

View File

@ -0,0 +1,12 @@
! Copyright (C) 2011 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: alien.private compiler.utilities kernel namespaces
stack-checker.alien threads threads.private ;
IN: compiler.threads
[ yield ] yield-hook set-global
[
dup current-callback eq?
[ drop ] [ wait-for-callback ] if
] wait-for-callback-hook set-global

View File

@ -104,15 +104,8 @@ TUPLE: run-loop fds sources timers ;
: (reset-timer) ( timer timestamp -- ) : (reset-timer) ( timer timestamp -- )
>CFAbsoluteTime CFRunLoopTimerSetNextFireDate ; >CFAbsoluteTime CFRunLoopTimerSetNextFireDate ;
: nano-count>micros ( x -- n )
nano-count - 1,000 /f system-micros + ;
: reset-timer ( timer -- ) : reset-timer ( timer -- )
{ sleep-time 1000 /f system-micros + (reset-timer) ;
{ [ run-queue deque-empty? not ] [ system-micros ] }
{ [ sleep-queue heap-empty? not ] [ sleep-queue heap-peek nip nano-count>micros ] }
[ system-micros 1,000,000 + ]
} cond (reset-timer) ;
PRIVATE> PRIVATE>

View File

@ -355,3 +355,5 @@ M: not-found-in-roots summary drop "Cannot resolve vocab: path" ;
M: wrong-values summary drop "Quotation's stack effect does not match call site" ; M: wrong-values summary drop "Quotation's stack effect does not match call site" ;
M: stack-effect-omits-dashes summary drop "Stack effect must contain “--”" ; M: stack-effect-omits-dashes summary drop "Stack effect must contain “--”" ;
{ "threads" "debugger" } "debugger.threads" require-when

View File

@ -122,9 +122,13 @@ TUPLE: alien-callback-params < alien-node-params xt ;
GENERIC: wrap-callback-quot ( params quot -- quot' ) GENERIC: wrap-callback-quot ( params quot -- quot' )
SYMBOL: wait-for-callback-hook
wait-for-callback-hook [ [ drop ] ] initialize
M: callable wrap-callback-quot M: callable wrap-callback-quot
swap [ callback-parameter-quot ] [ callback-return-quot ] bi surround swap [ callback-parameter-quot ] [ callback-return-quot ] bi surround
yield-hook get wait-for-callback-hook get
'[ _ _ do-callback ] '[ _ _ do-callback ]
>quotation ; >quotation ;

View File

@ -1,8 +1,8 @@
! Copyright (C) 2004, 2010 Slava Pestov. ! Copyright (C) 2004, 2011 Slava Pestov.
! Copyright (C) 2005 Mackenzie Straight. ! Copyright (C) 2005 Mackenzie Straight.
! See http://factorcode.org/license.txt for BSD license. ! See http://factorcode.org/license.txt for BSD license.
USING: arrays hashtables heaps kernel kernel.private math USING: alien.private arrays hashtables heaps kernel kernel.private
namespaces sequences vectors continuations continuations.private math namespaces sequences vectors continuations continuations.private
dlists assocs system combinators init boxes accessors math.order dlists assocs system combinators init boxes accessors math.order
deques strings quotations fry ; deques strings quotations fry ;
IN: threads IN: threads
@ -101,6 +101,9 @@ PRIVATE>
: sleep-queue ( -- heap ) : sleep-queue ( -- heap )
66 special-object { min-heap } declare ; inline 66 special-object { min-heap } declare ; inline
: waiting-callbacks ( -- assoc )
68 special-object { hashtable } declare ; inline
: new-thread ( quot name class -- thread ) : new-thread ( quot name class -- thread )
new new
swap >>name swap >>name
@ -123,6 +126,7 @@ PRIVATE>
: sleep-time ( -- nanos/f ) : sleep-time ( -- nanos/f )
{ {
{ [ current-callback waiting-callbacks key? ] [ 0 ] }
{ [ run-queue deque-empty? not ] [ 0 ] } { [ run-queue deque-empty? not ] [ 0 ] }
{ [ sleep-queue heap-empty? ] [ f ] } { [ sleep-queue heap-empty? ] [ f ] }
[ sleep-queue heap-peek nip nano-count [-] ] [ sleep-queue heap-peek nip nano-count [-] ]
@ -176,8 +180,13 @@ M: thread (next)
[ context>> box> set-context-and-delete ] [ context>> box> set-context-and-delete ]
[ t >>runnable drop [start] start-context-and-delete ] if ; [ t >>runnable drop [start] start-context-and-delete ] if ;
: wake-up-callbacks ( -- )
current-callback waiting-callbacks delete-at*
[ resume-now ] [ drop ] if ;
: next ( -- obj thread ) : next ( -- obj thread )
expire-sleep-loop expire-sleep-loop
wake-up-callbacks
run-queue pop-back run-queue pop-back
dup array? [ first2 ] [ [ f ] dip ] if dup array? [ first2 ] [ [ f ] dip ] if
f >>state f >>state
@ -230,7 +239,8 @@ GENERIC: error-in-thread ( error thread -- )
: init-thread-state ( -- ) : init-thread-state ( -- )
H{ } clone 64 set-special-object H{ } clone 64 set-special-object
<dlist> 65 set-special-object <dlist> 65 set-special-object
<min-heap> 66 set-special-object ; <min-heap> 66 set-special-object
H{ } clone 68 set-special-object ;
: init-initial-thread ( -- ) : init-initial-thread ( -- )
[ ] "Initial" <thread> [ ] "Initial" <thread>
@ -244,6 +254,10 @@ GENERIC: error-in-thread ( error thread -- )
init-thread-state init-thread-state
init-initial-thread ; init-initial-thread ;
: wait-for-callback ( callback -- )
self swap waiting-callbacks set-at
"Callback return" suspend drop ;
PRIVATE> PRIVATE>
[ init-threads ] "threads" add-startup-hook [ init-threads ] "threads" add-startup-hook

View File

@ -101,21 +101,12 @@ SYMBOL: callbacks
[ H{ } clone callbacks set-global ] "alien" add-startup-hook [ H{ } clone callbacks set-global ] "alien" add-startup-hook
! Every callback invocation has a unique identifier in the VM.
! We make sure that the current callback is the right one before
! returning from it, to avoid a bad interaction between threads
! and callbacks. See basis/compiler/tests/alien.factor for a
! test case.
: wait-to-return ( yield-quot: ( -- ) callback-id -- )
dup current-callback eq?
[ 2drop ] [ over call wait-to-return ] if ; inline recursive
! Used by compiler.codegen to wrap callback bodies ! Used by compiler.codegen to wrap callback bodies
: do-callback ( callback-quot yield-quot: ( -- ) -- ) : do-callback ( callback-quot wait-quot: ( callback -- ) -- )
init-namespaces init-namespaces
init-catchstack init-catchstack
current-callback current-callback
[ 2drop call ] [ wait-to-return drop ] 3bi ; inline [ 2drop call ] [ swap call( callback -- ) drop ] 3bi ; inline
! A utility for defining global variables that are recompiled in ! A utility for defining global variables that are recompiled in
! every session ! every session

View File

@ -93,6 +93,8 @@ enum special_object {
OBJ_SLEEP_QUEUE = 66, OBJ_SLEEP_QUEUE = 66,
OBJ_VM_COMPILER = 67, /* version string of the compiler we were built with */ OBJ_VM_COMPILER = 67, /* version string of the compiler we were built with */
OBJ_WAITING_CALLBACKS = 68,
}; };
/* save-image-and-exit discards special objects that are filled in on startup /* save-image-and-exit discards special objects that are filled in on startup