!VirtualMachineExe methods !
  
oldSpaceBytesTotal

    | min max oldSpaceInfo |
    oldSpaceInfo := ( ExternalBuffer atAddress: ( ( VirtualMachineLibrary queryProcAddr: 'ObjectStore' ) + 48) ).
    min := oldSpaceInfo addressAtOffset: 16.
    max := oldSpaceInfo addressAtOffset: 20.
    ^max asInteger - min asInteger! !



Object subclass: #ProcessScheduler
  instanceVariableNames: 
    ' readyProcesses bytesCollected bytesFlipped oldSpacePages newSpacePages newSpaceLimit gcOperation traceMode bytesTenured unboundComponents oldSpaceThreshold inTrouble inPanic '
  classVariableNames: 
    ' Finalizer GCStrategy OldSpaceThresholdIncrement '
  poolDictionaries: '' !



!ProcessScheduler methods !
 
gcStrategy

    " Answer the strategy for doing global compacts. "

    ^GCStrategy!

gcStrategy: aSymbolOrNil

    " Set the strategy for doing global compacts:

    aSymbolOrNil may be:
        nil - the digitalk default (1MB)
        #fixed - a fixed percentage of oldSpaceTotal
        #adaptive - a fixed percentage of oldSpaceAvailable"

    GCStrategy := aSymbolOrNil.!
 

oldSpaceBytesAvailable

    " Answer the amount of memory that can be allocated for old space in bytes "

    ^self oldSpaceBytesTotal - self oldSpaceBytesUsed!

oldSpaceBytesTotal

    " Answer the maximum amount of memory for old space currently configured in bytes "

    ^VirtualMachineExe current oldSpaceBytesTotal!
 
oldSpaceBytesUsed

    " Answer the amount of memory currently used for old space in bytes "

    ^self oldSpacePages * 4096!
   
 
oldSpaceThresholdAdaptive

    " Answer the threshold increment for the process scheduler.
    We take 10% of the free old space size and round it towards the next 1 MB boundary.
    To configure the process scheduler we must answer a number of CPU pages (4096 bytes each)  "

    ^(((self oldSpaceBytesAvailable // 10) + 524288 ) bitAnd: 16rFFF00000) / 4096!
   
oldSpaceThresholdDigitalk

    " the default used by Digitalk - answer the number of CPU pages (4096 bytes each) "

    ^self oldSpaceThresholdIncrement!
   
oldSpaceThresholdDynamic

    " Answer the value for oldSpaceThreshold depending on the chosen strategy. "

    | s |

     (s := self gcStrategy) == #fixed ifTrue: [ ^self oldSpaceThresholdFixed ].
     s == #adaptive ifTrue: [ ^self oldSpaceThresholdAdaptive ].
     ^self oldSpaceThresholdDigitalk!
   
oldSpaceThresholdFixed

    " Answer the threshold increment for the process scheduler.
    We take 1% of the old space size and round it towards the next 1 MB boundary.
    To configure the process scheduler we must answer a number of CPU pages (4096 bytes each)  "

    ^(((self oldSpaceBytesTotal // 100) + 524288 ) bitAnd: 16rFFF00000) / 4096!
   

rebalance

        "Private - If oldSpace is too large, do a compact."

    | increment |

    unboundComponents isNil ifTrue: [
        unboundComponents := SmalltalkLibraryBinder unboundK ].
    SmalltalkLibraryBinder unboundK > ( unboundComponents + 1000 ) ifTrue: [
        "some libs were unbound since last time, so try to free them."
        unboundComponents := SmalltalkLibraryBinder unboundK.
        SmalltalkLibraryBinder compact.
        unboundComponents := SmalltalkLibraryBinder unboundK ].
    increment := self oldSpaceThresholdDynamic.
    oldSpacePages > oldSpaceThreshold
        ifTrue: [
            oldSpaceThreshold := oldSpacePages + 10.
            SmalltalkLibraryBinder unboundCount > 0
                ifTrue: [ SmalltalkLibraryBinder compact ]
                ifFalse: [ Smalltalk unusedMemory ].
            self status.
            oldSpaceThreshold := oldSpacePages + increment.
            self configure
        ].
    oldSpaceThreshold > (oldSpacePages + increment)
        ifTrue: [
            oldSpaceThreshold := oldSpacePages + increment.
            self configure
        ].!
 
