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!
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 commits@source.squeak.org commits@source.squeak.org: 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!
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 marcel.taeumel@hpi.de: 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 commits@source.squeak.org commits@source.squeak.org: 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!
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 marcel.taeumel@hpi.de: 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 marcel.taeumel@hpi.de: 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 commits@source.squeak.org commits@source.squeak.org: 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!
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
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 m@jaromir.net:
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
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 squeak-dev-bounces@lists.squeakfoundation.org 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 m@jaromir.net:
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
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
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 m@jaromir.net:
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
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
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 m@jaromir.net:
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
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
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
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
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
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
squeak-dev@lists.squeakfoundation.org