ProcessorScheduler.st
changeset 1154 96bb8fce61cf
parent 1133 961f2b095c22
child 1166 f5affd8cb289
equal deleted inserted replaced
1153:8119975c55ce 1154:96bb8fce61cf
    14 	instanceVariableNames:'quiescentProcessLists scheduler zombie activeProcess
    14 	instanceVariableNames:'quiescentProcessLists scheduler zombie activeProcess
    15 		currentPriority readFdArray readSemaphoreArray readCheckArray
    15 		currentPriority readFdArray readSemaphoreArray readCheckArray
    16 		writeFdArray writeSemaphoreArray timeoutArray timeoutActionArray
    16 		writeFdArray writeSemaphoreArray timeoutArray timeoutActionArray
    17 		timeoutProcessArray timeoutSemaphoreArray idleActions anyTimeouts
    17 		timeoutProcessArray timeoutSemaphoreArray idleActions anyTimeouts
    18 		dispatching interruptedProcess useIOInterrupts gotIOInterrupt
    18 		dispatching interruptedProcess useIOInterrupts gotIOInterrupt
    19 		osChildExitActions exitWhenNoMoreUserProcesses'
    19 		osChildExitActions gotChildSignalInterrupt
       
    20 		exitWhenNoMoreUserProcesses'
    20 	classVariableNames:'KnownProcesses KnownProcessIds PureEventDriven
    21 	classVariableNames:'KnownProcesses KnownProcessIds PureEventDriven
    21 		UserSchedulingPriority UserInterruptPriority TimingPriority
    22 		UserSchedulingPriority UserInterruptPriority TimingPriority
    22 		HighestPriority SchedulingPriority MaxNumberOfProcesses'
    23 		HighestPriority SchedulingPriority MaxNumberOfProcesses'
    23 	poolDictionaries:''
    24 	poolDictionaries:''
    24 	category:'Kernel-Processes'
    25 	category:'Kernel-Processes'
   500 
   501 
   501     "
   502     "
   502      handle all timeout actions
   503      handle all timeout actions
   503     "
   504     "
   504     anyTimeouts ifTrue:[
   505     anyTimeouts ifTrue:[
   505 	self evaluateTimeouts
   506         self evaluateTimeouts
   506     ].
   507     ].
   507 
   508 
   508     "first do a quick check for semaphores using checkActions - this is needed for
   509     "first do a quick check for semaphores using checkActions - this is needed for
   509      devices like the X-connection, where some events might be in the event
   510      devices like the X-connection, where some events might be in the event
   510      queue. Without these checks, a select might block even though there is work to do
   511      queue. Without these checks, a select might block even though there is work to do
   511     "
   512     "
   512     any := false.
   513     any := false.
   513     nActions := readCheckArray size.
   514     nActions := readCheckArray size.
   514     1 to:nActions do:[:index |
   515     1 to:nActions do:[:index |
   515 	checkBlock := readCheckArray at:index.
   516         checkBlock := readCheckArray at:index.
   516 	(checkBlock notNil and:[checkBlock value]) ifTrue:[
   517         (checkBlock notNil and:[checkBlock value]) ifTrue:[
   517 	    sema := readSemaphoreArray at:index.
   518             sema := readSemaphoreArray at:index.
   518 	    sema notNil ifTrue:[
   519             sema notNil ifTrue:[
   519 		sema signalOnce.
   520                 sema signalOnce.
   520 	    ].
   521             ].
   521 	    any := true.
   522             any := true.
   522 	]
   523         ]
   523     ].
   524     ].
   524 
   525 
   525     "now, someone might be runnable ..."
   526     "now, someone might be runnable ..."
   526 
   527 
   527     p := self highestPriorityRunnableProcess.
   528     p := self highestPriorityRunnableProcess.
   528     p isNil ifTrue:[
   529     p isNil ifTrue:[
   529 	"/ no one runnable, hard wait for event or timeout
   530         "/ no one runnable, hard wait for event or timeout
   530 
   531 
   531 	self waitForEventOrTimeout.
   532         self waitForEventOrTimeout.
   532 	^ self
   533         ^ self
   533     ].
   534     ].
   534 
   535 
   535     pri := p priority.
   536     pri := p priority.
   536 
   537 
   537     "
   538     "
   558  (a future version will have a process running to handle a timeout queue)
   559  (a future version will have a process running to handle a timeout queue)
   559 "
   560 "
   560 
   561 
   561 "
   562 "
   562     pri < TimingPriority ifTrue:[
   563     pri < TimingPriority ifTrue:[
   563 	anyTimeouts ifTrue:[
   564         anyTimeouts ifTrue:[
   564 	    millis := self timeToNextTimeout.
   565             millis := self timeToNextTimeout.
   565 	    millis == 0 ifTrue:[^ self].
   566             millis == 0 ifTrue:[^ self].
   566 	]
   567         ]
   567     ].
   568     ].
   568 "
   569 "
   569 
   570 
   570     "
   571     "
   571      if the process to run has a lower than UserInterruptPriority,
   572      if the process to run has a lower than UserInterruptPriority,
   574      or by installing a poll-interrupt after 50ms (if the OS does not).
   575      or by installing a poll-interrupt after 50ms (if the OS does not).
   575     "
   576     "
   576     pri < UserInterruptPriority ifTrue:[
   577     pri < UserInterruptPriority ifTrue:[
   577     
   578     
   578 "comment out this if above is uncommented"
   579 "comment out this if above is uncommented"
   579 	anyTimeouts ifTrue:[
   580         anyTimeouts ifTrue:[
   580 	    millis := self timeToNextTimeout.
   581             millis := self timeToNextTimeout.
   581 	    millis == 0 ifTrue:[^ self].
   582             millis == 0 ifTrue:[^ self].
   582 	].
   583         ].
   583 "---"
   584 "---"
   584 
   585 
   585 	useIOInterrupts ifTrue:[
   586         useIOInterrupts ifTrue:[
   586 	    readFdArray do:[:fd |
   587             readFdArray do:[:fd |
   587 		fd notNil ifTrue:[
   588                 fd notNil ifTrue:[
   588 		    OperatingSystem enableIOInterruptsOn:fd
   589                     OperatingSystem enableIOInterruptsOn:fd
   589 		].
   590                 ].
   590 	    ].
   591             ].
   591 	] ifFalse:[
   592         ] ifFalse:[
   592 	    millis notNil ifTrue:[
   593             millis notNil ifTrue:[
   593 		millis := millis min:50
   594                 millis := millis min:50
   594 	    ] ifFalse:[
   595             ] ifFalse:[
   595 		millis := 50
   596                 millis := 50
   596 	    ]
   597             ]
   597 	]
   598         ]
   598     ].
   599     ].
   599 
   600 
   600     millis notNil ifTrue:[
   601     millis notNil ifTrue:[
   601 	"schedule a clock interrupt after millis milliseconds"
   602         "schedule a clock interrupt after millis milliseconds"
   602 	OperatingSystem enableTimer:millis rounded.
   603         OperatingSystem enableTimer:millis rounded.
   603     ].
   604     ].
   604 
   605 
   605     "
   606     "
   606      now let the process run - will come back here by reschedule
   607      now let the process run - will come back here by reschedule
   607      from ioInterrupt or timerInterrupt ... (running at max+1)
   608      from ioInterrupt or timerInterrupt ... (running at max+1)
   608     "
   609     "
   609     self threadSwitch:p.
   610     self threadSwitch:p.
   610 
   611 
   611     "... when we arrive here, we are back on stage.
   612     "... when we arrive here, we are back on stage.
   612 	 Either by an ALARM or IO signal, or by a suspend of another process
   613          Either by an ALARM or IO signal, or by a suspend of another process
   613     "
   614     "
   614 
   615 
   615     millis notNil ifTrue:[
   616     millis notNil ifTrue:[
   616 	OperatingSystem disableTimer.
   617         OperatingSystem disableTimer.
       
   618     ].
       
   619 
       
   620     "/ check for OS process termination
       
   621     gotChildSignalInterrupt ifTrue:[
       
   622         gotChildSignalInterrupt := false.
       
   623         self handleChildSignalInterrupt
   617     ].
   624     ].
   618 
   625 
   619     "/ check for new input
   626     "/ check for new input
   620 
   627 
   621     (gotIOInterrupt or:[useIOInterrupts not]) ifTrue:[
   628     (gotIOInterrupt or:[useIOInterrupts not]) ifTrue:[
   622 	gotIOInterrupt := false.
   629         gotIOInterrupt := false.
   623 	self checkForInputWithTimeout:0.
   630         self checkForInputWithTimeout:0.
   624     ]
   631     ]
   625 
   632 
   626     "Modified: 21.12.1995 / 16:21:54 / stefan"
   633     "Modified: 12.4.1996 / 10:14:18 / stefan"
   627 !
   634 !
   628 
   635 
   629 dispatchLoop
   636 dispatchLoop
   630     "central dispatch loop; the scheduler process is always staying in
   637     "central dispatch loop; the scheduler process is always staying in
   631      this method, looping forever."
   638      this method, looping forever."
   675 ! !
   682 ! !
   676 
   683 
   677 !ProcessorScheduler methodsFor:'os process handling'!
   684 !ProcessorScheduler methodsFor:'os process handling'!
   678 
   685 
   679 childSignalInterrupt
   686 childSignalInterrupt
       
   687     "child changed state - switch to scheduler process which will decide 
       
   688      what to do now."
       
   689 
       
   690     gotChildSignalInterrupt := true.
       
   691     interruptedProcess := activeProcess.
       
   692     self threadSwitch:scheduler
       
   693 
       
   694     "Modified: 12.4.1996 / 10:12:18 / stefan"
       
   695 !
       
   696 
       
   697 handleChildSignalInterrupt
   680     "child changed state - execute child termination blocks.
   698     "child changed state - execute child termination blocks.
   681      If child is no longer alive, remove action block."
   699      If child is no longer alive, remove action block."
   682 
   700 
   683     |osProcessStatus blocking wasBlocked|
   701     |osProcessStatus blocking wasBlocked|
   684 
   702 
   718         ].
   736         ].
   719     ] valueNowOrOnUnwindDo:[
   737     ] valueNowOrOnUnwindDo:[
   720         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   738         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   721     ]
   739     ]
   722 
   740 
   723     "Created: 22.12.1995 / 14:16:26 / stefan"
       
   724     "Modified: 5.1.1996 / 16:56:11 / stefan"
   741     "Modified: 5.1.1996 / 16:56:11 / stefan"
   725     "Modified: 28.2.1996 / 21:36:31 / cg"
   742     "Modified: 28.2.1996 / 21:36:31 / cg"
       
   743     "Created: 12.4.1996 / 10:08:21 / stefan"
   726 !
   744 !
   727 
   745 
   728 monitorPid:pid action:aBlock
   746 monitorPid:pid action:aBlock
   729     "add a 1-arg-block that is called when the operating system child process
   747     "add a 1-arg-block that is called when the operating system child process
   730      with pid pid changes state.
   748      with pid pid changes state.
   916 
   934 
   917     |nPrios "{ Class: SmallInteger }"
   935     |nPrios "{ Class: SmallInteger }"
   918      p|
   936      p|
   919 
   937 
   920     KnownProcesses isNil ifTrue:[
   938     KnownProcesses isNil ifTrue:[
   921 	KnownProcesses := WeakArray new:10.
   939         KnownProcesses := WeakArray new:10.
   922 	KnownProcesses watcher:self class.
   940         KnownProcesses watcher:self class.
   923 	KnownProcessIds := OrderedCollection new.
   941         KnownProcessIds := OrderedCollection new.
   924     ].
   942     ].
   925 
   943 
   926     "
   944     "
   927      create a collection with process lists; accessed using the priority as key
   945      create a collection with process lists; accessed using the priority as key
   928     "
   946     "
   929     nPrios := SchedulingPriority.
   947     nPrios := SchedulingPriority.
   930     quiescentProcessLists := Array new:nPrios.
   948     quiescentProcessLists := Array new:nPrios.
   931     1 to:nPrios do:[:pri |
   949     1 to:nPrios do:[:pri |
   932 	quiescentProcessLists at:pri put:(LinkedList new)
   950         quiescentProcessLists at:pri put:(LinkedList new)
   933     ].
   951     ].
   934 
   952 
   935     readFdArray := Array with:nil.
   953     readFdArray := Array with:nil.
   936     readCheckArray := Array with:nil.
   954     readCheckArray := Array with:nil.
   937     readSemaphoreArray := Array with:nil.
   955     readSemaphoreArray := Array with:nil.
   945     dispatching := false.
   963     dispatching := false.
   946     exitWhenNoMoreUserProcesses := false. "/ mhmh - how about true ?
   964     exitWhenNoMoreUserProcesses := false. "/ mhmh - how about true ?
   947     useIOInterrupts := OperatingSystem supportsIOInterrupts.
   965     useIOInterrupts := OperatingSystem supportsIOInterrupts.
   948     gotIOInterrupt := false.
   966     gotIOInterrupt := false.
   949     osChildExitActions := Dictionary new.
   967     osChildExitActions := Dictionary new.
       
   968     gotChildSignalInterrupt := false.
   950 
   969 
   951     "
   970     "
   952      handcraft the first (dispatcher-) process - this one will never
   971      handcraft the first (dispatcher-) process - this one will never
   953      block, but go into a select if there is nothing to do.
   972      block, but go into a select if there is nothing to do.
   954      Also, it has a prio of max+1 - thus, it comes first when looking
   973      Also, it has a prio of max+1 - thus, it comes first when looking
   969     "
   988     "
   970     ObjectMemory ioInterruptHandler:self.
   989     ObjectMemory ioInterruptHandler:self.
   971     ObjectMemory timerInterruptHandler:self.
   990     ObjectMemory timerInterruptHandler:self.
   972     ObjectMemory childSignalInterruptHandler:self.
   991     ObjectMemory childSignalInterruptHandler:self.
   973 
   992 
   974     "Modified: 22.12.1995 / 14:15:29 / stefan"
   993     "Modified: 12.4.1996 / 10:12:56 / stefan"
   975 !
   994 !
   976 
   995 
   977 reinitialize
   996 reinitialize
   978     "all previous processes (except those marked as restartable) are made dead 
   997     "all previous processes (except those marked as restartable) are made dead 
   979      - each object should reinstall its process(s) upon restart;
   998      - each object should reinstall its process(s) upon restart;
  1774      hard wait for either input to arrive or a timeout to occur."
  1793      hard wait for either input to arrive or a timeout to occur."
  1775 
  1794 
  1776     |fd index sema action|
  1795     |fd index sema action|
  1777 
  1796 
  1778     fd := OperatingSystem 
  1797     fd := OperatingSystem 
  1779 	      selectOnAnyReadable:readFdArray 
  1798               selectOnAnyReadable:readFdArray 
  1780 			 writable:writeFdArray
  1799                          writable:writeFdArray
  1781 			exception:nil 
  1800                         exception:nil 
  1782 		      withTimeOut:millis.
  1801                       withTimeOut:millis.
  1783 
  1802 
  1784     fd isNil ifTrue:[
  1803     fd isNil ifTrue:[
  1785 	(OperatingSystem lastErrorSymbol == #EBADF) ifTrue:[
  1804         (OperatingSystem lastErrorSymbol == #EBADF) ifTrue:[
  1786 
  1805 
  1787 	    "/ mhmh - one of the fd's given to me is corrupt.
  1806             "/ mhmh - one of the fd's given to me is corrupt.
  1788 	    "/ find out which one .... and remove it
  1807             "/ find out which one .... and remove it
  1789 
  1808 
  1790 	    self removeCorruptedFds
  1809             OperatingSystem clearLastErrorNumber.
  1791 	]
  1810             self removeCorruptedFds
       
  1811         ]
  1792     ] ifFalse:[
  1812     ] ifFalse:[
  1793 	index := readFdArray indexOf:fd.
  1813         index := readFdArray indexOf:fd.
  1794 	index ~~ 0 ifTrue:[
  1814         index ~~ 0 ifTrue:[
  1795 	    sema := readSemaphoreArray at:index.
  1815             sema := readSemaphoreArray at:index.
  1796 	    sema notNil ifTrue:[
  1816             sema notNil ifTrue:[
  1797 		sema signalOnce.
  1817                 sema signalOnce.
  1798 		^ true
  1818                 ^ true
  1799 	    ] ifFalse:[
  1819             ] ifFalse:[
  1800 		action := readCheckArray at:index.
  1820                 action := readCheckArray at:index.
  1801 		action notNil ifTrue:[
  1821                 action notNil ifTrue:[
  1802 		    action value.
  1822                     action value.
  1803 		     ^ true
  1823                      ^ true
  1804 		]
  1824                 ]
  1805 	    ]
  1825             ]
  1806 	]
  1826         ]
  1807     ].
  1827     ].
  1808     ^ false
  1828     ^ false
       
  1829 
       
  1830     "Modified: 12.4.1996 / 09:31:22 / stefan"
  1809 !
  1831 !
  1810 
  1832 
  1811 ioInterrupt
  1833 ioInterrupt
  1812     "data arrived while waiting - switch to scheduler process which will decide 
  1834     "data arrived while waiting - switch to scheduler process which will decide 
  1813      what to do now."
  1835      what to do now."
  1836                                writable:nil
  1858                                writable:nil
  1837                               exception:nil
  1859                               exception:nil
  1838                             withTimeOut:0.
  1860                             withTimeOut:0.
  1839 
  1861 
  1840         (rslt isNil and:[OperatingSystem lastErrorSymbol == #EBADF]) ifTrue:[
  1862         (rslt isNil and:[OperatingSystem lastErrorSymbol == #EBADF]) ifTrue:[
  1841             ('PROCESSOR: remove invalid read fileDescriptor: ' , fd printString) errorPrintNL.
  1863             ('PROCESSOR: removing invalid read fileDescriptor: ' , fd printString) errorPrintNL.
  1842             readFdArray at:idx put:nil
  1864             readFdArray at:idx put:nil.
       
  1865             OperatingSystem clearLastErrorNumber
  1843         ]
  1866         ]
  1844     ].
  1867     ].
  1845 
  1868 
  1846     writeFdArray keysAndValuesDo:[:idx :fd |
  1869     writeFdArray keysAndValuesDo:[:idx :fd |
  1847         |rslt|
  1870         |rslt|
  1852                               exception:nil
  1875                               exception:nil
  1853                             withTimeOut:0.
  1876                             withTimeOut:0.
  1854 
  1877 
  1855         (rslt isNil and:[OperatingSystem lastErrorSymbol == #EBADF]) ifTrue:[
  1878         (rslt isNil and:[OperatingSystem lastErrorSymbol == #EBADF]) ifTrue:[
  1856             ('PROCESSOR: removing invalid write fileDescriptor: ' , fd printString) errorPrintNL.
  1879             ('PROCESSOR: removing invalid write fileDescriptor: ' , fd printString) errorPrintNL.
  1857             writeFdArray at:idx put:nil
  1880             writeFdArray at:idx put:nil.
       
  1881             OperatingSystem clearLastErrorNumber
  1858         ]
  1882         ]
  1859     ].
  1883     ].
       
  1884 
       
  1885     "Modified: 12.4.1996 / 09:32:58 / stefan"
  1860 !
  1886 !
  1861 
  1887 
  1862 schedulerInterrupt
  1888 schedulerInterrupt
  1863     "forced reschedule - switch to scheduler process which will decide
  1889     "forced reschedule - switch to scheduler process which will decide
  1864      what to do now."
  1890      what to do now."
  1991 ! !
  2017 ! !
  1992 
  2018 
  1993 !ProcessorScheduler class methodsFor:'documentation'!
  2019 !ProcessorScheduler class methodsFor:'documentation'!
  1994 
  2020 
  1995 version
  2021 version
  1996     ^ '$Header: /cvs/stx/stx/libbasic/ProcessorScheduler.st,v 1.74 1996-04-02 22:04:46 cg Exp $'
  2022     ^ '$Header: /cvs/stx/stx/libbasic/ProcessorScheduler.st,v 1.75 1996-04-12 09:25:42 stefan Exp $'
  1997 ! !
  2023 ! !
  1998 ProcessorScheduler initialize!
  2024 ProcessorScheduler initialize!