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... -- Best regards, Igor Stasenko AKA sig. |
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... > -- "If at first, the idea is not absurd, then there is no hope for it". Albert Einstein |
2009/4/29 Klaus D. Witzel <[hidden email]>:
> 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. > 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 ?? > 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 > > > -- Best regards, Igor Stasenko AKA sig. |
Free forum by Nabble | Edit this page |