ProcessorScheduler.st
changeset 6376 6a3ce5694cc9
parent 6260 cafdfa333832
child 6421 58dca33cf0fc
equal deleted inserted replaced
6375:7391258a73e8 6376:6a3ce5694cc9
   772     "/  this safes a bit of memory allocation in the scheduler)
   772     "/  this safes a bit of memory allocation in the scheduler)
   773 
   773 
   774     dispatchAction := [self dispatch].
   774     dispatchAction := [self dispatch].
   775 
   775 
   776     handlerAction := [:ex |
   776     handlerAction := [:ex |
   777                         ('Processor [info]: ignored signal (', ex signal printString, ')') infoPrintCR.
   777 			('Processor [info]: ignored signal (', ex signal printString, ')') infoPrintCR.
   778                         ex return
   778 			ex return
   779                      ].
   779 		     ].
   780 
   780 
   781     ignoredSignals := SignalSet 
   781     ignoredSignals := SignalSet 
   782                         with:TerminateProcessRequest
   782 			with:TerminateProcessRequest
   783                         with:AbortSignal.
   783 			with:AbortSignal.
   784 
   784 
   785     "/
   785     "/
   786     "/ I made this an extra call to dispatch; this allows recompilation
   786     "/ I made this an extra call to dispatch; this allows recompilation
   787     "/  of the dispatch-handling code in the running system.
   787     "/  of the dispatch-handling code in the running system.
   788     "/
   788     "/
   789     [dispatching] whileTrue:[
   789     [dispatching] whileTrue:[
   790         ignoredSignals handle:handlerAction do:dispatchAction
   790 	ignoredSignals handle:handlerAction do:dispatchAction
   791     ].
   791     ].
   792 
   792 
   793     "/ we arrive here in standalone Apps,
   793     "/ we arrive here in standalone Apps,
   794     "/ when the last process at or above UserSchedulingPriority process died.
   794     "/ when the last process at or above UserSchedulingPriority process died.
   795     "/ regular ST/X stays in above loop forever
   795     "/ regular ST/X stays in above loop forever
   817 
   817 
   818     |nPrios "{ Class: SmallInteger }"
   818     |nPrios "{ Class: SmallInteger }"
   819      p l|
   819      p l|
   820 
   820 
   821     KnownProcesses isNil ifTrue:[
   821     KnownProcesses isNil ifTrue:[
   822         KnownProcesses := WeakArray new:30.
   822 	KnownProcesses := WeakArray new:30.
   823         KnownProcesses addDependent:self class.
   823 	KnownProcesses addDependent:self class.
   824         KnownProcessIds := OrderedCollection new.
   824 	KnownProcessIds := OrderedCollection new.
   825     ].
   825     ].
   826 
   826 
   827     "
   827     "
   828      create a collection with process lists; accessed using the priority as key
   828      create a collection with process lists; accessed using the priority as key
   829     "
   829     "
   842     timeoutProcessArray := Array new:5.
   842     timeoutProcessArray := Array new:5.
   843 
   843 
   844     anyTimeouts := false.
   844     anyTimeouts := false.
   845     dispatching := false.
   845     dispatching := false.
   846     exitWhenNoMoreUserProcesses isNil ifTrue:[
   846     exitWhenNoMoreUserProcesses isNil ifTrue:[
   847         exitWhenNoMoreUserProcesses := false. "/ mhmh - how about true ?
   847 	exitWhenNoMoreUserProcesses := false. "/ mhmh - how about true ?
   848     ].
   848     ].
   849     useIOInterrupts := OperatingSystem supportsIOInterrupts.
   849     useIOInterrupts := OperatingSystem supportsIOInterrupts.
   850     gotIOInterrupt := false.
   850     gotIOInterrupt := false.
   851     osChildExitActions := Dictionary new.
   851     osChildExitActions := Dictionary new.
   852     gotChildSignalInterrupt := false.
   852     gotChildSignalInterrupt := false.
   989      This is only used with win32's native threads."
   989      This is only used with win32's native threads."
   990 
   990 
   991     |index pri aProcess l|
   991     |index pri aProcess l|
   992 
   992 
   993     OperatingSystem interruptsBlocked ifFalse:[
   993     OperatingSystem interruptsBlocked ifFalse:[
   994         MiniDebugger 
   994 	MiniDebugger 
   995             enterWithMessage:'resumeImmediateInterrupt with no interruptsBlocked'
   995 	    enterWithMessage:'resumeImmediateInterrupt with no interruptsBlocked'
   996             mayProceed:true.
   996 	    mayProceed:true.
   997     ].
   997     ].
   998     index := KnownProcessIds identityIndexOf:id.
   998     index := KnownProcessIds identityIndexOf:id.
   999     index ~~ 0 ifTrue:[
   999     index ~~ 0 ifTrue:[
  1000         aProcess := KnownProcesses at:index.
  1000 	aProcess := KnownProcesses at:index.
  1001         "/
  1001 	"/
  1002         "/ CG: the situation below may happen, if the wrapCall
  1002 	"/ CG: the situation below may happen, if the wrapCall
  1003         "/ finishes before the process was layed to sleep
  1003 	"/ finishes before the process was layed to sleep
  1004         "/ (i.e. schedulerIRQ arrives before the threadSwitch
  1004 	"/ (i.e. schedulerIRQ arrives before the threadSwitch
  1005         "/ was finished.
  1005 	"/ was finished.
  1006         "/ In that case, simply resume it and everything is OK.
  1006 	"/ In that case, simply resume it and everything is OK.
  1007         "/
  1007 	"/
  1008 "/        aProcess state ~~ #wrapWait ifTrue:[
  1008 "/        aProcess state ~~ #wrapWait ifTrue:[
  1009 "/            'ProcSched [info]: oops - resumeImmIRQ for non wrapWait process' infoPrintCR.
  1009 "/            'ProcSched [info]: oops - resumeImmIRQ for non wrapWait process' infoPrintCR.
  1010 "/            ^ self
  1010 "/            ^ self
  1011 "/        ].
  1011 "/        ].
  1012         pri := aProcess priority.
  1012 	pri := aProcess priority.
  1013         l := quiescentProcessLists at:pri.
  1013 	l := quiescentProcessLists at:pri.
  1014         "if already running, ignore"
  1014 	"if already running, ignore"
  1015         l notNil ifTrue:[
  1015 	l notNil ifTrue:[
  1016             (l identityIndexOf:aProcess) ~~ 0 ifTrue:[
  1016 	    (l identityIndexOf:aProcess) ~~ 0 ifTrue:[
  1017                 'ProcSched [info]: oops - resumeIRQ for already running process' infoPrintCR.
  1017 		'ProcSched [info]: oops - resumeIRQ for already running process' infoPrintCR.
  1018                 ^ self
  1018 		^ self
  1019             ]
  1019 	    ]
  1020         ] ifFalse:[
  1020 	] ifFalse:[
  1021             l := LinkedList new.
  1021 	    l := LinkedList new.
  1022             quiescentProcessLists at:pri put:l.
  1022 	    quiescentProcessLists at:pri put:l.
  1023         ].
  1023 	].
  1024         l addLast:aProcess.
  1024 	l addLast:aProcess.
  1025         aProcess state:#run.
  1025 	aProcess state:#run.
  1026     ] ifFalse:[
  1026     ] ifFalse:[
  1027         'ProcSched [info]: oops - resumeIRQ for unknown process: ' infoPrint.
  1027 	'ProcSched [info]: oops - resumeIRQ for unknown process: ' infoPrint.
  1028         id infoPrintCR.
  1028 	id infoPrintCR.
  1029     ]
  1029     ]
  1030 
  1030 
  1031     "Modified: / 28.9.1998 / 11:36:53 / cg"
  1031     "Modified: / 28.9.1998 / 11:36:53 / cg"
  1032 ! !
  1032 ! !
  1033 
  1033 
  1108      The method returns the value from aBlockReturningPid (i.e a pid or nil)."
  1108      The method returns the value from aBlockReturningPid (i.e a pid or nil)."
  1109 
  1109 
  1110     |pid blocked osProcessStatus|
  1110     |pid blocked osProcessStatus|
  1111 
  1111 
  1112     OperatingSystem supportsChildInterrupts ifTrue:[
  1112     OperatingSystem supportsChildInterrupts ifTrue:[
  1113         "/ SIGCHLD is supported,
  1113 	"/ SIGCHLD is supported,
  1114         "/ aBlock will be evaluated, as soon as a SIGCHLD interrupt for pid has been received.
  1114 	"/ aBlock will be evaluated, as soon as a SIGCHLD interrupt for pid has been received.
  1115 
  1115 
  1116         OperatingSystem enableChildSignalInterrupts.
  1116 	OperatingSystem enableChildSignalInterrupts.
  1117         blocked := OperatingSystem blockInterrupts.
  1117 	blocked := OperatingSystem blockInterrupts.
  1118         pid := aBlockReturningPid value.
  1118 	pid := aBlockReturningPid value.
  1119         pid notNil ifTrue:[
  1119 	pid notNil ifTrue:[
  1120             osChildExitActions at:pid put:actionBlock.
  1120 	    osChildExitActions at:pid put:actionBlock.
  1121         ].
  1121 	].
  1122         blocked ifFalse:[
  1122 	blocked ifFalse:[
  1123             OperatingSystem unblockInterrupts.
  1123 	    OperatingSystem unblockInterrupts.
  1124         ].
  1124 	].
  1125     ] ifFalse:[
  1125     ] ifFalse:[
  1126         "/ SIGCHLD is not supported, fork a high prio process 
  1126 	"/ SIGCHLD is not supported, fork a high prio process 
  1127         "/ to poll for for the exit of pid.
  1127 	"/ to poll for for the exit of pid.
  1128 
  1128 
  1129         blocked := OperatingSystem blockInterrupts.
  1129 	blocked := OperatingSystem blockInterrupts.
  1130         pid := aBlockReturningPid value.
  1130 	pid := aBlockReturningPid value.
  1131         pid notNil ifTrue:[
  1131 	pid notNil ifTrue:[
  1132             osChildExitActions at:pid put:actionBlock.
  1132 	    osChildExitActions at:pid put:actionBlock.
  1133         ].
  1133 	].
  1134         blocked ifFalse:[
  1134 	blocked ifFalse:[
  1135             OperatingSystem unblockInterrupts.
  1135 	    OperatingSystem unblockInterrupts.
  1136         ].
  1136 	].
  1137 
  1137 
  1138         pid notNil ifTrue:[
  1138 	pid notNil ifTrue:[
  1139             [
  1139 	    [
  1140                 [
  1140 		[
  1141                   |polling myDelay t|
  1141 		  |polling myDelay t|
  1142 
  1142 
  1143                   polling := true.
  1143 		  polling := true.
  1144                   myDelay := Delay forMilliseconds:(t := EventPollingInterval).
  1144 		  myDelay := Delay forMilliseconds:(t := EventPollingInterval).
  1145                   [polling] whileTrue:[
  1145 		  [polling] whileTrue:[
  1146                       t ~~ EventPollingInterval ifTrue:[
  1146 		      t ~~ EventPollingInterval ifTrue:[
  1147                           "/ interval changed -> need a new delay
  1147 			  "/ interval changed -> need a new delay
  1148                           myDelay delay:(t := EventPollingInterval).
  1148 			  myDelay delay:(t := EventPollingInterval).
  1149                       ].
  1149 		      ].
  1150                       myDelay wait.
  1150 		      myDelay wait.
  1151                       (osChildExitActions includesKey:pid) ifFalse:[
  1151 		      (osChildExitActions includesKey:pid) ifFalse:[
  1152                           polling := false.
  1152 			  polling := false.
  1153                       ] ifTrue:[
  1153 		      ] ifTrue:[
  1154                           osProcessStatus := OperatingSystem childProcessWait:false pid:pid.
  1154 			  osProcessStatus := OperatingSystem childProcessWait:false pid:pid.
  1155                           osProcessStatus notNil ifTrue:[
  1155 			  osProcessStatus notNil ifTrue:[
  1156                               (osProcessStatus pid = pid) ifTrue:[
  1156 			      (osProcessStatus pid = pid) ifTrue:[
  1157                                   osChildExitActions removeKey:pid ifAbsent:nil.
  1157 				  osChildExitActions removeKey:pid ifAbsent:nil.
  1158                                   actionBlock value:osProcessStatus.
  1158 				  actionBlock value:osProcessStatus.
  1159                                   polling := false.
  1159 				  polling := false.
  1160                               ] ifFalse:[
  1160 			      ] ifFalse:[
  1161                                   osProcessStatus stillAlive
  1161 				  osProcessStatus stillAlive
  1162                               ]
  1162 			      ]
  1163                           ]
  1163 			  ]
  1164                       ]. 
  1164 		      ]. 
  1165                   ]
  1165 		  ]
  1166               ] valueOnUnwindDo:[
  1166 	      ] valueOnUnwindDo:[
  1167                   osChildExitActions removeKey:pid ifAbsent:nil
  1167 		  osChildExitActions removeKey:pid ifAbsent:nil
  1168               ]
  1168 	      ]
  1169             ] forkAt:TimingPriority.
  1169 	    ] forkAt:TimingPriority.
  1170         ].
  1170 	].
  1171     ].
  1171     ].
  1172     ^ pid
  1172     ^ pid
  1173 
  1173 
  1174     "Created: / 25.3.1997 / 10:54:56 / stefan"
  1174     "Created: / 25.3.1997 / 10:54:56 / stefan"
  1175     "Modified: / 25.3.1997 / 11:21:05 / stefan"
  1175     "Modified: / 25.3.1997 / 11:21:05 / stefan"
  1256     activeProcess := oldProcess.
  1256     activeProcess := oldProcess.
  1257     activeProcessId := oldId.
  1257     activeProcessId := oldId.
  1258     currentPriority := oldProcess priority.
  1258     currentPriority := oldProcess priority.
  1259 
  1259 
  1260     ok == true ifFalse:[
  1260     ok == true ifFalse:[
  1261         "
  1261 	"
  1262          switch failed for some reason -
  1262 	 switch failed for some reason -
  1263          destroy (hard-terminate) the bad process.
  1263 	 destroy (hard-terminate) the bad process.
  1264          This happens when:
  1264 	 This happens when:
  1265          - the stack went above the absolute limit
  1265 	 - the stack went above the absolute limit
  1266            (VM switches back to scheduler)
  1266 	   (VM switches back to scheduler)
  1267          - a halted process cannot execute its interrupt
  1267 	 - a halted process cannot execute its interrupt
  1268            actions (win32 only)
  1268 	   actions (win32 only)
  1269         "
  1269 	"
  1270         (id := p id) ~~ 0 ifTrue:[
  1270 	(id := p id) ~~ 0 ifTrue:[
  1271             id notNil ifTrue:[
  1271 	    id notNil ifTrue:[
  1272                 'Processor [warning]: problem with process ' errorPrint. 
  1272 		'Processor [warning]: problem with process ' errorPrint. 
  1273                 id errorPrint. 
  1273 		id errorPrint. 
  1274                 (nm := p name) notNil ifTrue:[
  1274 		(nm := p name) notNil ifTrue:[
  1275                     ' (' errorPrint. nm errorPrint. ')' errorPrint.
  1275 		    ' (' errorPrint. nm errorPrint. ')' errorPrint.
  1276                 ].
  1276 		].
  1277 
  1277 
  1278                 ok == #halted ifTrue:[
  1278 		ok == #halted ifTrue:[
  1279                     "/ that process was halted (win32 only)
  1279 		    "/ that process was halted (win32 only)
  1280                     p state:#halted.
  1280 		    p state:#halted.
  1281                    '; stopped it.' errorPrintCR.
  1281 		   '; stopped it.' errorPrintCR.
  1282                    self suspend:p.
  1282 		   self suspend:p.
  1283                 ] ifFalse:[
  1283 		] ifFalse:[
  1284                    '; hard-terminate it.' errorPrintCR.
  1284 		   '; hard-terminate it.' errorPrintCR.
  1285                    'Processor [info]: cleanup may take a while if stack is huge' infoPrintCR.
  1285 		   'Processor [info]: cleanup may take a while if stack is huge' infoPrintCR.
  1286                    p state:#cleanup.
  1286 		   p state:#cleanup.
  1287                    self terminateNoSignal:p.
  1287 		   self terminateNoSignal:p.
  1288                 ]
  1288 		]
  1289             ]
  1289 	    ]
  1290         ]
  1290 	]
  1291     ].
  1291     ].
  1292     zombie notNil ifTrue:[
  1292     zombie notNil ifTrue:[
  1293         self class threadDestroy:zombie.
  1293 	self class threadDestroy:zombie.
  1294         zombie := nil
  1294 	zombie := nil
  1295     ].
  1295     ].
  1296     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1296     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1297 !
  1297 !
  1298 
  1298 
  1299 threadSwitchFrom:oldProcess to:aProcess id:id singleStep:singleStep
  1299 threadSwitchFrom:oldProcess to:aProcess id:id singleStep:singleStep
  1309 %{
  1309 %{
  1310     extern OBJ ___threadSwitch();
  1310     extern OBJ ___threadSwitch();
  1311     OBJ ok;
  1311     OBJ ok;
  1312 
  1312 
  1313     if (__isSmallInteger(id)) {
  1313     if (__isSmallInteger(id)) {
  1314         ok = ___threadSwitch(__context, __intVal(id), (singleStep == true) ? 1 : 0);
  1314 	ok = ___threadSwitch(__context, __intVal(id), (singleStep == true) ? 1 : 0, 0);
  1315     } else {
  1315     } else {
  1316         ok = false;
  1316 	ok = false;
  1317     }
  1317     }
  1318     RETURN (ok)
  1318     RETURN (ok)
  1319 %}
  1319 %}
  1320 ! !
  1320 ! !
  1321 
  1321 
  1700     ].
  1700     ].
  1701 
  1701 
  1702     "/ the returned value here has a subtle effect:
  1702     "/ the returned value here has a subtle effect:
  1703     "/ if false, the interrupt is assumed to be not taken,
  1703     "/ if false, the interrupt is assumed to be not taken,
  1704     "/ and will be redelivered.
  1704     "/ and will be redelivered.
  1705 
       
  1706     ^ activeProcess interruptedIn:s
  1705     ^ activeProcess interruptedIn:s
  1707 
  1706 
  1708     "Modified: 20.10.1996 / 17:06:48 / cg"
  1707     "Modified: 20.10.1996 / 17:06:48 / cg"
  1709 !
  1708 !
  1710 
  1709 
  1945 
  1944 
  1946     |pri id l wasBlocked|
  1945     |pri id l wasBlocked|
  1947 
  1946 
  1948     aProcess isNil ifTrue:[^ self].
  1947     aProcess isNil ifTrue:[^ self].
  1949     aProcess == scheduler ifTrue:[
  1948     aProcess == scheduler ifTrue:[
  1950         InvalidProcessSignal raiseWith:aProcess errorString:'PROCESSOR: I will not terminate scheduler'.
  1949 	InvalidProcessSignal raiseWith:aProcess errorString:'PROCESSOR: I will not terminate scheduler'.
  1951         ^ self
  1950 	^ self
  1952     ].
  1951     ].
  1953 
  1952 
  1954     id := aProcess id.
  1953     id := aProcess id.
  1955     id isNil ifTrue:[^ self].   "already dead"
  1954     id isNil ifTrue:[^ self].   "already dead"
  1956 
  1955 
  1961     "remove the process from the runnable list"
  1960     "remove the process from the runnable list"
  1962 
  1961 
  1963     pri := aProcess priority.
  1962     pri := aProcess priority.
  1964     l := quiescentProcessLists at:pri.
  1963     l := quiescentProcessLists at:pri.
  1965     l notNil ifTrue:[
  1964     l notNil ifTrue:[
  1966         (l remove:aProcess ifAbsent:nil) notNil ifTrue:[
  1965 	(l remove:aProcess ifAbsent:nil) notNil ifTrue:[
  1967             l isEmpty ifTrue:[
  1966 	    l isEmpty ifTrue:[
  1968                 quiescentProcessLists at:pri put:nil
  1967 		quiescentProcessLists at:pri put:nil
  1969             ]
  1968 	    ]
  1970         ].
  1969 	].
  1971     ].
  1970     ].
  1972     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1971     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1973 
  1972 
  1974     aProcess == activeProcess ifTrue:[
  1973     aProcess == activeProcess ifTrue:[
  1975         "
  1974 	"
  1976          hard case - its the currently running process
  1975 	 hard case - its the currently running process
  1977          we must have the next active process destroy this one
  1976 	 we must have the next active process destroy this one
  1978          (we cannot destroy the chair we are sitting on ... :-)
  1977 	 (we cannot destroy the chair we are sitting on ... :-)
  1979         "
  1978 	"
  1980         zombie := id.
  1979 	zombie := id.
  1981         self unRemember:aProcess.
  1980 	self unRemember:aProcess.
  1982         self threadSwitch:scheduler.
  1981 	self threadSwitch:scheduler.
  1983         "not reached"
  1982 	"not reached"
  1984         ^ self
  1983 	^ self
  1985     ].
  1984     ].
  1986     self class threadDestroy:id.
  1985     self class threadDestroy:id.
  1987     self unRemember:aProcess.
  1986     self unRemember:aProcess.
  1988     ^ self
  1987     ^ self
  1989 
  1988 
  2408     "arrange for a semaphore to be triggered when input on aStream arrives. 
  2407     "arrange for a semaphore to be triggered when input on aStream arrives. 
  2409      This will do a select, if the OS supports selecting on that filedescriptor,
  2408      This will do a select, if the OS supports selecting on that filedescriptor,
  2410      otherwise, it will be polled every few milliseconds (MSDOS)."
  2409      otherwise, it will be polled every few milliseconds (MSDOS)."
  2411 
  2410 
  2412     aStream canBeSelected ifTrue:[
  2411     aStream canBeSelected ifTrue:[
  2413         "/ can this stream be selected on ?
  2412 	"/ can this stream be selected on ?
  2414         self signal:aSemaphore onInput:aStream fileDescriptor orCheck:nil
  2413 	self signal:aSemaphore onInput:aStream fileDescriptor orCheck:nil
  2415     ] ifFalse:[
  2414     ] ifFalse:[
  2416         "/ nope - must poll ...
  2415 	"/ nope - must poll ...
  2417         self signal:aSemaphore onInput:nil orCheck:[aStream canReadWithoutBlocking]
  2416 	self signal:aSemaphore onInput:nil orCheck:[aStream canReadWithoutBlocking]
  2418     ]
  2417     ]
  2419 
  2418 
  2420     "Modified: / 14.12.1999 / 23:58:50 / cg"
  2419     "Modified: / 14.12.1999 / 23:58:50 / cg"
  2421 !
  2420 !
  2422 
  2421 
  2482     "arrange for a semaphore to be triggered when output on aStream is possible. 
  2481     "arrange for a semaphore to be triggered when output on aStream is possible. 
  2483      This will do a select, if the OS supports selecting on that filedescriptor,
  2482      This will do a select, if the OS supports selecting on that filedescriptor,
  2484      otherwise, it will be polled every few milliseconds (MSDOS)."
  2483      otherwise, it will be polled every few milliseconds (MSDOS)."
  2485 
  2484 
  2486     aStream canBeSelected ifTrue:[
  2485     aStream canBeSelected ifTrue:[
  2487         "/ can this stream be selected on ?
  2486 	"/ can this stream be selected on ?
  2488         self signal:aSemaphore onOutput:aStream fileDescriptor orCheck:nil
  2487 	self signal:aSemaphore onOutput:aStream fileDescriptor orCheck:nil
  2489     ] ifFalse:[
  2488     ] ifFalse:[
  2490         "/ nope - must poll ...
  2489 	"/ nope - must poll ...
  2491         self signal:aSemaphore onOutput:nil orCheck:[aStream canWriteWithoutBlocking]
  2490 	self signal:aSemaphore onOutput:nil orCheck:[aStream canWriteWithoutBlocking]
  2492     ]
  2491     ]
  2493 
  2492 
  2494     "Modified: / 14.12.1999 / 23:59:19 / cg"
  2493     "Modified: / 14.12.1999 / 23:59:19 / cg"
  2495 ! !
  2494 ! !
  2496 
  2495 
  2503      If enabled, arrangements are made for data-availability to trigger an
  2502      If enabled, arrangements are made for data-availability to trigger an
  2504      interrupt.
  2503      interrupt.
  2505      Using IO interrupts reduces the idle CPU usage of ST/X by some percent
  2504      Using IO interrupts reduces the idle CPU usage of ST/X by some percent
  2506      (typically 2-7%).
  2505      (typically 2-7%).
  2507      Notice: 
  2506      Notice: 
  2508         some systems do not support IO-interrupts (or have a broken stdio-lib), 
  2507 	some systems do not support IO-interrupts (or have a broken stdio-lib), 
  2509         and this feature is always disabled;
  2508 	and this feature is always disabled;
  2510      Also notice:
  2509      Also notice:
  2511         we found that in some Xlib-implementations, interrupted reads are not
  2510 	we found that in some Xlib-implementations, interrupted reads are not
  2512         handled correctly (especially in multi-headed applications), and this
  2511 	handled correctly (especially in multi-headed applications), and this
  2513         feature should be disabled to avoid a blocking XPending.
  2512 	feature should be disabled to avoid a blocking XPending.
  2514 
  2513 
  2515      If this method is used to disable IO interrupts in multi-headed apps, 
  2514      If this method is used to disable IO interrupts in multi-headed apps, 
  2516      it should be invoked BEFORE the display event dispatcher processes are started."
  2515      it should be invoked BEFORE the display event dispatcher processes are started."
  2517 
  2516 
  2518     OperatingSystem supportsIOInterrupts ifTrue:[
  2517     OperatingSystem supportsIOInterrupts ifTrue:[
  2519         useIOInterrupts := aBoolean
  2518 	useIOInterrupts := aBoolean
  2520     ].
  2519     ].
  2521 
  2520 
  2522     "Created: / 15.7.1998 / 13:32:29 / cg"
  2521     "Created: / 15.7.1998 / 13:32:29 / cg"
  2523 ! !
  2522 ! !
  2524 
  2523 
  2835 
  2834 
  2836     "/ must enable interrupts, to be able to get out of a
  2835     "/ must enable interrupts, to be able to get out of a
  2837     "/ long wait (especially, to handle sigChild in the meantime)
  2836     "/ long wait (especially, to handle sigChild in the meantime)
  2838 
  2837 
  2839     (wasBlocked := OperatingSystem interruptsBlocked) ifTrue:[
  2838     (wasBlocked := OperatingSystem interruptsBlocked) ifTrue:[
  2840         OperatingSystem unblockInterrupts.
  2839 	OperatingSystem unblockInterrupts.
  2841     ].
  2840     ].
  2842 
  2841 
  2843     fd := OperatingSystem 
  2842     fd := OperatingSystem 
  2844               selectOnAnyReadable:readFdArray 
  2843 	      selectOnAnyReadable:readFdArray 
  2845                          writable:writeFdArray
  2844 			 writable:writeFdArray
  2846                         exception:nil 
  2845 			exception:nil 
  2847                       withTimeOut:millis.
  2846 		      withTimeOut:millis.
  2848 
  2847 
  2849     wasBlocked ifTrue:[
  2848     wasBlocked ifTrue:[
  2850         OperatingSystem blockInterrupts.
  2849 	OperatingSystem blockInterrupts.
  2851     ].
  2850     ].
  2852 
  2851 
  2853     fd isNil ifTrue:[
  2852     fd isNil ifTrue:[
  2854         "/ either still nothing to do,
  2853 	"/ either still nothing to do,
  2855         "/ or error (which should not happen)
  2854 	"/ or error (which should not happen)
  2856 
  2855 
  2857         (err := OperatingSystem lastErrorSymbol) notNil ifTrue:[
  2856 	(err := OperatingSystem lastErrorSymbol) notNil ifTrue:[
  2858             err == #EBADF ifTrue:[
  2857 	    err == #EBADF ifTrue:[
  2859 
  2858 
  2860                 "/ mhmh - one of the fd's given to me is corrupt.
  2859 		"/ mhmh - one of the fd's given to me is corrupt.
  2861                 "/ find out which one .... and remove it
  2860 		"/ find out which one .... and remove it
  2862 
  2861 
  2863                 'Processor [info]: obsolete FD in select - clearing' infoPrintCR.
  2862 		'Processor [info]: obsolete FD in select - clearing' infoPrintCR.
  2864                 OperatingSystem clearLastErrorNumber.
  2863 		OperatingSystem clearLastErrorNumber.
  2865                 self removeCorruptedFds
  2864 		self removeCorruptedFds
  2866             ] ifFalse:[
  2865 	    ] ifFalse:[
  2867                 err == #ENOENT ifTrue:[
  2866 		err == #ENOENT ifTrue:[
  2868                     'Processor [warning]: ENOENT in select; rd=' infoPrint.
  2867 		    'Processor [warning]: ENOENT in select; rd=' infoPrint.
  2869                     readFdArray infoPrint.
  2868 		    readFdArray infoPrint.
  2870                     ' wr=' infoPrint.
  2869 		    ' wr=' infoPrint.
  2871                     writeFdArray infoPrintCR.
  2870 		    writeFdArray infoPrintCR.
  2872                 ] ifFalse:[
  2871 		] ifFalse:[
  2873                     'Processor [warning]: error in select: ' infoPrint. err infoPrintCR.
  2872 		    'Processor [warning]: error in select: ' infoPrint. err infoPrintCR.
  2874                 ]
  2873 		]
  2875             ].
  2874 	    ].
  2876         ]
  2875 	]
  2877     ] ifFalse:[
  2876     ] ifFalse:[
  2878         index := readFdArray identityIndexOf:fd.
  2877 	index := readFdArray identityIndexOf:fd.
  2879         index ~~ 0 ifTrue:[
  2878 	index ~~ 0 ifTrue:[
  2880             sema := readSemaphoreArray at:index.
  2879 	    sema := readSemaphoreArray at:index.
  2881             sema notNil ifTrue:[
  2880 	    sema notNil ifTrue:[
  2882                 sema signalOnce.
  2881 		sema signalOnce.
  2883                 ^ true
  2882 		^ true
  2884             ].
  2883 	    ].
  2885             action := readCheckArray at:index.
  2884 	    action := readCheckArray at:index.
  2886             action notNil ifTrue:[
  2885 	    action notNil ifTrue:[
  2887                 action value.
  2886 		action value.
  2888                  ^ true
  2887 		 ^ true
  2889             ]
  2888 	    ]
  2890         ].
  2889 	].
  2891         index := writeFdArray identityIndexOf:fd.
  2890 	index := writeFdArray identityIndexOf:fd.
  2892         index ~~ 0 ifTrue:[
  2891 	index ~~ 0 ifTrue:[
  2893             sema := writeSemaphoreArray at:index.
  2892 	    sema := writeSemaphoreArray at:index.
  2894             sema notNil ifTrue:[
  2893 	    sema notNil ifTrue:[
  2895                 sema signalOnce.
  2894 		sema signalOnce.
  2896                  ^ true
  2895 		 ^ true
  2897             ].
  2896 	    ].
  2898             action := writeCheckArray at:index.
  2897 	    action := writeCheckArray at:index.
  2899             action notNil ifTrue:[
  2898 	    action notNil ifTrue:[
  2900                 action value.
  2899 		action value.
  2901                  ^ true
  2900 		 ^ true
  2902             ]
  2901 	    ]
  2903         ]
  2902 	]
  2904     ].
  2903     ].
  2905     ^ false
  2904     ^ false
  2906 
  2905 
  2907     "Modified: / 12.4.1996 / 09:31:22 / stefan"
  2906     "Modified: / 12.4.1996 / 09:31:22 / stefan"
  2908     "Modified: / 14.6.1998 / 17:31:51 / cg"
  2907     "Modified: / 14.6.1998 / 17:31:51 / cg"
  3053 
  3052 
  3054     |millis doingGC anySema dT|
  3053     |millis doingGC anySema dT|
  3055 
  3054 
  3056     doingGC := true.
  3055     doingGC := true.
  3057     [doingGC] whileTrue:[
  3056     [doingGC] whileTrue:[
  3058         anyTimeouts ifTrue:[
  3057 	anyTimeouts ifTrue:[
  3059             millis := self timeToNextTimeout.
  3058 	    millis := self timeToNextTimeout.
  3060             (millis notNil and:[millis <= 0]) ifTrue:[
  3059 	    (millis notNil and:[millis <= 0]) ifTrue:[
  3061                 ^ self    "oops - hurry up checking"
  3060 		^ self    "oops - hurry up checking"
  3062             ].
  3061 	    ].
  3063         ].
  3062 	].
  3064 
  3063 
  3065         "
  3064 	"
  3066          if its worth doing, collect a bit of garbage;
  3065 	 if its worth doing, collect a bit of garbage;
  3067          but not, if a backgroundCollector is active
  3066 	 but not, if a backgroundCollector is active
  3068         "
  3067 	"
  3069         ObjectMemory backgroundCollectorRunning ifTrue:[
  3068 	ObjectMemory backgroundCollectorRunning ifTrue:[
  3070             doingGC := false
  3069 	    doingGC := false
  3071         ] ifFalse:[
  3070 	] ifFalse:[
  3072             doingGC := ObjectMemory gcStepIfUseful.
  3071 	    doingGC := ObjectMemory gcStepIfUseful.
  3073         ].
  3072 	].
  3074 
  3073 
  3075         "then do idle actions"
  3074 	"then do idle actions"
  3076         (idleActions notNil and:[idleActions size ~~ 0]) ifTrue:[
  3075 	(idleActions notNil and:[idleActions size ~~ 0]) ifTrue:[
  3077             idleActions do:[:aBlock |
  3076 	    idleActions do:[:aBlock |
  3078                 aBlock value.
  3077 		aBlock value.
  3079             ].
  3078 	    ].
  3080             ^ self   "go back checking"
  3079 	    ^ self   "go back checking"
  3081         ].
  3080 	].
  3082 
  3081 
  3083         doingGC ifTrue:[
  3082 	doingGC ifTrue:[
  3084             (self checkForInputWithTimeout:0) ifTrue:[
  3083 	    (self checkForInputWithTimeout:0) ifTrue:[
  3085                 ^ self  "go back checking"
  3084 		^ self  "go back checking"
  3086             ]
  3085 	    ]
  3087         ]
  3086 	]
  3088     ].
  3087     ].
  3089 
  3088 
  3090     exitWhenNoMoreUserProcesses ifTrue:[
  3089     exitWhenNoMoreUserProcesses ifTrue:[
  3091         "/ check if there are any processes at all
  3090 	"/ check if there are any processes at all
  3092         "/ stop dispatching if there is none
  3091 	"/ stop dispatching if there is none
  3093         "/ (and millis is nil, which means that no timeout blocks are present)
  3092 	"/ (and millis is nil, which means that no timeout blocks are present)
  3094         "/ and no readSemaphores are present (which means that noone is waiting for input)
  3093 	"/ and no readSemaphores are present (which means that noone is waiting for input)
  3095         "/ and no writeSemaphores are present
  3094 	"/ and no writeSemaphores are present
  3096 
  3095 
  3097         anySema := false.
  3096 	anySema := false.
  3098         anySema := (readSemaphoreArray findFirst:[:sema | sema notNil]) ~~ 0.
  3097 	anySema := (readSemaphoreArray findFirst:[:sema | sema notNil]) ~~ 0.
  3099         anySema ifFalse:[
  3098 	anySema ifFalse:[
  3100             anySema := (writeSemaphoreArray findFirst:[:sema | sema notNil]) ~~ 0.
  3099 	    anySema := (writeSemaphoreArray findFirst:[:sema | sema notNil]) ~~ 0.
  3101         ].
  3100 	].
  3102         anySema ifFalse:[
  3101 	anySema ifFalse:[
  3103             self anyUserProcessAtAll ifFalse:[
  3102 	    self anyUserProcessAtAll ifFalse:[
  3104                 dispatching := false.
  3103 		dispatching := false.
  3105                 ^ self
  3104 		^ self
  3106             ]
  3105 	    ]
  3107         ].
  3106 	].
  3108     ].
  3107     ].
  3109 
  3108 
  3110     "/
  3109     "/
  3111     "/ absolutely nothing to do - simply wait
  3110     "/ absolutely nothing to do - simply wait
  3112     "/
  3111     "/
  3113     OperatingSystem supportsSelect ifFalse:[
  3112     OperatingSystem supportsSelect ifFalse:[
  3114         "SCO instant ShitStation has a bug here,
  3113 	"SCO instant ShitStation has a bug here,
  3115          waiting always 1 sec in the select - therefore we delay a bit and
  3114 	 waiting always 1 sec in the select - therefore we delay a bit and
  3116          return - effectively polling in 50ms cycles
  3115 	 return - effectively polling in 50ms cycles
  3117         "
  3116 	"
  3118         (self checkForInputWithTimeout:0) ifTrue:[
  3117 	(self checkForInputWithTimeout:0) ifTrue:[
  3119             ^ self  "go back checking"
  3118 	    ^ self  "go back checking"
  3120         ].
  3119 	].
  3121         OperatingSystem millisecondDelay:EventPollingInterval.
  3120 	OperatingSystem millisecondDelay:EventPollingInterval.
  3122         ^ self
  3121 	^ self
  3123     ].
  3122     ].
  3124 
  3123 
  3125     useIOInterrupts ifTrue:[
  3124     useIOInterrupts ifTrue:[
  3126         dT := 999999
  3125 	dT := 999999
  3127     ] ifFalse:[
  3126     ] ifFalse:[
  3128         dT := EventPollingInterval
  3127 	dT := EventPollingInterval
  3129     ].
  3128     ].
  3130 
  3129 
  3131     millis isNil ifTrue:[
  3130     millis isNil ifTrue:[
  3132         millis := dT.
  3131 	millis := dT.
  3133     ] ifFalse:[
  3132     ] ifFalse:[
  3134         millis := millis rounded min:dT.
  3133 	millis := millis rounded min:dT.
  3135     ].
  3134     ].
  3136     self checkForInputWithTimeout:millis
  3135     self checkForInputWithTimeout:millis
  3137 
  3136 
  3138     "Modified: 14.12.1995 / 13:37:46 / stefan"
  3137     "Modified: 14.12.1995 / 13:37:46 / stefan"
  3139     "Modified: 18.7.1996 / 20:42:17 / cg"
  3138     "Modified: 18.7.1996 / 20:42:17 / cg"
  3140 ! !
  3139 ! !
  3141 
  3140 
  3142 !ProcessorScheduler class methodsFor:'documentation'!
  3141 !ProcessorScheduler class methodsFor:'documentation'!
  3143 
  3142 
  3144 version
  3143 version
  3145     ^ '$Header: /cvs/stx/stx/libbasic/ProcessorScheduler.st,v 1.195 2001-12-06 08:52:25 cg Exp $'
  3144     ^ '$Header: /cvs/stx/stx/libbasic/ProcessorScheduler.st,v 1.196 2002-02-04 14:31:14 cg Exp $'
  3146 ! !
  3145 ! !
  3147 ProcessorScheduler initialize!
  3146 ProcessorScheduler initialize!