The Inbox: Compiler-mt.456.mcz

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

The Inbox: Compiler-mt.456.mcz

commits-2
A new version of Compiler was added to project The Inbox:
http://source.squeak.org/inbox/Compiler-mt.456.mcz

==================== Summary ====================

Name: Compiler-mt.456
Author: mt
Time: 2 February 2021, 11:06:33.099178 am
UUID: 0558759c-0bf7-e946-8a65-c673c49d6c8f
Ancestors: Compiler-mt.455

Forgot to remove old method. Sorry for the noise.

=============== Diff against Compiler-mt.455 ===============

Item was removed:
- ----- Method: Parser>>noContextSwitch (in category 'pragmas - code evaluation') -----
- noContextSwitch
- "By adding this pragma to a method, it will not be preempt the current process on method activation if a higher-priority process is runnable. Any numbered primitive without side effects will do here."
- <pragmaParser>
-
- "Note that primitive 123 once was primitiveValueUninteruptibly but is no longer in use."
- self addPragma: (Pragma keyword: #primitive: arguments: #(123)).
-
- self advance.
- ^ true!


Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

marcel.taeumel
Hi all!

I would like to merge <noContextSwitchOnActivation> into Trunk. But I still need a nice test case. Should be independent from the JIT. Maybe a simple setter?

foobar: value
   <noContextSwitchOnActivation>
   instVar := value

...

[ test instVar should be 42 already ] forkAt: current + 1.
self foobar: 42.

??

Best,
Marcel

Am 02.02.2021 11:06:41 schrieb [hidden email] <[hidden email]>:

A new version of Compiler was added to project The Inbox:
http://source.squeak.org/inbox/Compiler-mt.456.mcz

==================== Summary ====================

Name: Compiler-mt.456
Author: mt
Time: 2 February 2021, 11:06:33.099178 am
UUID: 0558759c-0bf7-e946-8a65-c673c49d6c8f
Ancestors: Compiler-mt.455

Forgot to remove old method. Sorry for the noise.

=============== Diff against Compiler-mt.455 ===============

Item was removed:
- ----- Method: Parser>>noContextSwitch (in category 'pragmas - code evaluation') -----
- noContextSwitch
- "By adding this pragma to a method, it will not be preempt the current process on method activation if a higher-priority process is runnable. Any numbered primitive without side effects will do here."
-
-
- "Note that primitive 123 once was primitiveValueUninteruptibly but is no longer in use."
- self addPragma: (Pragma keyword: #primitive: arguments: #(123)).
-
- self advance.
- ^ true!




Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

marcel.taeumel
Ha! Tricky. I figured that #forkAt: will immediately run the process if its priority is higher than the current one:

x := 0.
[ x := 1 ] forkAt: 41.
y := x == 1. "true :-)"

However, I have no idea why the following happens:

x := 0.
[ [ x := 1 ] forkAt: 41 ] valueUnpreemptively.
y := x == 1. "false :-("

Or this:

x := 0.
[ [ x := 1 ] forkAt: 41 ] valueUnpreemptively.
Transcript showln: 'foo'.
y := x == 1. "false :-("

I would expect that "Transcript showln: 'foo'" entails many suspension points. The following, however, works for me:

x := 0.
[ [ x := 1 ] forkAt: 41 ] valueUnpreemptively.
ActiveWorld imageForm asMorph.
y := x == 1. "true :-)"

In any case, I have not yet found a way to test <noContextSwitchOnActivation>.

Best,
Marcel

Am 02.02.2021 11:23:28 schrieb Marcel Taeumel <[hidden email]>:

Hi all!

I would like to merge <noContextSwitchOnActivation> into Trunk. But I still need a nice test case. Should be independent from the JIT. Maybe a simple setter?

foobar: value
   <noContextSwitchOnActivation>
   instVar := value

...

[ test instVar should be 42 already ] forkAt: current + 1.
self foobar: 42.

??

Best,
Marcel

Am 02.02.2021 11:06:41 schrieb [hidden email] <[hidden email]>:

A new version of Compiler was added to project The Inbox:
http://source.squeak.org/inbox/Compiler-mt.456.mcz

==================== Summary ====================

Name: Compiler-mt.456
Author: mt
Time: 2 February 2021, 11:06:33.099178 am
UUID: 0558759c-0bf7-e946-8a65-c673c49d6c8f
Ancestors: Compiler-mt.455

Forgot to remove old method. Sorry for the noise.

=============== Diff against Compiler-mt.455 ===============

Item was removed:
- ----- Method: Parser>>noContextSwitch (in category 'pragmas - code evaluation') -----
- noContextSwitch
- "By adding this pragma to a method, it will not be preempt the current process on method activation if a higher-priority process is runnable. Any numbered primitive without side effects will do here."
-
-
- "Note that primitive 123 once was primitiveValueUninteruptibly but is no longer in use."
- self addPragma: (Pragma keyword: #primitive: arguments: #(123)).
-
- self advance.
- ^ true!




Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

marcel.taeumel
Also, taking a closer look at #valueUnpreemptively, which I now use to schedule that higher-priority process in a test:

[ [ result :=  value == 10 ] forkAt: 41 ] valueUnpreemptively.
self setValue.
self assert: result.

Here is the problem: "result" is still undefined. That means that there is no suspension point when invoking #setValue. At least not my VM.

setValue
   value := 10.

What would be a good implementation for #setValue to benefit from <noContextSwitchOnActivation>?

Best,
Marcel

Am 02.02.2021 12:23:13 schrieb Marcel Taeumel <[hidden email]>:

Ha! Tricky. I figured that #forkAt: will immediately run the process if its priority is higher than the current one:

x := 0.
[ x := 1 ] forkAt: 41.
y := x == 1. "true :-)"

However, I have no idea why the following happens:

x := 0.
[ [ x := 1 ] forkAt: 41 ] valueUnpreemptively.
y := x == 1. "false :-("

Or this:

x := 0.
[ [ x := 1 ] forkAt: 41 ] valueUnpreemptively.
Transcript showln: 'foo'.
y := x == 1. "false :-("

I would expect that "Transcript showln: 'foo'" entails many suspension points. The following, however, works for me:

x := 0.
[ [ x := 1 ] forkAt: 41 ] valueUnpreemptively.
ActiveWorld imageForm asMorph.
y := x == 1. "true :-)"

In any case, I have not yet found a way to test <noContextSwitchOnActivation>.

Best,
Marcel

Am 02.02.2021 11:23:28 schrieb Marcel Taeumel <[hidden email]>:

Hi all!

I would like to merge <noContextSwitchOnActivation> into Trunk. But I still need a nice test case. Should be independent from the JIT. Maybe a simple setter?

foobar: value
   <noContextSwitchOnActivation>
   instVar := value

...

[ test instVar should be 42 already ] forkAt: current + 1.
self foobar: 42.

??

Best,
Marcel

Am 02.02.2021 11:06:41 schrieb [hidden email] <[hidden email]>:

A new version of Compiler was added to project The Inbox:
http://source.squeak.org/inbox/Compiler-mt.456.mcz

==================== Summary ====================

Name: Compiler-mt.456
Author: mt
Time: 2 February 2021, 11:06:33.099178 am
UUID: 0558759c-0bf7-e946-8a65-c673c49d6c8f
Ancestors: Compiler-mt.455

Forgot to remove old method. Sorry for the noise.

=============== Diff against Compiler-mt.455 ===============

Item was removed:
- ----- Method: Parser>>noContextSwitch (in category 'pragmas - code evaluation') -----
- noContextSwitch
- "By adding this pragma to a method, it will not be preempt the current process on method activation if a higher-priority process is runnable. Any numbered primitive without side effects will do here."
-
-
- "Note that primitive 123 once was primitiveValueUninteruptibly but is no longer in use."
- self addPragma: (Pragma keyword: #primitive: arguments: #(123)).
-
- self advance.
- ^ true!




Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

Jaromir Matas
In reply to this post by marcel.taeumel
> However, I have no idea why the following happens:
>
> x := 0.
> [ [ x := 1 ] forkAt: 41 ] valueUnpreemptively.
> y := x == 1. "false :-("
>
>
> Or this:
>
> x := 0.
> [ [ x := 1 ] forkAt: 41 ] valueUnpreemptively.
> Transcript showln: 'foo'.
> y := x == 1. "false :-("

The reason is the #yield primitive 167 - it doesn't reflect the change of
priority as done in #valueUnpreemptively... Try to remove the primitive from
#yield and then it works ok
Regards,
Jaromir



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html

^[^ Jaromir
Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

marcel.taeumel
 Try to remove the primitive from #yield and then it works ok

Yes, removing the primitive form #yield will introduce one (or more) suspension points because of the (rather complex) fallback implementation. Yet, I cannot do that in a test. :-)

Best,
Marcel

Am 02.02.2021 14:14:14 schrieb jaromir <[hidden email]>:

> However, I have no idea why the following happens:

>
> x := 0.
> [ [ x := 1 ] forkAt: 41 ] valueUnpreemptively.
> y := x == 1. "false :-("
>
>
> Or this:
>
> x := 0.
> [ [ x := 1 ] forkAt: 41 ] valueUnpreemptively.
> Transcript showln: 'foo'.
> y := x == 1. "false :-("

The reason is the #yield primitive 167 - it doesn't reflect the change of
priority as done in #valueUnpreemptively... Try to remove the primitive from
#yield and then it works ok
Regards,
Jaromir



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html



Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

Christoph Thiede

Yet, I cannot do that in a test. :-)


Hypothetically, you could use a mock environment and subclass ProcessorScheduler. But this would get too complex for a single test ...
Do we have a good framework for such mocking experiments in Squeak? :-)

self mock: #Processor with: MockProcessorWithoutYield new during: [
    self doYourTestLogic].

or also:

self
    mock: Processor class >> #yield
    with: (Processor class >> #yield) decompile withoutPrimitiveNode generate
    during: [
        ...].

Best,
Christoph

Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Dienstag, 2. Februar 2021 14:22:34
An: squeak-dev
Betreff: Re: [squeak-dev] The Inbox: Compiler-mt.456.mcz
 
 Try to remove the primitive from #yield and then it works ok

Yes, removing the primitive form #yield will introduce one (or more) suspension points because of the (rather complex) fallback implementation. Yet, I cannot do that in a test. :-)

Best,
Marcel

Am 02.02.2021 14:14:14 schrieb jaromir <[hidden email]>:

> However, I have no idea why the following happens:
>
> x := 0.
> [ [ x := 1 ] forkAt: 41 ] valueUnpreemptively.
> y := x == 1. "false :-("
>
>
> Or this:
>
> x := 0.
> [ [ x := 1 ] forkAt: 41 ] valueUnpreemptively.
> Transcript showln: 'foo'.
> y := x == 1. "false :-("

The reason is the #yield primitive 167 - it doesn't reflect the change of
priority as done in #valueUnpreemptively... Try to remove the primitive from
#yield and then it works ok
Regards,
Jaromir



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html



Carpe Squeak!
Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

Jaromir Matas
In reply to this post by marcel.taeumel
> > Try to remove the primitive from #yield and then it works ok
>
> Yes, removing the primitive form #yield will introduce one (or more)
> suspension points because of the (rather complex) fallback implementation.
> Yet, I cannot do that in a test. :-)

Now I'm confused - it looks to me either yield primitive 167 or
#valueUnpreemptively behave incorrectly because your example

x := 0.
[ [ x := 1 ] forkAt: 41 ] valueUnpreemptively.
y := x == 1.

should definitely return true. In case yield primitive works as intended,
#valueUnpreemptively should change (replace Processor yield line to digest
the change of priority) or vice versa - or am I missing something?

J.



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html

^[^ Jaromir
Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

marcel.taeumel
Now I'm confused - it looks to me either yield primitive 167 or #valueUnpreemptively behave incorrectly

Hmm... I think that "Processor yield" should not only schedule the next runnable process at the same priority but also serve as a "classic" suspension point and consider higher-priority processes first.

Not sure whether this is "by design" or actually a bug... most of the time, you would not need "Processor yield" to also look for interrupts. There are typically enough other suspension points. Hmmmm...

Best,
Marcel

Am 02.02.2021 14:49:41 schrieb jaromir <[hidden email]>:

> > Try to remove the primitive from #yield and then it works ok
>
> Yes, removing the primitive form #yield will introduce one (or more)
> suspension points because of the (rather complex) fallback implementation.
> Yet, I cannot do that in a test. :-)

Now I'm confused - it looks to me either yield primitive 167 or
#valueUnpreemptively behave incorrectly because your example

x := 0.
[ [ x := 1 ] forkAt: 41 ] valueUnpreemptively.
y := x == 1.

should definitely return true. In case yield primitive works as intended,
#valueUnpreemptively should change (replace Processor yield line to digest
the change of priority) or vice versa - or am I missing something?

J.



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html



Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

Jaromir Matas
> Not sure whether this is "by design" or actually a bug... most of the time,
you would not need "Processor yield" to also look for interrupts. There are
typically enough other suspension points. Hmmmm...

Aaah, I guess I know what you mean - looking at the valueUnpreemptively
method the Processor yield was meant to let the same priority preempted
processes a chance to run but here we have a higher priority process
scheduled and yield doesn't look there. And when you change `activeProcess
priority: oldPriority` just like this there's a higher priority process
scheduled while a lower priority process running! Funny, I thought that
can't happen :D

valueUnpreemptively
        | activeProcess oldPriority result |
        activeProcess := Processor activeProcess.
        oldPriority := activeProcess priority.
        activeProcess priority: Processor highestPriority.
        result := self ensure: [activeProcess priority: oldPriority].
        "Yield after restoring priority to give the preempted processes a chance to
run"
        Processor yield.   "<-- replace by:
        [activeProcess resume] fork.
        activeProcess suspend."
        ^result

I wanted to suggest replacing the yield as above but it may be a more
general issue...

J



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html

^[^ Jaromir
Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

marcel.taeumel
 looking at the valueUnpreemptively
> method the Processor yield was meant to let the same priority preempted
> processes a chance to run

Not quite. If you are at 40 and get boosted up to 80, there can be preempted processes at any other priority in between. I would expect that "Processor yield" accounts for that. Other processes running at 40 do not matter because we have cooperative schedulding at each priority.

Best,
Marcel

Am 02.02.2021 15:18:15 schrieb jaromir <[hidden email]>:

> Not sure whether this is "by design" or actually a bug... most of the time,
you would not need "Processor yield" to also look for interrupts. There are
typically enough other suspension points. Hmmmm...

Aaah, I guess I know what you mean - looking at the valueUnpreemptively
method the Processor yield was meant to let the same priority preempted
processes a chance to run but here we have a higher priority process
scheduled and yield doesn't look there. And when you change `activeProcess
priority: oldPriority` just like this there's a higher priority process
scheduled while a lower priority process running! Funny, I thought that
can't happen :D

valueUnpreemptively
| activeProcess oldPriority result |
activeProcess := Processor activeProcess.
oldPriority := activeProcess priority.
activeProcess priority: Processor highestPriority.
result := self ensure: [activeProcess priority: oldPriority].
"Yield after restoring priority to give the preempted processes a chance to
run"
Processor yield. "<-- replace by:
[activeProcess resume] fork.
activeProcess suspend."
^result

I wanted to suggest replacing the yield as above but it may be a more
general issue...

J



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html



Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

Jaromir Matas
> If you are at 40 and get boosted up to 80, there can be preempted processes
at any other priority in between. I would expect that "Processor yield"
accounts for that.

Well, in that case #yield probably doesn't do that considering #yield's
comment: "Give other Processes at the *current priority* a chance to run."
J



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html

^[^ Jaromir
Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

Jaromir Matas
Actually, I'd place the problem in Process>>#priority: method - it should
make sure that if the active process downgrades it's priority below an
existing runnable process, the active process will automatically be
preempted - something like this (works for your examples):

Process>>priority: anInteger
        "Set the receiver's priority to anInteger."
        (anInteger >= Processor lowestPriority and:[anInteger <= Processor
highestPriority])
                ifTrue: [
                        priority := anInteger.
                        (self isActiveProcess and: [anInteger < Processor nextReadyProcess
priority])
                                ifTrue: [ [self resume] fork. self suspend ]
                        ]
                ifFalse: [self error: 'Invalid priority: ', anInteger printString]

And then the #yield primitive can remain as it is :)

J



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html

^[^ Jaromir
Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

Jaromir Matas
If you modify #priority behavior as per my previous message the
#valueUnpreemptively can be simplified:

valueUnpreemptively
        | activeProcess oldPriority |
        activeProcess := Processor activeProcess.
        oldPriority := activeProcess priority.
        activeProcess priority: Processor highestPriority.
        ^self ensure: [activeProcess priority: oldPriority].



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html

^[^ Jaromir
Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

Jaromir Matas
Hi Marcel,

same problem here:

x := 0.
[ [ x := 1 ] forkAt: 41 ] valueAt: 42.
y := x == 1. "false :-("

And the same solution: fix Process>>priority: and simplify #valueAt: method.

Regards,
Jaromir

BlockClosure>>valueAt: blockPriority
        "Evaluate the receiver (block), with another priority as the actual one
        and restore it afterwards. The caller should be careful with using
        higher priorities."
        | activeProcess result outsidePriority |
        activeProcess := Processor activeProcess.
        outsidePriority := activeProcess priority.
        activeProcess priority: blockPriority.
        result := self ensure: [activeProcess priority: outsidePriority].
* "Yield after restoring lower priority to give the preempted processes a  
        chance to run."
        blockPriority > outsidePriority
                ifTrue: [Processor yield].* / "this part doesn't work and can be removed"/
        ^ result



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html

^[^ Jaromir
Reply | Threaded
Open this post in threaded view
|

Re: The Inbox: Compiler-mt.456.mcz

Jaromir Matas
In reply to this post by marcel.taeumel
>
>
> Hi all!
>
> I would like to merge <noContextSwitchOnActivation> into Trunk. But I
> still need a nice test case. Should be independent from the JIT. Maybe a
> simple setter?
>
> foobar: value
>    <noContextSwitchOnActivation>
>    instVar := value
>
> ...
>
> [ test instVar should be 42 already ] forkAt: current + 1.
> self foobar: 42.
>
> ??
>

Hi Marcel,
is it even possible to test #valueNoContextSwitch? I'm trying to understand
what would that require: you'd like to catch a higher priority process
trying to interrupt (preempt) a block activation between the
#valueNoContextSwitch send and the first context switching point inside the
block - right? Like a non-primitive send etc. So it's a very short period of
time you're targeting before the first switching point. I was thinking along
the lines of:

x := 0.
[1 milliSecond wait. x := x+1000000] forkAt:41.
[[x:=x+1. x<1000000] whileTrue] valueNoContextSwitch.
x

but x returns  e.g. 1084476 meaning whileTrue must be a context switching
point (because it's a backward jump?) and 1 millisecond is a desperately
long period...

My question - is this at least the right understanding? If yes, could you
think of any time consuming operations that would not contain any switching
points? To get past the 1 msec? I'm really curious. Thanks!



-----
^[^ Jaromir
--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html

^[^ Jaromir