In VM w/o closures, i implemented a new primitive, #primitiveInterrupt, which looks like following:
primitiveInterrupt "primitive" | context interruptProcess sched oldProc | self export: true. context := self stackTop.
sched := self schedulerPointer. "check that we using a new scheduler , which having additional instance variables: - interruptProcess - interruptedProcess" (self lastPointerOf: sched) >= (InterruptedProcessIndex * BytesPerWord + BaseHeaderSize) ifFalse: [ ^ self primitiveFail ].
oldProc := self fetchPointer: ActiveProcessIndex ofObject: sched. interruptProcess := self fetchPointer: InterruptProcessIndex ofObject: sched. oldProc == interruptProcess ifTrue: [ "we are already in interrupt, proceed as with sending #value to block" ^ self primitiveValue ]. self storePointer: InterruptedProcessIndex ofObject: sched withValue: oldProc. self storePointer: SuspendedContextIndex ofObject: interruptProcess withValue: context. self putToSleep: oldProc. self transferTo: interruptProcess.
self pop: 1 thenPush: self nilObject
A primitive is hooked in BlockContext>>primInterrupt :
primInterrupt "Primitive. Evaluate the block in special interrupt process" <primitive: 'primitiveInterrupt' module: ''> self primitiveFail
And code, which is using it looks like following:
Processor>>interruptWith: aBlock "Interrupt the currently running process to evaluate given block argument inside interrupt process" | result | [ result := aBlock value. activeProcess suspend. ] asContext primInterrupt. ^ result the VM crashing at attempt to return from aBlock value (it never gets to the point for evaluating 'activeProcess suspend').
if i write code like following:
Processor>>interruptWith: aBlock "Interrupt the currently running process to evaluate given block argument inside interrupt process" | result | [ [ result := aBlock value. ] value activeProcess suspend. ] asContext primInterrupt. ^ result
Then VM does not crashing, but silenty quits to OS.
The only way how i managed to make it work, is to do it as:
Processor>>interruptWith: aBlock "Interrupt the currently running process to evaluate given block argument inside interrupt process" [ self runBlock: aBlock ] asContext primInterrupt.
and runBlock: aBlock is:
runBlock: aBlock aBlock value. activeProcess suspend.
it works fine, except that i unable to use the returned result. - i could put it to instance variable.. but its a bit awkward :(
I suspect this somehow connected with the return to context who having sender = nil. (a bottom context of process always having sender = nil). But i wonder, why my code not working, while code, which used for #fork, it does? Any suggestions?
newProcess "Answer a Process running the code in the receiver. The process is not scheduled."
<primitive: 19> "Simulation guard" ^ Process forContext: [self value. Processor terminateActive] asContext priority: Processor activePriority
here, the initial context of newly created process will point to:
[self value. Processor terminateActive]
and in my case, an initial context of interrupt process is set in #primitiveInterrupt and points to: [ result := aBlock value. activeProcess suspend. ]
why i works for above case, but not for mine, no idea...
On Wed, 29 Apr 2009 09:17:16 +0200, Igor Stasenko wrote:
In VM w/o closures, i implemented a new primitive, #primitiveInterrupt, which looks like following:
primitiveInterrupt "primitive" | context interruptProcess sched oldProc | self export: true. context := self stackTop.
sched := self schedulerPointer. "check that we using a new scheduler , which having additional instance variables: - interruptProcess - interruptedProcess" (self lastPointerOf: sched) >= (InterruptedProcessIndex * BytesPerWord + BaseHeaderSize) ifFalse: [ ^ self primitiveFail ].
oldProc := self fetchPointer: ActiveProcessIndex ofObject: sched. interruptProcess := self fetchPointer: InterruptProcessIndex ofObject: sched. oldProc == interruptProcess ifTrue: [ "we are already in interrupt, proceed as with sending #value to block" ^ self primitiveValue ].
Check(s) may lack this: any process can be in any state including the ones which you do not want and the ones which #transferTo: does not want.
self storePointer: InterruptedProcessIndex ofObject: sched withValue: oldProc. self storePointer: SuspendedContextIndex ofObject: interruptProcess withValue: context. self putToSleep: oldProc. self transferTo: interruptProcess.
self pop: 1 thenPush: self nilObject
A primitive is hooked in BlockContext>>primInterrupt :
primInterrupt "Primitive. Evaluate the block in special interrupt process" <primitive: 'primitiveInterrupt' module: ''> self primitiveFail
And code, which is using it looks like following:
Processor>>interruptWith: aBlock "Interrupt the currently running process to evaluate given block argument inside interrupt process" | result | [ result := aBlock value. activeProcess suspend. ] asContext primInterrupt. ^ result
(activeProcess suspend) you mean an instVar ??
the VM crashing at attempt to return from aBlock value (it never gets to the point for evaluating 'activeProcess suspend').
if i write code like following:
Processor>>interruptWith: aBlock "Interrupt the currently running process to evaluate given block argument inside interrupt process" | result | [ [ result := aBlock value. ] value activeProcess suspend. ] asContext primInterrupt. ^ result
Now with #activeProcess you are sending, versus the instVar above ??
Then VM does not crashing, but silenty quits to OS.
Good luck :)
The only way how i managed to make it work, is to do it as:
Processor>>interruptWith: aBlock "Interrupt the currently running process to evaluate given block argument inside interrupt process" [ self runBlock: aBlock ] asContext primInterrupt.
and runBlock: aBlock is:
runBlock: aBlock
aBlock value. activeProcess suspend.
it works fine, except that i unable to use the returned result. - i could put it to instance variable.. but its a bit awkward :(
I suspect this somehow connected with the return to context who having sender = nil. (a bottom context of process always having sender = nil). But i wonder, why my code not working, while code, which used for #fork, it does? Any suggestions?
newProcess "Answer a Process running the code in the receiver. The process is not scheduled."
<primitive: 19> "Simulation guard" ^ Process forContext: [self value. Processor terminateActive] asContext priority: Processor activePriority
here, the initial context of newly created process will point to:
[self value. Processor terminateActive]
and in my case, an initial context of interrupt process is set in #primitiveInterrupt and points to: [ result := aBlock value. activeProcess suspend. ]
why i works for above case, but not for mine, no idea...
2009/4/29 Klaus D. Witzel klaus.witzel@cobss.com:
On Wed, 29 Apr 2009 09:17:16 +0200, Igor Stasenko wrote:
In VM w/o closures, i implemented a new primitive, #primitiveInterrupt, which looks like following:
primitiveInterrupt "primitive" | context interruptProcess sched oldProc | self export: true. context := self stackTop.
sched := self schedulerPointer. "check that we using a new scheduler , which having additional instance variables: - interruptProcess - interruptedProcess" (self lastPointerOf: sched) >= (InterruptedProcessIndex * BytesPerWord + BaseHeaderSize) ifFalse: [ ^ self primitiveFail ].
oldProc := self fetchPointer: ActiveProcessIndex ofObject: sched. interruptProcess := self fetchPointer: InterruptProcessIndex ofObject: sched. oldProc == interruptProcess ifTrue: [ "we are already in interrupt, proceed as with sending #value to block" ^ self primitiveValue ].
Check(s) may lack this: any process can be in any state including the ones which you do not want and the ones which #transferTo: does not want.
at this stage i don't care. Active process is healthy - because it runs. An interrupt process is accessible only by scheduler, and scheduler makes sure its in good shape. :)
self storePointer: InterruptedProcessIndex ofObject: sched withValue: oldProc. self storePointer: SuspendedContextIndex ofObject: interruptProcess withValue: context. self putToSleep: oldProc. self transferTo: interruptProcess.
self pop: 1 thenPush: self nilObject
A primitive is hooked in BlockContext>>primInterrupt :
primInterrupt "Primitive. Evaluate the block in special interrupt process" <primitive: 'primitiveInterrupt' module: ''> self primitiveFail
And code, which is using it looks like following:
Processor>>interruptWith: aBlock "Interrupt the currently running process to evaluate given block argument inside interrupt process" | result | [ result := aBlock value. activeProcess suspend. ] asContext primInterrupt. ^ result
(activeProcess suspend) you mean an instVar ??
yeah. why writing 'Processor activeProcess suspend', when self == Processor?
the VM crashing at attempt to return from aBlock value (it never gets to the point for evaluating 'activeProcess suspend').
if i write code like following:
Processor>>interruptWith: aBlock "Interrupt the currently running process to evaluate given block argument inside interrupt process" | result | [ [ result := aBlock value. ] value activeProcess suspend. ] asContext primInterrupt. ^ result
Now with #activeProcess you are sending, versus the instVar above ??
its just a typo. there is '.' missing. I changed this code multiple times trying multiple variants. And i can assure you that problem is not because DNU :) As i said, VM crashing/misbehaves after returning from send #value to a block. So its really irrelevant what follows, i can write:
[ result := aBlock value. ] value foo bar zork.
and have the same result :)
Then VM does not crashing, but silenty quits to OS.
Good luck :)
Actually, the problem is not relevant anymore because i changed a strategy to simply have a primitive which does task switching. Rest will be handled by scheduler process (including: scheduling processes, signaling semaphores etc).
But still its would be good to know, what is wrong with it, to know how to avoid it in future :)
The only way how i managed to make it work, is to do it as:
Processor>>interruptWith: aBlock "Interrupt the currently running process to evaluate given block argument inside interrupt process" [ self runBlock: aBlock ] asContext primInterrupt.
and runBlock: aBlock is:
runBlock: aBlock
aBlock value. activeProcess suspend.
it works fine, except that i unable to use the returned result. - i could put it to instance variable.. but its a bit awkward :(
I suspect this somehow connected with the return to context who having sender = nil. (a bottom context of process always having sender = nil). But i wonder, why my code not working, while code, which used for #fork, it does? Any suggestions?
newProcess "Answer a Process running the code in the receiver. The process is not scheduled."
<primitive: 19> "Simulation guard" ^ Process forContext: [self value. Processor terminateActive] asContext priority: Processor activePriority
here, the initial context of newly created process will point to:
[self value. Processor terminateActive]
and in my case, an initial context of interrupt process is set in #primitiveInterrupt and points to: [ result := aBlock value. activeProcess suspend. ]
why i works for above case, but not for mine, no idea...
-- "If at first, the idea is not absurd, then there is no hope for it". Albert Einstein
squeak-dev@lists.squeakfoundation.org