fun with callbackEnter

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

fun with callbackEnter

johnmci
 
Since we are talking about events, this is an error thrown by a iphone  
squeak vm setup as a single pthread.

What happens is ioGetNextEvent is called which calls ioProcessEvents  
which on a special version of the iphone vm
calls [NSRunLoop currentRunLoop] to run for N milliseconds.

When the run loop runs it ends up sending a message to an Objective-C  
SqueakProxy instance which then signals
a squeak semaphore to wake up the VM. In this specialized VM it does

                interpreterProxy->signalSemaphoreWithIndex(sem);
                interpreterProxy->callbackEnter(&callbackid);

However I *think* the problem here is that although we signal the  
semaphore then issue the forceInterruptCheck
in callbackEnter: this does not actually alter the runnable processes  
list since that work is only done when
checkForInterrrupts() is run.  Thus in this case the only process  
running is the idleProcess, and it's sleeping
but we are attempting to wake a squeakProxy process waiting on the  
semaphore we did signal, but
as you see oops nada runnable, so die.



2009-11-10 12:59:36.214 x[13886:207] forwardInvocation: <NSInvocation:  
0x1368370>
2009-11-10 12:59:36.215 x[13886:207] currentThread: <NSThread:  
0x1105e90>{name = (null), num = 1}
2009-11-10 12:59:36.219 x[13886:207] inside lock 0
2009-11-10 12:59:36.220 x[13886:207] signalling squeak

scheduler could not find a runnable process

548435824 >idleProcess
548435732 >startUp
548291060 BlockClosure>newProcess



callbackEnter: callbackID
        "Re-enter the interpreter for executing a callback"
        | result activeProc |
        self export: true.
        self var: #callbackID declareC: 'sqInt *callbackID'.

        "For now, do not allow a callback unless we're in a primitiveResponse"
        primitiveIndex = 0 ifTrue:[^false].

        "Check if we've exceeded the callback depth"
        jmpDepth >= jmpMax ifTrue:[^false].
        jmpDepth := jmpDepth + 1.

        "Suspend the currently active process"
        activeProc := self fetchPointer: ActiveProcessIndex
                                                 ofObject: self schedulerPointer.
        suspendedCallbacks at: jmpDepth put: activeProc.
        "We need to preserve newMethod explicitly since it is not activated yet
        and therefore no context has been created for it. If the caller  
primitive
        for any reason decides to fail we need to make sure we execute the  
correct
        method and not the one 'last used' in the call back"
        suspendedMethods at: jmpDepth put: newMethod.
        self transferTo: self wakeHighestPriority.

        "Typically, invoking the callback means that some semaphore has been
        signaled to indicate the callback. Force an interrupt check right  
away."
        self forceInterruptCheck.

        result := self setjmp: (jmpBuf at: jmpDepth).
        result == 0 ifTrue:["Fill in callbackID"
                callbackID at: 0 put: jmpDepth.
                "This is ugly but the inliner treats interpret() in very special and  
strange ways and calling any kind of 'self interpret' either directly  
or even via cCode:inSmalltalk: will cause this entire method to vanish."
                self cCode: 'interpret()'.
        ].

        "Transfer back to the previous process so that caller can push result"
        activeProc := self fetchPointer: ActiveProcessIndex
                                                 ofObject: self schedulerPointer.
        self putToSleep: activeProc.
        activeProc := suspendedCallbacks at: jmpDepth.
        newMethod := suspendedMethods at: jmpDepth. "see comment above"
        self transferTo: activeProc.
        jmpDepth := jmpDepth-1.
        ^true



--
=
=
=
========================================================================
John M. McIntosh <[hidden email]>   Twitter:  
squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
=
=
=
========================================================================




Reply | Threaded
Open this post in threaded view
|

Re: fun with callbackEnter

Andreas.Raab
 
Oh. Interesting observation. Sounds right to me. Guess we'll have to add
a checkForInterrupts() to callbackEnter. BTW, this strongly resonates
with what I was writing about the event driven VM. In that scheme
"callbackEnter" would be a straightforward call to interpret().

Cheers,
   - Andreas

John M McIntosh wrote:

> Since we are talking about events, this is an error thrown by a iphone
> squeak vm setup as a single pthread.
>
> What happens is ioGetNextEvent is called which calls ioProcessEvents
> which on a special version of the iphone vm
> calls [NSRunLoop currentRunLoop] to run for N milliseconds.
>
> When the run loop runs it ends up sending a message to an Objective-C
> SqueakProxy instance which then signals
> a squeak semaphore to wake up the VM. In this specialized VM it does
>
>         interpreterProxy->signalSemaphoreWithIndex(sem);
>         interpreterProxy->callbackEnter(&callbackid);
>
> However I *think* the problem here is that although we signal the
> semaphore then issue the forceInterruptCheck
> in callbackEnter: this does not actually alter the runnable processes
> list since that work is only done when
> checkForInterrrupts() is run.  Thus in this case the only process
> running is the idleProcess, and it's sleeping
> but we are attempting to wake a squeakProxy process waiting on the
> semaphore we did signal, but
> as you see oops nada runnable, so die.
>
>
>
> 2009-11-10 12:59:36.214 x[13886:207] forwardInvocation: <NSInvocation:
> 0x1368370>
> 2009-11-10 12:59:36.215 x[13886:207] currentThread: <NSThread:
> 0x1105e90>{name = (null), num = 1}
> 2009-11-10 12:59:36.219 x[13886:207] inside lock 0
> 2009-11-10 12:59:36.220 x[13886:207] signalling squeak
>
> scheduler could not find a runnable process
>
> 548435824 >idleProcess
> 548435732 >startUp
> 548291060 BlockClosure>newProcess
>
>
>
> callbackEnter: callbackID
>     "Re-enter the interpreter for executing a callback"
>     | result activeProc |
>     self export: true.
>     self var: #callbackID declareC: 'sqInt *callbackID'.
>
>     "For now, do not allow a callback unless we're in a primitiveResponse"
>     primitiveIndex = 0 ifTrue:[^false].
>
>     "Check if we've exceeded the callback depth"
>     jmpDepth >= jmpMax ifTrue:[^false].
>     jmpDepth := jmpDepth + 1.
>
>     "Suspend the currently active process"
>     activeProc := self fetchPointer: ActiveProcessIndex
>                          ofObject: self schedulerPointer.
>     suspendedCallbacks at: jmpDepth put: activeProc.
>     "We need to preserve newMethod explicitly since it is not activated yet
>     and therefore no context has been created for it. If the caller
> primitive
>     for any reason decides to fail we need to make sure we execute the
> correct
>     method and not the one 'last used' in the call back"
>     suspendedMethods at: jmpDepth put: newMethod.
>     self transferTo: self wakeHighestPriority.
>
>     "Typically, invoking the callback means that some semaphore has been
>     signaled to indicate the callback. Force an interrupt check right
> away."
>     self forceInterruptCheck.
>
>     result := self setjmp: (jmpBuf at: jmpDepth).
>     result == 0 ifTrue:["Fill in callbackID"
>         callbackID at: 0 put: jmpDepth.
>         "This is ugly but the inliner treats interpret() in very special
> and strange ways and calling any kind of 'self interpret' either
> directly or even via cCode:inSmalltalk: will cause this entire method to
> vanish."
>         self cCode: 'interpret()'.
>     ].
>
>     "Transfer back to the previous process so that caller can push result"
>     activeProc := self fetchPointer: ActiveProcessIndex
>                          ofObject: self schedulerPointer.
>     self putToSleep: activeProc.
>     activeProc := suspendedCallbacks at: jmpDepth.
>     newMethod := suspendedMethods at: jmpDepth.    "see comment above"
>     self transferTo: activeProc.
>     jmpDepth := jmpDepth-1.
>     ^true
>
>
>
> --
> ===========================================================================
> John M. McIntosh <[hidden email]>   Twitter:  
> squeaker68882
> Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
> ===========================================================================
>
>
>
>
Reply | Threaded
Open this post in threaded view
|

Re: fun with callbackEnter

johnmci
 
Part of the complication here is that I think callbackEnter is not  
fully integrated in VMMaker?
And there is a different implementation for the Alien callback logic,  
so we really need to decide which way to go here.


On 2009-11-10, at 11:37 AM, Andreas Raab wrote:

> Oh. Interesting observation. Sounds right to me. Guess we'll have to  
> add a checkForInterrupts() to callbackEnter. BTW, this strongly  
> resonates with what I was writing about the event driven VM. In that  
> scheme "callbackEnter" would be a straightforward call to interpret().
>
> Cheers,
>  - Andreas

--
=
=
=
========================================================================
John M. McIntosh <[hidden email]>   Twitter:  
squeaker68882
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
=
=
=
========================================================================