Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.3365.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.3365 Author: eem Time: 17 April 2024, 4:17:09.846667 pm UUID: d067e715-4de3-4931-8c6e-5884b5fbab91 Ancestors: VMMaker.oscog-eem.3364
First pass at getting threaded VM to work on Mac. Only call ioProcessEvents if teh platform doesn't care (doesn't define ioEventThreadAffinity, or defines it as 0) or the current thread id is the same as ioEventThreadAffinity.
Nuke vmOwnerAddress & vmOwnerFromMachineCode which were used only by the pre-C-atomics access code to generate the machine code accessors for vmOwner.
=============== Diff against VMMaker.oscog-eem.3364 ===============
Item was changed: ----- Method: CoInterpreterMT>>checkForEventsMayContextSwitch: (in category 'process primitive support') ----- checkForEventsMayContextSwitch: mayContextSwitch "Check for possible interrupts and handle one if necessary. Answer if a context switch has occurred." + | switched sema now threadingThwartsIOProcessEventsInvocation | - | switched sema now | <inline: false> <var: #now type: #usqLong> self assertSaneThreadAndProcess. cogit assertCStackWellAligned. statCheckForEvents := statCheckForEvents + 1.
"restore the stackLimit if it has been smashed." self restoreStackLimit. self externalWriteBackHeadFramePointers. self assert: stackPage = stackPages mostRecentlyUsedPage.
"Allow the platform to do anything it needs to do synchronously." self ioSynchronousCheckForEvents.
self checkCogCompiledCodeCompactionCalledFor.
objectMemory needGCFlag ifTrue: ["sufficientSpaceAfterGC: runs the incremental GC and then, if not enough space is available, the fullGC." (objectMemory sufficientSpaceAfterGC: 0) ifFalse: [self setSignalLowSpaceFlagAndSaveProcess]].
mayContextSwitch ifFalse: [^false].
switched := false. self assert: deferThreadSwitch not. deferThreadSwitch := true.
(profileProcess ~= objectMemory nilObject or: [nextProfileTick > 0 and:[self ioHighResClock >= nextProfileTick]]) ifTrue: [self zeroNextProfileTick. "Take a sample (if not already done so) for the profiler if it is active. This must be done before any of the synchronousSignals below or else we will attribute a pause in ioRelinquishProcessor to the newly activated process." profileProcess = objectMemory nilObject ifTrue: [profileProcess := self activeProcess. profileMethod := objectMemory nilObject]. "and signal the profiler semaphore if it is present" (profileSemaphore ~= objectMemory nilObject and: [self synchronousSignal: profileSemaphore]) ifTrue: [switched := true]].
self cppIf: #LRPCheck ifTrue: [self checkDeliveryOfLongRunningPrimitiveSignal ifTrue: [switched := true]].
objectMemory signalLowSpace ifTrue: [objectMemory signalLowSpace: false. "reset flag" sema := objectMemory splObj: TheLowSpaceSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]].
+ threadingThwartsIOProcessEventsInvocation := self checkInvokeIOProcessEvents: (now := self ioUTCMicroseconds). - "inIOProcessEvents prevents reentrancy into ioProcessEvents and allows disabling - ioProcessEvents e.g. for native GUIs. We would like to manage that here but can't - since the platform code may choose to call ioProcessEvents itself in various places." - false - ifTrue: - [((now := self ioUTCMicroseconds) >= nextPollUsecs - and: [inIOProcessEvents = 0]) ifTrue: - [statIOProcessEvents := statIOProcessEvents + 1. - inIOProcessEvents := inIOProcessEvents + 1. - self ioProcessEvents. "sets interruptPending if interrupt key pressed; may callback" - inIOProcessEvents > 0 ifTrue: - [inIOProcessEvents := inIOProcessEvents - 1]. - nextPollUsecs := now + 20000 - "msecs to wait before next call to ioProcessEvents. Note that strictly - speaking we might need to update 'now' at this point since - ioProcessEvents could take a very long time on some platforms"]] - ifFalse: - [(now := self ioUTCMicroseconds) >= nextPollUsecs ifTrue: - [statIOProcessEvents := statIOProcessEvents + 1. - self ioProcessEvents. "sets interruptPending if interrupt key pressed; may callback" - nextPollUsecs := now + 20000 - "msecs to wait before next call to ioProcessEvents. Note that strictly - speaking we might need to update 'now' at this point since - ioProcessEvents could take a very long time on some platforms"]].
interruptPending ifTrue: [interruptPending := false. "reset interrupt flag" sema := objectMemory splObj: TheInterruptSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]].
nextWakeupUsecs ~= 0 ifTrue: [now >= nextWakeupUsecs ifTrue: [nextWakeupUsecs := 0. "set timer interrupt to 0 for 'no timer'" sema := objectMemory splObj: TheTimerSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]]].
"signal any pending finalizations" pendingFinalizationSignals > 0 ifTrue: [pendingFinalizationSignals := 0. sema := objectMemory splObj: TheFinalizationSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]].
"signal all semaphores in semaphoresToSignal" self signalExternalSemaphores ifTrue: [switched := true].
deferThreadSwitch := false. + (threadingThwartsIOProcessEventsInvocation + or: [checkThreadActivation]) ifTrue: - checkThreadActivation ifTrue: [checkThreadActivation := false. self cedeToHigherPriorityThreads]. "N.B. This may not return if we do switch."
self threadSwitchIfNecessary: self activeProcess from: CSCheckEvents. ^switched!
Item was added: + ----- Method: CoInterpreterMT>>checkInvokeIOProcessEvents: (in category 'process primitive support') ----- + checkInvokeIOProcessEvents: now + "Some platforms allow event resaponse only from a subset of threads (e.g. on Mac, the main application thread). + Override to check if the platform allows us to invoke or not and answer true if ioProcessEvents should have been + invoked but wasn't because of thread affinity." + <inline: #always> + (self ioEventThreadAffinity > 0 + and: [self ioEventThreadAffinity ~= cogThreadManager getVMOwner]) ifTrue: + [^now >= nextPollUsecs]. + super checkInvokeIOProcessEvents: now. + ^false!
Item was removed: - ----- Method: CoInterpreterMT>>vmOwnerAddress (in category 'simulation') ----- - vmOwnerAddress - <doNotGenerate> - ^cogThreadManager vmOwnerAddress!
Item was removed: - ----- Method: CogThreadManager>>vmOwnerAddress (in category 'Cogit lock implementation') ----- - vmOwnerAddress - <api> "NB. For the JIT only, so it can generate the lock & unlock functions." - <returnTypeC: #usqInt> - self error: 'Deprecated!! Replaced by proper atomic functions'. - ^self - cCode: [(self addressOf: vmOwner) asUnsignedInteger] - inSmalltalk: [cogit simulatedReadWriteVariableAddress: #vmOwnerFromMachineCode in: self]!
Item was removed: - ----- Method: CogThreadManager>>vmOwnerFromMachineCode (in category 'Cogit lock implementation') ----- - vmOwnerFromMachineCode - <doNotGenerate> - self error: 'Deprecated!! Replaced by proper atomic C functions'. - ^vmOwner!
Item was removed: - ----- Method: CogThreadManager>>vmOwnerFromMachineCode: (in category 'Cogit lock implementation') ----- - vmOwnerFromMachineCode: aValue - <doNotGenerate> - self error: 'Deprecated!! Replaced by proper atomic C functions'. - self assert: (aValue between: 0 and: numThreads). - vmOwner := aValue!
Item was changed: ----- Method: StackInterpreter>>checkForEventsMayContextSwitch: (in category 'process primitive support') ----- checkForEventsMayContextSwitch: mayContextSwitch "Check for possible interrupts and handle one if necessary. Answer if a context switch has occurred." | switched sema now | <inline: false> <var: #now type: #usqLong> statCheckForEvents := statCheckForEvents + 1.
"restore the stackLimit if it has been smashed." self restoreStackLimit. self externalWriteBackHeadFramePointers. self assert: stackPage = stackPages mostRecentlyUsedPage.
"Allow the platform to do anything it needs to do synchronously." self ioSynchronousCheckForEvents.
self checkCogCompiledCodeCompactionCalledFor.
objectMemory needGCFlag ifTrue: ["sufficientSpaceAfterGC: runs the incremental GC and then, if not enough space is available, the fullGC." (objectMemory sufficientSpaceAfterGC: 0) ifFalse: [self setSignalLowSpaceFlagAndSaveProcess]].
mayContextSwitch ifFalse: [^false].
switched := false.
(profileProcess ~= objectMemory nilObject or: [nextProfileTick > 0 and:[self ioHighResClock >= nextProfileTick]]) ifTrue: [self zeroNextProfileTick. "Take a sample (if not already done so) for the profiler if it is active. This must be done before any of the synchronousSignals below or else we will attribute a pause in ioRelinquishProcessor to the newly activated process." profileProcess = objectMemory nilObject ifTrue: [profileProcess := self activeProcess. profileMethod := objectMemory nilObject]. "and signal the profiler semaphore if it is present" (profileSemaphore ~= objectMemory nilObject and: [self synchronousSignal: profileSemaphore]) ifTrue: [switched := true]].
self cppIf: #LRPCheck ifTrue: [self checkDeliveryOfLongRunningPrimitiveSignal ifTrue: [switched := true]].
objectMemory signalLowSpace ifTrue: [objectMemory signalLowSpace: false. "reset flag" sema := objectMemory splObj: TheLowSpaceSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]].
+ self checkInvokeIOProcessEvents: (now := self ioUTCMicroseconds). - "inIOProcessEvents prevents reentrancy into ioProcessEvents and allows disabling - ioProcessEvents e.g. for native GUIs. We would like to manage that here but can't - since the platform code may choose to call ioProcessEvents itself in various places." - false - ifTrue: - [((now := self ioUTCMicroseconds) >= nextPollUsecs - and: [inIOProcessEvents = 0]) ifTrue: - [statIOProcessEvents := statIOProcessEvents + 1. - inIOProcessEvents := inIOProcessEvents + 1. - self ioProcessEvents. "sets interruptPending if interrupt key pressed; may callback" - inIOProcessEvents > 0 ifTrue: - [inIOProcessEvents := inIOProcessEvents - 1]. - nextPollUsecs := now + 20000 - "msecs to wait before next call to ioProcessEvents. Note that strictly - speaking we might need to update 'now' at this point since - ioProcessEvents could take a very long time on some platforms"]] - ifFalse: - [(now := self ioUTCMicroseconds) >= nextPollUsecs ifTrue: - [statIOProcessEvents := statIOProcessEvents + 1. - self ioProcessEvents. "sets interruptPending if interrupt key pressed; may callback" - nextPollUsecs := now + 20000 - "msecs to wait before next call to ioProcessEvents. Note that strictly - speaking we might need to update 'now' at this point since - ioProcessEvents could take a very long time on some platforms"]].
interruptPending ifTrue: [interruptPending := false. "reset interrupt flag" sema := objectMemory splObj: TheInterruptSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]].
nextWakeupUsecs ~= 0 ifTrue: [now >= nextWakeupUsecs ifTrue: [nextWakeupUsecs := 0. "set timer interrupt to 0 for 'no timer'" sema := objectMemory splObj: TheTimerSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]]].
"signal any pending finalizations" pendingFinalizationSignals > 0 ifTrue: [pendingFinalizationSignals := 0. sema := objectMemory splObj: TheFinalizationSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]].
"signal all semaphores in semaphoresToSignal" self signalExternalSemaphores ifTrue: [switched := true].
^switched!
Item was added: + ----- Method: StackInterpreter>>checkInvokeIOProcessEvents: (in category 'process primitive support') ----- + checkInvokeIOProcessEvents: now + "inIOProcessEvents prevents reentrancy into ioProcessEvents and allows disabling + ioProcessEvents e.g. for native GUIs. We would like to manage that here but can't + since the platform code may choose to call ioProcessEvents itself in various places." + <inline: #always> + false + ifTrue: + [(now >= nextPollUsecs + and: [inIOProcessEvents = 0]) ifTrue: + [statIOProcessEvents := statIOProcessEvents + 1. + inIOProcessEvents := inIOProcessEvents + 1. + self ioProcessEvents. "sets interruptPending if interrupt key pressed; may callback" + inIOProcessEvents > 0 ifTrue: + [inIOProcessEvents := inIOProcessEvents - 1]. + nextPollUsecs := now + 20000 + "msecs to wait before next call to ioProcessEvents. Note that strictly + speaking we might need to update 'now' at this point since + ioProcessEvents could take a very long time on some platforms"]] + ifFalse: + [now >= nextPollUsecs ifTrue: + [statIOProcessEvents := statIOProcessEvents + 1. + self ioProcessEvents. "sets interruptPending if interrupt key pressed; may callback" + nextPollUsecs := now + 20000 + "msecs to wait before next call to ioProcessEvents. Note that strictly + speaking we might need to update 'now' at this point since + ioProcessEvents could take a very long time on some platforms"]].!
Hi all, Hi Marcel,
apologies for breaking the VM build in recent commits. I shall have things fixed before Monday. Bear with me.
On Wed, Apr 17, 2024 at 4:17 PM commits@source.squeak.org wrote:
Eliot Miranda uploaded a new version of VMMaker to project VM Maker: http://source.squeak.org/VMMaker/VMMaker.oscog-eem.3365.mcz
==================== Summary ====================
Name: VMMaker.oscog-eem.3365 Author: eem Time: 17 April 2024, 4:17:09.846667 pm UUID: d067e715-4de3-4931-8c6e-5884b5fbab91 Ancestors: VMMaker.oscog-eem.3364
First pass at getting threaded VM to work on Mac. Only call ioProcessEvents if teh platform doesn't care (doesn't define ioEventThreadAffinity, or defines it as 0) or the current thread id is the same as ioEventThreadAffinity.
Nuke vmOwnerAddress & vmOwnerFromMachineCode which were used only by the pre-C-atomics access code to generate the machine code accessors for vmOwner.
=============== Diff against VMMaker.oscog-eem.3364 ===============
Item was changed: ----- Method: CoInterpreterMT>>checkForEventsMayContextSwitch: (in category 'process primitive support') ----- checkForEventsMayContextSwitch: mayContextSwitch "Check for possible interrupts and handle one if necessary. Answer if a context switch has occurred."
| switched sema now threadingThwartsIOProcessEventsInvocation |
| switched sema now | <inline: false> <var: #now type: #usqLong> self assertSaneThreadAndProcess. cogit assertCStackWellAligned. statCheckForEvents := statCheckForEvents + 1. "restore the stackLimit if it has been smashed." self restoreStackLimit. self externalWriteBackHeadFramePointers. self assert: stackPage = stackPages mostRecentlyUsedPage. "Allow the platform to do anything it needs to do synchronously." self ioSynchronousCheckForEvents. self checkCogCompiledCodeCompactionCalledFor. objectMemory needGCFlag ifTrue: ["sufficientSpaceAfterGC: runs the incremental GC and then, if not enough space is available, the fullGC." (objectMemory sufficientSpaceAfterGC: 0) ifFalse: [self setSignalLowSpaceFlagAndSaveProcess]]. mayContextSwitch ifFalse: [^false]. switched := false. self assert: deferThreadSwitch not. deferThreadSwitch := true. (profileProcess ~= objectMemory nilObject or: [nextProfileTick > 0 and:[self ioHighResClock >=
nextProfileTick]]) ifTrue: [self zeroNextProfileTick. "Take a sample (if not already done so) for the profiler if it is active. This must be done before any of the synchronousSignals below or else we will attribute a pause in ioRelinquishProcessor to the newly activated process." profileProcess = objectMemory nilObject ifTrue: [profileProcess := self activeProcess. profileMethod := objectMemory nilObject]. "and signal the profiler semaphore if it is present" (profileSemaphore ~= objectMemory nilObject and: [self synchronousSignal: profileSemaphore]) ifTrue: [switched := true]].
self cppIf: #LRPCheck ifTrue: [self checkDeliveryOfLongRunningPrimitiveSignal
ifTrue: [switched := true]].
objectMemory signalLowSpace ifTrue: [objectMemory signalLowSpace: false. "reset flag" sema := objectMemory splObj: TheLowSpaceSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]].
threadingThwartsIOProcessEventsInvocation := self
checkInvokeIOProcessEvents: (now := self ioUTCMicroseconds).
"inIOProcessEvents prevents reentrancy into ioProcessEvents and
allows disabling
ioProcessEvents e.g. for native GUIs. We would like to manage
that here but can't
since the platform code may choose to call ioProcessEvents itself
in various places."
false
ifTrue:
[((now := self ioUTCMicroseconds) >= nextPollUsecs
and: [inIOProcessEvents = 0]) ifTrue:
[statIOProcessEvents :=
statIOProcessEvents + 1.
inIOProcessEvents := inIOProcessEvents +
self ioProcessEvents. "sets
interruptPending if interrupt key pressed; may callback"
inIOProcessEvents > 0 ifTrue:
[inIOProcessEvents :=
inIOProcessEvents - 1].
nextPollUsecs := now + 20000
"msecs to wait before next call to
ioProcessEvents. Note that strictly
speaking we might need to update 'now'
at this point since
ioProcessEvents could take a very long
time on some platforms"]]
ifFalse:
[(now := self ioUTCMicroseconds) >= nextPollUsecs
ifTrue:
[statIOProcessEvents :=
statIOProcessEvents + 1.
self ioProcessEvents. "sets
interruptPending if interrupt key pressed; may callback"
nextPollUsecs := now + 20000
"msecs to wait before next call to
ioProcessEvents. Note that strictly
speaking we might need to update 'now'
at this point since
ioProcessEvents could take a very long
time on some platforms"]].
interruptPending ifTrue: [interruptPending := false. "reset interrupt flag" sema := objectMemory splObj: TheInterruptSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]]. nextWakeupUsecs ~= 0 ifTrue: [now >= nextWakeupUsecs ifTrue: [nextWakeupUsecs := 0. "set timer interrupt to 0 for 'no timer'" sema := objectMemory splObj: TheTimerSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]]]. "signal any pending finalizations" pendingFinalizationSignals > 0 ifTrue: [pendingFinalizationSignals := 0. sema := objectMemory splObj: TheFinalizationSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]]. "signal all semaphores in semaphoresToSignal" self signalExternalSemaphores ifTrue: [switched := true]. deferThreadSwitch := false.
(threadingThwartsIOProcessEventsInvocation
or: [checkThreadActivation]) ifTrue:
checkThreadActivation ifTrue: [checkThreadActivation := false. self cedeToHigherPriorityThreads]. "N.B. This may not
return if we do switch."
self threadSwitchIfNecessary: self activeProcess from:
CSCheckEvents. ^switched!
Item was added:
- ----- Method: CoInterpreterMT>>checkInvokeIOProcessEvents: (in category
'process primitive support') -----
- checkInvokeIOProcessEvents: now
"Some platforms allow event resaponse only from a subset of
threads (e.g. on Mac, the main application thread).
Override to check if the platform allows us to invoke or not and
answer true if ioProcessEvents should have been
invoked but wasn't because of thread affinity."
<inline: #always>
(self ioEventThreadAffinity > 0
and: [self ioEventThreadAffinity ~= cogThreadManager getVMOwner])
ifTrue:
[^now >= nextPollUsecs].
super checkInvokeIOProcessEvents: now.
^false!
Item was removed:
- ----- Method: CoInterpreterMT>>vmOwnerAddress (in category 'simulation')
- vmOwnerAddress
<doNotGenerate>
^cogThreadManager vmOwnerAddress!
Item was removed:
- ----- Method: CogThreadManager>>vmOwnerAddress (in category 'Cogit lock
implementation') -----
- vmOwnerAddress
<api> "NB. For the JIT only, so it can generate the lock & unlock
functions."
<returnTypeC: #usqInt>
self error: 'Deprecated!! Replaced by proper atomic functions'.
^self
cCode: [(self addressOf: vmOwner) asUnsignedInteger]
inSmalltalk: [cogit simulatedReadWriteVariableAddress:
#vmOwnerFromMachineCode in: self]!
Item was removed:
- ----- Method: CogThreadManager>>vmOwnerFromMachineCode (in category
'Cogit lock implementation') -----
- vmOwnerFromMachineCode
<doNotGenerate>
self error: 'Deprecated!! Replaced by proper atomic C functions'.
^vmOwner!
Item was removed:
- ----- Method: CogThreadManager>>vmOwnerFromMachineCode: (in category
'Cogit lock implementation') -----
- vmOwnerFromMachineCode: aValue
<doNotGenerate>
self error: 'Deprecated!! Replaced by proper atomic C functions'.
self assert: (aValue between: 0 and: numThreads).
vmOwner := aValue!
Item was changed: ----- Method: StackInterpreter>>checkForEventsMayContextSwitch: (in category 'process primitive support') ----- checkForEventsMayContextSwitch: mayContextSwitch "Check for possible interrupts and handle one if necessary. Answer if a context switch has occurred." | switched sema now | <inline: false> <var: #now type: #usqLong> statCheckForEvents := statCheckForEvents + 1.
"restore the stackLimit if it has been smashed." self restoreStackLimit. self externalWriteBackHeadFramePointers. self assert: stackPage = stackPages mostRecentlyUsedPage. "Allow the platform to do anything it needs to do synchronously." self ioSynchronousCheckForEvents. self checkCogCompiledCodeCompactionCalledFor. objectMemory needGCFlag ifTrue: ["sufficientSpaceAfterGC: runs the incremental GC and then, if not enough space is available, the fullGC." (objectMemory sufficientSpaceAfterGC: 0) ifFalse: [self setSignalLowSpaceFlagAndSaveProcess]]. mayContextSwitch ifFalse: [^false]. switched := false. (profileProcess ~= objectMemory nilObject or: [nextProfileTick > 0 and:[self ioHighResClock >=
nextProfileTick]]) ifTrue: [self zeroNextProfileTick. "Take a sample (if not already done so) for the profiler if it is active. This must be done before any of the synchronousSignals below or else we will attribute a pause in ioRelinquishProcessor to the newly activated process." profileProcess = objectMemory nilObject ifTrue: [profileProcess := self activeProcess. profileMethod := objectMemory nilObject]. "and signal the profiler semaphore if it is present" (profileSemaphore ~= objectMemory nilObject and: [self synchronousSignal: profileSemaphore]) ifTrue: [switched := true]].
self cppIf: #LRPCheck ifTrue: [self checkDeliveryOfLongRunningPrimitiveSignal
ifTrue: [switched := true]].
objectMemory signalLowSpace ifTrue: [objectMemory signalLowSpace: false. "reset flag" sema := objectMemory splObj: TheLowSpaceSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]].
self checkInvokeIOProcessEvents: (now := self ioUTCMicroseconds).
"inIOProcessEvents prevents reentrancy into ioProcessEvents and
allows disabling
ioProcessEvents e.g. for native GUIs. We would like to manage
that here but can't
since the platform code may choose to call ioProcessEvents itself
in various places."
false
ifTrue:
[((now := self ioUTCMicroseconds) >= nextPollUsecs
and: [inIOProcessEvents = 0]) ifTrue:
[statIOProcessEvents :=
statIOProcessEvents + 1.
inIOProcessEvents := inIOProcessEvents +
self ioProcessEvents. "sets
interruptPending if interrupt key pressed; may callback"
inIOProcessEvents > 0 ifTrue:
[inIOProcessEvents :=
inIOProcessEvents - 1].
nextPollUsecs := now + 20000
"msecs to wait before next call to
ioProcessEvents. Note that strictly
speaking we might need to update 'now'
at this point since
ioProcessEvents could take a very long
time on some platforms"]]
ifFalse:
[(now := self ioUTCMicroseconds) >= nextPollUsecs
ifTrue:
[statIOProcessEvents :=
statIOProcessEvents + 1.
self ioProcessEvents. "sets
interruptPending if interrupt key pressed; may callback"
nextPollUsecs := now + 20000
"msecs to wait before next call to
ioProcessEvents. Note that strictly
speaking we might need to update 'now'
at this point since
ioProcessEvents could take a very long
time on some platforms"]].
interruptPending ifTrue: [interruptPending := false. "reset interrupt flag" sema := objectMemory splObj: TheInterruptSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]]. nextWakeupUsecs ~= 0 ifTrue: [now >= nextWakeupUsecs ifTrue: [nextWakeupUsecs := 0. "set timer interrupt to 0 for 'no timer'" sema := objectMemory splObj: TheTimerSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]]]. "signal any pending finalizations" pendingFinalizationSignals > 0 ifTrue: [pendingFinalizationSignals := 0. sema := objectMemory splObj: TheFinalizationSemaphore. (sema ~= objectMemory nilObject and: [self synchronousSignal: sema]) ifTrue: [switched := true]]. "signal all semaphores in semaphoresToSignal" self signalExternalSemaphores ifTrue: [switched := true]. ^switched!
Item was added:
- ----- Method: StackInterpreter>>checkInvokeIOProcessEvents: (in category
'process primitive support') -----
- checkInvokeIOProcessEvents: now
"inIOProcessEvents prevents reentrancy into ioProcessEvents and
allows disabling
ioProcessEvents e.g. for native GUIs. We would like to manage
that here but can't
since the platform code may choose to call ioProcessEvents itself
in various places."
<inline: #always>
false
ifTrue:
[(now >= nextPollUsecs
and: [inIOProcessEvents = 0]) ifTrue:
[statIOProcessEvents :=
statIOProcessEvents + 1.
inIOProcessEvents := inIOProcessEvents +
self ioProcessEvents. "sets
interruptPending if interrupt key pressed; may callback"
inIOProcessEvents > 0 ifTrue:
[inIOProcessEvents :=
inIOProcessEvents - 1].
nextPollUsecs := now + 20000
"msecs to wait before next call to
ioProcessEvents. Note that strictly
speaking we might need to update 'now'
at this point since
ioProcessEvents could take a very long
time on some platforms"]]
ifFalse:
[now >= nextPollUsecs ifTrue:
[statIOProcessEvents :=
statIOProcessEvents + 1.
self ioProcessEvents. "sets
interruptPending if interrupt key pressed; may callback"
nextPollUsecs := now + 20000
"msecs to wait before next call to
ioProcessEvents. Note that strictly
speaking we might need to update 'now'
at this point since
ioProcessEvents could take a very long
time on some platforms"]].!
Aye, aye. No worries. :-)
Best, Marcel
Am 18.04.2024 19:14:11 schrieb Eliot Miranda eliot.miranda@gmail.com:
vm-dev@lists.squeakfoundation.org