VM Maker: VMMaker.oscog-eem.2893.mcz

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

VM Maker: VMMaker.oscog-eem.2893.mcz

Eliot Miranda uploaded a new version of VMMaker to project VM Maker:

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

Name: VMMaker.oscog-eem.2893
Author: eem
Time: 20 November 2020, 12:18:59.36201 pm
UUID: 80846f05-27f9-4e14-a97e-11dcde420a0b
Ancestors: VMMaker.oscog-eem.2892

Make sure that primitiveRelinquishProcessor has PrimCallMayEndureCodeCompaction set.

Change simulation away from MultiProcessor to switching register contents in CogThreadManager>>#tryLockVMOwnerTo:, which invokes Cogit>>#tryLockVMOwnerTo:, hence change senders of tryLockVMOwnerTo:.  Retain Multiprocessor via an option only.

Fix termination of processes on shutdown.

Put a breakpoint in CogVMSimulator>>#ownVM: for now.

Eliminate unused stuff from CogVMThread.

=============== Diff against VMMaker.oscog-eem.2892 ===============

Item was changed:
  CoInterpreterPrimitives subclass: #CoInterpreterMT
  instanceVariableNames: 'cogThreadManager checkThreadActivation maxWaitingPriority foreignCallbackPriority deferThreadSwitch disowningVMThread disownCount foreignCallbackProcessSlot willNotThreadWarnCount activeProcessAffined relinquishing processHasThreadId noThreadingOfGUIThread reenterThreadSchedulingLoop'
+ classVariableNames: 'DisownFlagsShift DisownVMForProcessorRelinquish LockGUIThreadFlag LockGUIThreadShift OwnVMForeignThreadFlag PrimNumberRelinquishProcessor ProcessUnaffinedOnDisown ReturnToThreadSchedulingLoop VMAlreadyOwnedHenceDoNotDisown'
- classVariableNames: 'DisownFlagsShift DisownVMForProcessorRelinquish LockGUIThreadFlag LockGUIThreadShift OwnVMForeignThreadFlag ProcessUnaffinedOnDisown ReturnToThreadSchedulingLoop VMAlreadyOwnedHenceDoNotDisown'
  poolDictionaries: 'VMThreadingConstants'
  category: 'VMMaker-Multithreading'!

Item was changed:
  ----- Method: CoInterpreterMT class>>initializePrimitiveTable (in category 'initialization') -----
  super initializePrimitiveTable.
+ PrimNumberRelinquishProcessor := 230.
  COGMTVM ifTrue:
  [(227 to: 229) do:
  [:pidx| self assert: (PrimitiveTable at: pidx + 1) = #primitiveFail].
  at: 227 + 1 put: #primitiveVMCurrentThreadId;
  at: 228 + 1 put: #primitiveProcessBoundThreadId;
  at: 229 + 1 put: #primitiveProcessBindToThreadId]!

Item was added:
+ ----- Method: CoInterpreterMT>>assertValidNewMethodPropertyFlags (in category 'simulation') -----
+ assertValidNewMethodPropertyFlags
+ <cmacro: '() 0'> "simulation only"
+ self assert: (objectMemory addressCouldBeObj: newMethod).
+ self assert: (objectMemory isCompiledMethod: newMethod).
+ self assert: (self primitiveIndexOf: newMethod) > 0.
+ self assert: ((self primitivePropertyFlags: (self primitiveIndexOf: newMethod)) anyMask: PrimCallMayEndureCodeCompaction)!

Item was changed:
  ----- Method: CoInterpreterMT>>disownVM: (in category 'vm scheduling') -----
  disownVM: flags
  "Release the VM to other threads and answer the current thread's index.
  Currently valid flags:
  DisownVMForFFICall - informs the VM that it is entering an FFI call
  DisownVMForThreading - informs the VM that it is entering code during which threading should be permitted
  OwnVMForeignThreadFlag - indicates lowest-level entry from a foreign thread
  - not to be used explicitly by clients
  - only set by ownVMFromUnidentifiedThread
  - indicates an ownVM from a callback was made when
   the vm was still owned.
  - not to be used explicitly by clients
  - only set by ownVMFromUnidentifiedThread
  This is the entry-point for plugins and primitives that wish to release the VM while
  performing some operation that may potentially block, and for callbacks returning
  back to some blocking operation.  If this thread does not reclaim the VM before-
  hand then when the next heartbeat occurs the thread manager will schedule a
  thread to acquire the VM which may start running the VM in place of this thread.
  N.B. Most of the state needed to resume after preemption is set in preemptDisowningThread."
  <inline: false>
  | vmThread result |
  <var: #vmThread type: #'CogVMThread *'>
  self assert: self successful.
  cogit recordEventTrace ifTrue:
  [self recordTrace: TraceDisownVM thing: (objectMemory integerObjectOf: flags) source: 0].
  processHasThreadId ifFalse:
  [willNotThreadWarnCount < 10 ifTrue:
  [self print: 'warning: VM parameter 48 indicates Process doesn''t have threadId; VM will not thread'; cr.
  willNotThreadWarnCount := willNotThreadWarnCount + 1]].
  vmThread := cogThreadManager currentVMThread.
  (flags anyMask: VMAlreadyOwnedHenceDoNotDisown) ifTrue:
  [disowningVMThread := vmThread.
  vmThread state: CTMUnavailable.
  self assertCStackPointersBelongToCurrentThread.
+ self assertValidNewMethodPropertyFlags.
  (flags anyMask: DisownVMForProcessorRelinquish) ifTrue:
  [| proc |
  (proc := objectMemory splObj: foreignCallbackProcessSlot) ~= objectMemory nilObject ifTrue:
  [foreignCallbackPriority := self quickFetchInteger: PriorityIndex ofObject: proc].
  relinquishing := true.
  self sqLowLevelMFence].
  (noThreadingOfGUIThread and: [self inGUIThread]) ifTrue:
  [^vmThread index
  + LockGUIThreadFlag
  + (activeProcessAffined ifTrue: [0] ifFalse: [ProcessUnaffinedOnDisown])
  + (flags << DisownFlagsShift)].
  disownCount := disownCount + 1.
  disowningVMThread := vmThread.
  "self cr; cr; print: 'disownVM  Csp: '; printHex: vmThread cStackPointer; cr.
  (0 to: 16 by: 4) do:
  self print: ' *(esp+'; printNum: offset; print: ': '; printHex: (stackPages longAt: cogit processor sp + offset); cr].
  cogit processor printIntegerRegistersOn: Transcript."
  "OwnVMForeignThreadFlag indicates lowest-level of entry by a foreign
  thread. If that's where we are then release the vmThread.  Otherwise
  indicate the vmThread is off doing something outside of the VM."
  (flags anyMask: OwnVMForeignThreadFlag)
  ["I don't think this is quite right.  Josh's use case is creating some foreign thread and then registering
  it with the VM. That's not the same as binding a process to a foreign thread given that the foreign
  callback process is about to terminate anyway (it is returning from a callback here).  So do we need
  an additional concept, that of a vmThread being either of the set known to the VM or floating?"
  self flag: 'issue with registering foreign threads with the VM'.
  (self isBoundProcess: self activeProcess) ifFalse:
  [cogThreadManager unregisterVMThread: vmThread]]
  ifFalse: [vmThread state: CTMUnavailable].
  result := vmThread index
  + (activeProcessAffined ifTrue: [0] ifFalse: [ProcessUnaffinedOnDisown])
  + (flags << DisownFlagsShift).
  cogThreadManager releaseVM.

Item was changed:
  ----- Method: CoInterpreterMT>>ownVMFromUnidentifiedThread (in category 'vm scheduling') -----
  "Attempt to take ownership from a thread that as yet doesn't know its index.
  This supports callbacks where the callback could originate from any thread.
  Answer 0 if the owning thread is known to the VM.
  Answer 1 if the owning thread is unknown to the VM and now owns the VM.
  Answer -1 if the owning thread is unknown to the VM and fails to own the VM.
  Answer -2 if the owning thread is unknown to the VM and there is no foreign callback process installed."
  | count threadIndex vmThread |
  <var: #vmThread type: #'CogVMThread *'>
  <inline: false>
  (threadIndex := cogThreadManager ioGetThreadLocalThreadIndex) ~= 0 ifTrue:
  [ "this is a callback from a known thread"
  (cogThreadManager vmOwnerIs: threadIndex) ifTrue: "the VM has not been disowned"
  [self assert: (disowningVMThread isNil or: [disowningVMThread = self currentVMThread]).
  disowningVMThread := nil.
  self currentVMThread state: CTMAssignableOrInVM.
  ^self ownVM: threadIndex].
  foreignCallbackPriority = 0 ifTrue:
  count := 0.
  "If the current thread doesn't have an index it's new to the vm
  and we need to allocate a new threadInfo, failing if we can't.
  We also need a process in the foreignCallbackProcessSlot upon
  which to run the thread's eventual callback."
+ [[cogThreadManager tryLockVMOwnerTo: cogThreadManager ioCurrentOSThread asUnsignedInteger] whileFalse:
- [[cogit tryLockVMOwnerTo: cogThreadManager ioCurrentOSThread asUnsignedInteger] whileFalse:
  [self waitingPriorityIsAtLeast: foreignCallbackPriority.
  cogThreadManager ioTransferTimeslice].
  (objectMemory splObj: foreignCallbackProcessSlot) ~= objectMemory nilObject] whileFalse:
  [cogThreadManager releaseVM.
  (count := count + 1) > 1000 ifTrue:
  cogThreadManager ioMilliSleep: 1].
  vmThread := cogThreadManager unusedThreadInfo.
  "N.B.  Keep the VM locked anonymously so that we reserve the non-nil ForeignCallbackProcess
  for this thread, avoiding the race between competing foreign callbacks.  The acquireVMFor: in
  ownVM: will set the vmOwner to the actual index.  So only unlock on failure."
  vmThread ifNil:
  [cogThreadManager releaseVM.
  cogThreadManager setVMOwner: vmThread index.
  state: CTMWantingOwnership;
  priority: foreignCallbackPriority.
  cogThreadManager registerVMThread: vmThread.
  ^self ownVM: vmThread index + OwnVMForeignThreadFlag!

Item was added:
+ ----- Method: CoInterpreterMT>>primitivePropertyFlagsForSpur: (in category 'cog jit support') -----
+ primitivePropertyFlagsForSpur: primIndex
+ <inline: true>
+ "Answer any special requirements of the given primitive.  Spur always needs to set
+ primitiveFunctionPointer and newMethod so primitives can retry on failure due to forwarders."
+ self cCode: [] inSmalltalk: [#(primitiveRelinquishProcessor)]. "For senders..."
+ primIndex = PrimNumberRelinquishProcessor ifTrue:
+ [^profileSemaphore ~= objectMemory nilObject
+ ifTrue: [PrimCallNeedsPrimitiveFunction + PrimCallNeedsNewMethod + PrimCallMayEndureCodeCompaction + PrimCallCollectsProfileSamples]
+ ifFalse: [PrimCallNeedsPrimitiveFunction + PrimCallNeedsNewMethod + PrimCallMayEndureCodeCompaction]].
+ ^super primitivePropertyFlagsForSpur: primIndex!

Item was changed:
  ----- Method: CoInterpreterMT>>threadSchedulingLoopImplementation: (in category 'vm scheduling') -----
  threadSchedulingLoopImplementation: vmThread
  "Enter a loop attempting to run the VM with the highest priority process and
  blocking on the thread's OS semaphore when unable to run that process.
  We will return to this via threadSwitchIfNecessary:from: which is called in the
  middle of transferTo:from: once the active process has been stored in the scheduler."
  <var: #vmThread type: #'CogVMThread *'>
- | attemptToRun |
  <inline: false>
  self _setjmp: reenterThreadSchedulingLoop.
  [self assert: vmThread state = CTMAssignableOrInVM.
+ (cogThreadManager tryLockVMOwnerTo: vmThread index) ifTrue:
+ ["If relinquishing is true, then primitiveRelinquishProcessor has disowned the
+  VM and only a returning call or callback should take ownership in that case."
+ relinquishing
+ ifTrue: [cogThreadManager releaseVM]
+ ifFalse: [self tryToExecuteSmalltalk: vmThread]].
- attemptToRun := false.
- (cogThreadManager vmOwnerIs: vmThread index)
- ifTrue: [attemptToRun := true]
- ifFalse:
- [(cogit tryLockVMOwnerTo: vmThread index) ifTrue:
- ["If relinquishing is true, then primitiveRelinquishProcessor has disowned the
-  VM and only a returning call or callback should take ownership in that case."
- relinquishing
- ifTrue: [cogThreadManager releaseVM]
- ifFalse: [attemptToRun := true]]].
- attemptToRun ifTrue:
- [self tryToExecuteSmalltalk: vmThread].
  (cogThreadManager vmOwnerIs: vmThread index) ifFalse:
  [cogThreadManager waitForWork: vmThread].
  true] whileTrue!

Item was changed:
  ----- Method: CoInterpreterMT>>tryToExecuteSmalltalk: (in category 'vm scheduling') -----
  tryToExecuteSmalltalk: vmThread
  "Attempt to run the current process, if it exists, on the given vmThread."
  <var: #vmThread type: #'CogVMThread *'>
  | dvmt activeProc ownerIndex |
  <var: #dvmt type: #'CogVMThread *'>
  self assert: (cogThreadManager vmOwnerIs: vmThread index).
  self assert: cogThreadManager ioGetThreadLocalThreadIndex = vmThread index.
  dvmt := disowningVMThread.
  ifNil: [activeProc := self activeProcess]
  [self preemptDisowningThread.
  activeProc := self wakeHighestPriority.
  ifNil: [activeProc := objectMemory nilObject]
  ifNotNil: [objectMemory
  storePointerUnchecked: MyListIndex
  ofObject: activeProc
  withValue: objectMemory nilObject].
  storePointer: ActiveProcessIndex
  ofObject: self schedulerPointer
  withValue: activeProc].
  activeProc = objectMemory nilObject ifTrue:
  [cogThreadManager releaseVM.
  ownerIndex := self ownerIndexOfProcess: activeProc.
  (ownerIndex = 0 or: [cogThreadManager vmOwnerIs: ownerIndex]) ifTrue:
  [self assert: (objectMemory fetchPointer: MyListIndex ofObject: self activeProcess) = objectMemory nilObject.
  (objectMemory fetchPointer: SuspendedContextIndex ofObject: activeProc) ~= objectMemory nilObject ifTrue:
  [self externalSetStackPageAndPointersForSuspendedContextOfProcess: activeProc].
+ instructionPointer = cogit ceReturnToInterpreterPC ifTrue:
+ [self deny: (self isMachineCodeFrame: framePointer).
+ instructionPointer := self iframeSavedIP: framePointer].
  self enterSmalltalkExecutive.
  "When we return here we should have already given up
   the VM and so we cannot touch any interpreter state."
  cogThreadManager wakeVMThreadFor: ownerIndex!

Item was changed:
  CogClass subclass: #CogThreadManager
(excessive size, no diff calculated)

Item was changed:
  ----- Method: CogThreadManager class>>declareCVarsIn: (in category 'translation') -----
  declareCVarsIn: cCodeGen
  removeVariable: 'coInterpreter';
  removeVariable: 'cogit';
  removeVariable: 'threadLocalStorage';
+ removeVariable: 'processorOwner';
+ removeVariable: 'registerStates'.
- removeVariable: 'processorOwner'.
  var: #threads type: #'CogVMThread **';
  var: #vmOSThread type: #sqOSThread!

Item was changed:
  ----- Method: CogThreadManager>>acquireVMFor: (in category 'public api') -----
  acquireVMFor: threadIndex
  "Attempt to acquire the VM, eventually blocking until it becomes available.
  Spin until the maxWaitingPriority has been updated if it is lower than this thread's priority."
  <returnTypeC: #'CogVMThread *'>
  | vmThread |
  <var: #vmThread type: #'CogVMThread *'>
  self assert: threadIndex = self ioGetThreadLocalThreadIndex.
  vmThread := self vmThreadAt: threadIndex.
  self assert: (vmThread state = CTMUnavailable
  or: [vmThread state = CTMWantingOwnership]).
+ (self tryLockVMOwnerTo: threadIndex) ifFalse:
- (cogit tryLockVMOwnerTo: threadIndex) ifFalse:
  [vmThread state: CTMWantingOwnership.
  [(self vmOwnerIs: threadIndex)
+  or: [self tryLockVMOwnerTo: threadIndex]] whileFalse:
+ [vmThread priority ifNotNil:
-  or: [cogit tryLockVMOwnerTo: threadIndex]] whileFalse:
- [[coInterpreter getMaxWaitingPriority < vmThread priority] whileTrue:
  [coInterpreter waitingPriorityIsAtLeast: vmThread priority].
  (self vmOwnerIs: threadIndex) ifFalse:
  [self ioWaitOnOSSemaphore: (self addressOf: vmThread osSemaphore)]]].
  vmOSThread := vmThread osThread.
  vmThread state: CTMAssignableOrInVM.

Item was changed:
  ----- Method: CogThreadManager>>ensureRunningVMThread: (in category 'public api') -----
  ensureRunningVMThread: vmIsRelinquishing
  "Called from checkVMOwnershipFromHeartbeat if the VM is unowned.
  Hence we are in the heartbeat thread.  The race is against that thread
  owning the VM and against foreign callbacks."
  <returnTypeC: #void>
  <var: #vmThread type: #'CogVMThread *'>
  self willingVMThread ifNotNil:
  "If the VM is relinquishing the processor then only schedule a thread if it has work to do."
   and: [vmThread state ~= CTMWantingOwnership]) ifTrue:
+ (self tryLockVMOwnerTo: vmThread index) ifFalse: "someone beat us to it..."
- (cogit tryLockVMOwnerTo: vmThread index) ifFalse: "someone beat us to it..."
  vmOSThread := vmThread osThread.
  "release the thread from its blocking loop"
  self ioSignalOSSemaphore: (self addressOf: vmThread osSemaphore).
  self ioTransferTimeslice.
  "self cCode: [coInterpreter print: 'ERVT signalled '; printNum: vmThread index; cr]."
  "If the VM is relinquishing the processor then only schedule a thread if it has work to do
  (willingVMThread not nil above).
  If we have failed to allocate thread storage before there is no point continuing to
  try to do so.  By this time we should have quite a few threads in the pool."
  (vmIsRelinquishing or: [memoryIsScarce]) ifTrue:
  self unusedThreadInfo ifNotNil:
+ (self tryLockVMOwnerTo: vmThread index) ifTrue:
- (cogit tryLockVMOwnerTo: vmThread index) ifTrue:
  [(self startThreadForThreadInfo: vmThread) ifFalse:
  [self releaseVM]]]!

Item was changed:
  ----- Method: CogThreadManager>>initialize (in category 'initialize-release') -----
- <doNotGenerate>
  vmOwner := numThreads := numThreadsIncrement := 0.
  memoryIsScarce := false.
+ "N.B.  Do not initialize threadLocalStorage; leave this to ioInitThreadLocalThreadIndices".
+ registerStates := IdentityDictionary new!
- "N.B.  Do not initialize threadLocalStorage; leave this to ioInitThreadLocalThreadIndices"!

Item was changed:
  ----- Method: CogThreadManager>>shutdownModule (in category 'simulation') -----
+ | guiProcess activeProcess |
- | guiProcess |
  threads ifNil: [^self].
+ (guiProcess := self guiProcess) ~= (activeProcess := Processor activeProcess) ifTrue:
- (guiProcess := self guiProcess) ~= Processor activeProcess ifTrue:
  (Notification new tag: #evaluateQuit; yourself).
+ Project current spawnNewProcessIfThisIsUI: activeProcess.
+ activeProcess terminate].
- Processor terminateActive].
  threads do:
  ea osThread ifNotNil:
+ (aProcess ~~ activeProcess and: [aProcess ~~ guiProcess]) ifTrue:
+ [aProcess terminate]]].
+ threads := nil!
- (aProcess ~~ Processor activeProcess and: [aProcess ~~ guiProcess]) ifTrue:
- [aProcess terminate]]]!

Item was added:
+ ----- Method: CogThreadManager>>tryLockVMOwnerTo: (in category 'simulation') -----
+ tryLockVMOwnerTo: value
+ "In the real VM this is a direct call of Cogit>>#tryLockVMOwnerTo:/ceTryLockVMOwner.
+ In the simulation this is where we save and switch register state."
+ <doNotGenerate>
+ | current post prior processor |
+ processor := cogit processor.
+ prior := processor registerState.
+ vmOwner ~= 0 ifTrue:
+ [registerStates at: vmOwner put: prior].
+ (cogit tryLockVMOwnerTo: value) ifFalse:
+ [^false].
+ post := processor registerState.
+ current := registerStates
+ at: vmOwner
+ ifAbsentPut:
+ [self assert: vmOwner = value.
+ processor voidRegisterState; registerState].
+ 1 to: prior size do:
+ [:i| | neuf |
+ (prior at: i) ~= (neuf := post at: i) ifTrue:
+ [current at: i put: neuf]].
+ cogit processor setRegisterState: current.
+ ^true!

Item was changed:
+ ----- Method: CogVMSimulator>>ownVM: (in category 'debugging traps') -----
- ----- Method: CogVMSimulator>>ownVM: (in category 'multi-threading simulation switch') -----
  ownVM: threadIndexAndFlags
  "This method includes or excludes CoInterpreterMT methods as required.
  Auto-generated by CogVMSimulator>>ensureMultiThreadingOverridesAreUpToDate"
+ (threadIndexAndFlags anyMask: DisownVMForProcessorRelinquish << DisownFlagsShift) ifFalse:
+ [self break].
  ^self perform: #ownVM:
  withArguments: {threadIndexAndFlags}
  inSuperclass: (cogThreadManager ifNil: [CoInterpreterPrimitives] ifNotNil: [CoInterpreterMT])!

Item was added:
+ ----- Method: CogVMSimulator>>primitivePropertyFlagsForSpur: (in category 'multi-threading simulation switch') -----
+ primitivePropertyFlagsForSpur: primIndex
+ "This method includes or excludes CoInterpreterMT methods as required.
+ Auto-generated by CogVMSimulator>>ensureMultiThreadingOverridesAreUpToDate"
+ ^self perform: #primitivePropertyFlagsForSpur:
+ withArguments: {primIndex}
+ inSuperclass: (cogThreadManager ifNil: [CoInterpreterPrimitives] ifNotNil: [CoInterpreterMT])!

Item was changed:
  ----- Method: CogVMSimulator>>windowIsClosing (in category 'primitive support') -----
  self threadManager ifNotNil:
+ [:threadManager| threadManager shutdownModule].
- [:threadManager|
- threadManager guiProcess ifNotNil:
- [:guiProcess|
- (guiProcess ~= Processor activeProcess
- and: [guiProcess isInteger not]) ifTrue:
- [guiProcess
- signalException:
- (Notification new tag: #evaluateQuit; yourself).
- Processor terminateActive]]].
  quitBlock ifNotNil:
  quitBlock := nil. "stop recursion on explicit window close."
  [effectiveQuitBlock value]
  on: BlockCannotReturn
  do: [:ex|]] "Cause return from #test, et al"!

Item was changed:
  VMStructType subclass: #CogVMThread
+ instanceVariableNames: 'index state priority osSemaphore osThread newMethodOrNull argumentCount primitiveFunctionPointer inMachineCode cStackPointer cFramePointer awolProcIndex awolProcLength awolProcesses'
- instanceVariableNames: 'index state priority osSemaphore osThread newMethodOrNull argumentCount primitiveFunctionPointer inMachineCode cStackPointer cFramePointer reenterInterpreter awolProcIndex awolProcLength awolProcesses'
  classVariableNames: ''
  poolDictionaries: 'VMThreadingConstants'
  category: 'VMMaker-Multithreading'!
  !CogVMThread commentStamp: '<historical>' prior: 0!
  Instances of this class represent control blocks for native threads that cooperatively schedule the VM.  See the class comment of CogThreadManager for full documentation.
  N.B. awolProcesses must be the last inst var.!

Item was removed:
- ----- Method: CogVMThread>>awolProcesses: (in category 'accessing') -----
- awolProcesses: anObject
- "Set the value of awolProcesses"
- ^awolProcesses := anObject!

Item was changed:
  ----- Method: CogVMThread>>initialize (in category 'initialize-release') -----
- <doNotGenerate>
  awolProcLength := CogThreadManager awolProcessesIncrement.
  awolProcesses := CArrayAccessor on: (Array new: awolProcLength).
  awolProcIndex := 0!

Item was removed:
- ----- Method: CogVMThread>>reenterInterpreter (in category 'accessing') -----
- reenterInterpreter
- "Answer the value of reenterInterpreter"
- ^ reenterInterpreter!

Item was removed:
- ----- Method: CogVMThread>>reenterInterpreter: (in category 'accessing') -----
- reenterInterpreter: anObject
- "Set the value of reenterInterpreter"
- ^reenterInterpreter := anObject!

Item was changed:
  ----- Method: Cogit>>initializeProcessor (in category 'initialization') -----
  "Initialize the simulation processor, arranging that its initial stack is somewhere on the rump C stack."
  guardPageSize := self class guardPageSize.
  lastNInstructions := OrderedCollection new.
  processor initializeStackFor: self.
  self initializeProcessorStack: coInterpreter rumpCStackAddress.
  coInterpreter setCFramePointer: processor fp setCStackPointer: processor sp.
+ (InitializationOptions at: #UseMultiProcessor ifAbsent: [false]) ifTrue:
- threadManager ifNotNil:
  [processor := MultiProcessor for: processor coInterpreter: coInterpreter]!