[Vm-dev] fun with callbackEnter
John M McIntosh
johnmci at smalltalkconsulting.com
Tue Nov 10 19:29:55 UTC 2009
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 <johnmci at smalltalkconsulting.com> Twitter:
squeaker68882
Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com
=
=
=
========================================================================
More information about the Vm-dev
mailing list