[squeak-dev] Need help with identifying the problem

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

[squeak-dev] Need help with identifying the problem

Igor Stasenko
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.

Reply | Threaded
Open this post in threaded view
|

[squeak-dev] Re: Need help with identifying the problem

Klaus D. Witzel
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


Reply | Threaded
Open this post in threaded view
|

Re: [squeak-dev] Re: Need help with identifying the problem

Igor Stasenko
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.
>
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
>
>
>



--
Best regards,
Igor Stasenko AKA sig.