ProcessorScheduler.st
changeset 5101 901c91d6dd50
parent 4879 a4fc6ad599f6
child 5103 7b1f6c93b3aa
equal deleted inserted replaced
5100:58ac5885aa41 5101:901c91d6dd50
    11 "
    11 "
    12 
    12 
    13 Object subclass:#ProcessorScheduler
    13 Object subclass:#ProcessorScheduler
    14 	instanceVariableNames:'quiescentProcessLists scheduler zombie activeProcess
    14 	instanceVariableNames:'quiescentProcessLists scheduler zombie activeProcess
    15 		activeProcessId currentPriority readFdArray readSemaphoreArray
    15 		activeProcessId currentPriority readFdArray readSemaphoreArray
    16 		readCheckArray writeFdArray writeSemaphoreArray timeoutArray
    16 		readCheckArray writeFdArray writeSemaphoreArray writeCheckArray timeoutArray
    17 		timeoutActionArray timeoutProcessArray timeoutSemaphoreArray
    17 		timeoutActionArray timeoutProcessArray timeoutSemaphoreArray
    18 		idleActions anyTimeouts dispatching interruptedProcess
    18 		idleActions anyTimeouts dispatching interruptedProcess
    19 		useIOInterrupts gotIOInterrupt osChildExitActions
    19 		useIOInterrupts gotIOInterrupt osChildExitActions
    20 		gotChildSignalInterrupt exitWhenNoMoreUserProcesses
    20 		gotChildSignalInterrupt exitWhenNoMoreUserProcesses
    21 		suspendScheduler timeSliceProcess supportDynamicPriorities
    21 		suspendScheduler timeSliceProcess supportDynamicPriorities
   111                                                 
   111                                                 
   112 	TimeSlicingPriorityLimit                for preemptive priority scheduling only:
   112 	TimeSlicingPriorityLimit                for preemptive priority scheduling only:
   113 						processes are only timesliced, if running 
   113 						processes are only timesliced, if running 
   114 						at or below this priority.
   114 						at or below this priority.
   115 
   115 
   116 	EventPollingInterval			for systems which do not support select on
   116 	EventPollingInterval                    for systems which do not support select on
   117 						a fileDescriptor: the polling interval in millis.
   117 						a fileDescriptor: the polling interval in millis.
   118 
   118 
   119     most interesting methods:
   119     most interesting methods:
   120 
   120 
   121 	Processor>>suspend:                  (see also Process>>suspend)
   121 	Processor>>suspend:                  (see also Process>>suspend)
   174     event.
   174     event.
   175     Timeslicing will not be done for processes running above TimeSlicingPriorityLimit, which
   175     Timeslicing will not be done for processes running above TimeSlicingPriorityLimit, which
   176     allows for critical processes to run unaffected to completion.
   176     allows for critical processes to run unaffected to completion.
   177 
   177 
   178     WARNING:
   178     WARNING:
   179         timesliced priority scheduling is an experimental feature. There is no warranty,
   179 	timesliced priority scheduling is an experimental feature. There is no warranty,
   180         (at the moment), that the system runs reliable in this mode.
   180 	(at the moment), that the system runs reliable in this mode.
   181         The problem is, that shared collections may now be easily modified by other
   181 	The problem is, that shared collections may now be easily modified by other
   182         processes, running at the same time. 
   182 	processes, running at the same time. 
   183         The class library has being investigated for such possible trouble spots 
   183 	The class library has being investigated for such possible trouble spots 
   184         (we have eliminated many weak spots, and added critical regions at many places,
   184 	(we have eliminated many weak spots, and added critical regions at many places,
   185          but cannot guarantee that all of them have been found so far ...)
   185 	 but cannot guarantee that all of them have been found so far ...)
   186         We found that many existing public domain programs are not prepared for
   186 	We found that many existing public domain programs are not prepared for
   187         being interrupted by a same-prio process and therefore may corrupt their
   187 	being interrupted by a same-prio process and therefore may corrupt their
   188         data. If in doubt, disable this fefature.
   188 	data. If in doubt, disable this fefature.
   189 
   189 
   190     We think, that the timeSlicer is a useful add-on and that the system is fit enough
   190     We think, that the timeSlicer is a useful add-on and that the system is fit enough
   191     for it to be evaluated, therefore, its included. 
   191     for it to be evaluated, therefore, its included. 
   192     However, use it at your own risk.
   192     However, use it at your own risk.
   193 
   193 
   194     To demonstrate the effect of timeSlicing, do the following:
   194     To demonstrate the effect of timeSlicing, do the following:
   195 
   195 
   196         - disable timeSlicing (in the launchers misc-settings menu)
   196 	- disable timeSlicing (in the launchers misc-settings menu)
   197         - open a workSpace
   197 	- open a workSpace
   198         - in the workspace, evaluate:
   198 	- in the workspace, evaluate:
   199                 [true] whileTrue:[1000 factorial]
   199 		[true] whileTrue:[1000 factorial]
   200 
   200 
   201     now, (since the workSpace runs at the same prio as other window-processes),
   201     now, (since the workSpace runs at the same prio as other window-processes),
   202     other views do no longer react - all CPU is used up by the workSpace.
   202     other views do no longer react - all CPU is used up by the workSpace.
   203     However, CTRL-C in the workspace is still possible to stop the endless loop,
   203     However, CTRL-C in the workspace is still possible to stop the endless loop,
   204     since that is handled by the (higher prio) event dispatcher process.
   204     since that is handled by the (higher prio) event dispatcher process.
   305     "physical creation of a process.
   305     "physical creation of a process.
   306      (warning: low level entry, no administration done).
   306      (warning: low level entry, no administration done).
   307      This may raise an exception, if a VM process could not be created."
   307      This may raise an exception, if a VM process could not be created."
   308 
   308 
   309     MaxNumberOfProcesses notNil ifTrue:[
   309     MaxNumberOfProcesses notNil ifTrue:[
   310         KnownProcessIds size >= MaxNumberOfProcesses ifTrue:[
   310 	KnownProcessIds size >= MaxNumberOfProcesses ifTrue:[
   311             (KnownProcessIds count:[:el | el notNil]) >= MaxNumberOfProcesses ifTrue:[
   311 	    (KnownProcessIds count:[:el | el notNil]) >= MaxNumberOfProcesses ifTrue:[
   312                 "
   312 		"
   313                  the number of processes has reached the (soft) limit.
   313 		 the number of processes has reached the (soft) limit.
   314                  This limit prevents runaway programs from creating too many
   314 		 This limit prevents runaway programs from creating too many
   315                  processes. If you continue in the debugger, the process will be
   315 		 processes. If you continue in the debugger, the process will be
   316                  created as usual. If you dont want this, abort or terminate.
   316 		 created as usual. If you dont want this, abort or terminate.
   317                 "
   317 		"
   318                 self error:'too many processes'.
   318 		self error:'too many processes'.
   319             ]
   319 	    ]
   320         ]
   320 	]
   321     ].
   321     ].
   322 
   322 
   323 %{
   323 %{
   324     int tid;
   324     int tid;
   325     extern int __threadCreate();
   325     extern int __threadCreate();
   326 
   326 
   327     tid = __threadCreate(aProcess, 
   327     tid = __threadCreate(aProcess, 
   328                          0   /* stackSize: no longer needed */, 
   328 			 0   /* stackSize: no longer needed */, 
   329                          __isSmallInteger(id) ? __intVal(id)     /* assign id */
   329 			 __isSmallInteger(id) ? __intVal(id)     /* assign id */
   330                                               : -1              /* let VM assign one */  );
   330 					      : -1              /* let VM assign one */  );
   331     if (tid) {
   331     if (tid) {
   332         RETURN ( __MKSMALLINT(tid));
   332 	RETURN ( __MKSMALLINT(tid));
   333     }
   333     }
   334 %}
   334 %}
   335 .
   335 .
   336     "
   336     "
   337      arrive here, if creation of process in VM failed.
   337      arrive here, if creation of process in VM failed.
   430 ! !
   430 ! !
   431 
   431 
   432 !ProcessorScheduler methodsFor:'I/O event actions'!
   432 !ProcessorScheduler methodsFor:'I/O event actions'!
   433 
   433 
   434 disableFd:aFileDescriptor
   434 disableFd:aFileDescriptor
   435     "disable block events on aFileDescriptor.
   435     "obsolete event support: disable block events on aFileDescriptor.
   436      This is a leftover support for pure-event systems and may vanish."
   436      This is a leftover support for pure-event systems and may vanish."
   437 
   437 
   438     |idx "{Class: SmallInteger }" 
   438     |idx "{Class: SmallInteger }" 
   439      wasBlocked|
   439      wasBlocked|
   440 
   440 
   441     wasBlocked := OperatingSystem blockInterrupts.
   441     wasBlocked := OperatingSystem blockInterrupts.
       
   442     useIOInterrupts ifTrue:[
       
   443 	OperatingSystem disableIOInterruptsOn:aFileDescriptor
       
   444     ].
       
   445 
   442     idx := readFdArray identityIndexOf:aFileDescriptor startingAt:1.
   446     idx := readFdArray identityIndexOf:aFileDescriptor startingAt:1.
   443     idx ~~ 0 ifTrue:[
   447     idx ~~ 0 ifTrue:[
   444         useIOInterrupts ifTrue:[
   448 	readFdArray at:idx put:nil.
   445             OperatingSystem disableIOInterruptsOn:aFileDescriptor
   449 	readCheckArray at:idx put:nil.
   446         ].
   450 	readSemaphoreArray at:idx put:nil
   447         readFdArray at:idx put:nil.
   451     ].
   448         readCheckArray at:idx put:nil.
   452     idx := writeFdArray identityIndexOf:aFileDescriptor startingAt:1.
   449         readSemaphoreArray at:idx put:nil
   453     idx ~~ 0 ifTrue:[
       
   454 	writeFdArray at:idx put:nil.
       
   455 	writeCheckArray at:idx put:nil.
       
   456 	writeSemaphoreArray at:idx put:nil
   450     ].
   457     ].
   451     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   458     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   452 
   459 
   453     "Modified: 4.8.1997 / 15:16:00 / cg"
   460     "Modified: 4.8.1997 / 15:16:00 / cg"
   454 !
   461 !
   455 
   462 
   456 enableIOAction:aBlock onInput:aFileDescriptor
   463 enableIOAction:aBlock onInput:aFileDescriptor
   457     "half-obsolete event support: arrange for aBlock to be
   464     "obsolete event support: arrange for aBlock to be
   458      evaluated when input on aFileDescriptor arrives. 
   465      evaluated when input on aFileDescriptor arrives. 
   459      This is a leftover support for pure-event systems and may vanish."
   466      This is a leftover support for pure-event systems and may vanish."
   460 
   467 
   461     |idx "{Class: SmallInteger }"
   468     |idx "{Class: SmallInteger }"
   462      wasBlocked|
   469      wasBlocked|
   467 	^ self
   474 	^ self
   468     ].
   475     ].
   469 
   476 
   470     wasBlocked := OperatingSystem blockInterrupts.
   477     wasBlocked := OperatingSystem blockInterrupts.
   471     (readFdArray identityIndexOf:aFileDescriptor startingAt:1) == 0 ifTrue:[
   478     (readFdArray identityIndexOf:aFileDescriptor startingAt:1) == 0 ifTrue:[
   472         idx := readFdArray identityIndexOf:nil startingAt:1.
   479 	idx := readFdArray identityIndexOf:nil startingAt:1.
   473         idx ~~ 0 ifTrue:[
   480 	idx ~~ 0 ifTrue:[
   474             readFdArray at:idx put:aFileDescriptor.
   481 	    readFdArray at:idx put:aFileDescriptor.
   475             readCheckArray at:idx put:aBlock.
   482 	    readCheckArray at:idx put:aBlock.
   476             readSemaphoreArray at:idx put:nil
   483 	    readSemaphoreArray at:idx put:nil
   477         ] ifFalse:[
   484 	] ifFalse:[
   478             readFdArray := readFdArray copyWith:aFileDescriptor.
   485 	    readFdArray := readFdArray copyWith:aFileDescriptor.
   479             readCheckArray := readCheckArray copyWith:aBlock.
   486 	    readCheckArray := readCheckArray copyWith:aBlock.
   480             readSemaphoreArray := readSemaphoreArray copyWith:nil.
   487 	    readSemaphoreArray := readSemaphoreArray copyWith:nil.
   481         ].
   488 	].
   482         useIOInterrupts ifTrue:[
   489 	useIOInterrupts ifTrue:[
   483             OperatingSystem enableIOInterruptsOn:aFileDescriptor
   490 	    OperatingSystem enableIOInterruptsOn:aFileDescriptor
   484         ].
   491 	].
   485 
   492 
   486     ].
   493     ].
   487     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   494     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   488 
   495 
   489     "Modified: 4.8.1997 / 15:17:28 / cg"
   496     "Modified: 4.8.1997 / 15:17:28 / cg"
   577 
   584 
   578     "
   585     "
   579      handle all timeout actions
   586      handle all timeout actions
   580     "
   587     "
   581     anyTimeouts ifTrue:[
   588     anyTimeouts ifTrue:[
   582         self evaluateTimeouts
   589 	self evaluateTimeouts
   583     ].
   590     ].
   584 
   591 
   585     "first do a quick check for semaphores using checkActions - this is needed for
   592     "first do a quick check for semaphores using checkActions - this is needed for
   586      devices like the X-connection, where some events might be in the event
   593      devices like the X-connection, where some events might be in the event
   587      queue but the sockets input queue is empty. 
   594      queue but the sockets input queue is empty. 
   588      Without these checks, a select might block even though there is work to do
   595      Without these checks, a select might block even though there is work to do.
       
   596      Also, this is needed for poor MSDOS, where WaitForObject does not work with
       
   597      sockets and pipes (sigh)
   589     "
   598     "
   590     any := false.
   599     any := false.
   591     nActions := readCheckArray size.
   600     nActions := readCheckArray size.
   592     1 to:nActions do:[:index |
   601     1 to:nActions do:[:index |
   593         checkBlock := readCheckArray at:index.
   602 	checkBlock := readCheckArray at:index.
   594         (checkBlock notNil and:[checkBlock value]) ifTrue:[
   603 	(checkBlock notNil and:[checkBlock value]) ifTrue:[
   595             sema := readSemaphoreArray at:index.
   604 	    sema := readSemaphoreArray at:index.
   596             sema notNil ifTrue:[
   605 	    sema notNil ifTrue:[
   597                 sema signalOnce.
   606 		sema signalOnce.
   598             ].
   607 	    ].
   599             any := true.
   608 	    any := true.
   600         ]
   609 	]
       
   610     ].
       
   611     nActions := writeCheckArray size.
       
   612     1 to:nActions do:[:index |
       
   613 	checkBlock := writeCheckArray at:index.
       
   614 	(checkBlock notNil and:[checkBlock value]) ifTrue:[
       
   615 	    sema := writeSemaphoreArray at:index.
       
   616 	    sema notNil ifTrue:[
       
   617 		sema signalOnce.
       
   618 	    ].
       
   619 	    any := true.
       
   620 	]
   601     ].
   621     ].
   602 
   622 
   603     "now, someone might be runnable ..."
   623     "now, someone might be runnable ..."
   604 
   624 
   605     p := self highestPriorityRunnableProcess.
   625     p := self highestPriorityRunnableProcess.
   606     p isNil ifTrue:[
   626     p isNil ifTrue:[
   607         "/ no one runnable, hard wait for event or timeout
   627 	"/ no one runnable, hard wait for event or timeout
   608 
   628 
   609         self waitForEventOrTimeout.
   629 	self waitForEventOrTimeout.
   610 
   630 
   611         "/ check for OS process termination
   631 	"/ check for OS process termination
   612         gotChildSignalInterrupt ifTrue:[
   632 	gotChildSignalInterrupt ifTrue:[
   613             gotChildSignalInterrupt := false.
   633 	    gotChildSignalInterrupt := false.
   614             self handleChildSignalInterrupt
   634 	    self handleChildSignalInterrupt
   615         ].
   635 	].
   616 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   636 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   617         ^ self
   637 	^ self
   618     ].
   638     ].
   619 
   639 
   620     pri := p priority.
   640     pri := p priority.
   621 
   641 
   622     "
   642     "
   643  (a future version will have a process running to handle a timeout queue)
   663  (a future version will have a process running to handle a timeout queue)
   644 "
   664 "
   645 
   665 
   646 "
   666 "
   647     pri < TimingPriority ifTrue:[
   667     pri < TimingPriority ifTrue:[
   648         anyTimeouts ifTrue:[
   668 	anyTimeouts ifTrue:[
   649             millis := self timeToNextTimeout.
   669 	    millis := self timeToNextTimeout.
   650             millis == 0 ifTrue:[
   670 	    millis == 0 ifTrue:[
   651 	        wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   671 		wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   652 		^ self
   672 		^ self
   653 	    ]
   673 	    ]
   654         ]
   674 	]
   655     ].
   675     ].
   656 "
   676 "
   657 
   677 
   658     "
   678     "
   659      if the process to run has a lower than UserInterruptPriority,
   679      if the process to run has a lower than UserInterruptPriority,
   662      or by installing a poll-interrupt after 50ms (if the OS does not).
   682      or by installing a poll-interrupt after 50ms (if the OS does not).
   663     "
   683     "
   664     pri < UserInterruptPriority ifTrue:[
   684     pri < UserInterruptPriority ifTrue:[
   665     
   685     
   666 "comment out this if above is uncommented"
   686 "comment out this if above is uncommented"
   667         anyTimeouts ifTrue:[
   687 	anyTimeouts ifTrue:[
   668             millis := self timeToNextTimeout.
   688 	    millis := self timeToNextTimeout.
   669             millis == 0 ifTrue:[
   689 	    millis == 0 ifTrue:[
   670 	        wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   690 		wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   671 		^ self
   691 		^ self
   672 	    ].
   692 	    ].
   673         ].
   693 	].
   674 "---"
   694 "---"
   675 
   695 
   676         useIOInterrupts ifTrue:[
   696 	useIOInterrupts ifTrue:[
   677 "/            readFdArray do:[:fd |
   697 "/            readFdArray do:[:fd |
   678 "/                (fd notNil and:[fd >= 0]) ifTrue:[
   698 "/                (fd notNil and:[fd >= 0]) ifTrue:[
   679 "/                    OperatingSystem enableIOInterruptsOn:fd
   699 "/                    OperatingSystem enableIOInterruptsOn:fd
   680 "/                ].
   700 "/                ].
   681 "/            ].
   701 "/            ].
   682         ] ifFalse:[
   702 	] ifFalse:[
   683             millis notNil ifTrue:[
   703 	    millis notNil ifTrue:[
   684                 millis := millis min:EventPollingInterval
   704 		millis := millis min:EventPollingInterval
   685             ] ifFalse:[
   705 	    ] ifFalse:[
   686                 millis := EventPollingInterval
   706 		millis := EventPollingInterval
   687             ]
   707 	    ]
   688         ]
   708 	]
   689     ].
   709     ].
   690 
   710 
   691     millis notNil ifTrue:[
   711     millis notNil ifTrue:[
   692         "schedule a clock interrupt after millis milliseconds"
   712 	"schedule a clock interrupt after millis milliseconds"
   693         OperatingSystem enableTimer:millis rounded.
   713 	OperatingSystem enableTimer:millis rounded.
   694     ].
   714     ].
   695 
   715 
   696     scheduledProcesses notNil ifTrue:[
   716     scheduledProcesses notNil ifTrue:[
   697         scheduledProcesses add:p
   717 	scheduledProcesses add:p
   698     ].
   718     ].
   699 
   719 
   700     "
   720     "
   701      now let the process run - will come back here by reschedule
   721      now let the process run - will come back here by reschedule
   702      from ioInterrupt or timerInterrupt ... (running at max+1)
   722      from ioInterrupt or timerInterrupt ... (running at max+1)
   703     "
   723     "
   704     self threadSwitch:p.
   724     self threadSwitch:p.
   705 
   725 
   706     "... when we arrive here, we are back on stage.
   726     "... when we arrive here, we are back on stage.
   707          Either by an ALARM or IO signal, or by a suspend of another process
   727 	 Either by an ALARM or IO signal, or by a suspend of another process
   708     "
   728     "
   709 
   729 
   710     millis notNil ifTrue:[
   730     millis notNil ifTrue:[
   711         OperatingSystem disableTimer.
   731 	OperatingSystem disableTimer.
   712     ].
   732     ].
   713 
   733 
   714     "/ check for OS process termination
   734     "/ check for OS process termination
   715     gotChildSignalInterrupt ifTrue:[
   735     gotChildSignalInterrupt ifTrue:[
   716         gotChildSignalInterrupt := false.
   736 	gotChildSignalInterrupt := false.
   717         self handleChildSignalInterrupt
   737 	self handleChildSignalInterrupt
   718     ].
   738     ].
   719 
   739 
   720     "/ check for new input
   740     "/ check for new input
   721 
   741 
   722     OperatingSystem unblockInterrupts.
   742     OperatingSystem unblockInterrupts.
   723 
   743 
   724     (gotIOInterrupt or:[useIOInterrupts not]) ifTrue:[
   744     (gotIOInterrupt or:[useIOInterrupts not]) ifTrue:[
   725         gotIOInterrupt := false.
   745 	gotIOInterrupt := false.
   726         self checkForInputWithTimeout:0.
   746 	self checkForInputWithTimeout:0.
   727     ].
   747     ].
   728 
   748 
   729     wasBlocked ifTrue:[OperatingSystem blockInterrupts].
   749     wasBlocked ifTrue:[OperatingSystem blockInterrupts].
   730 
   750 
   731     "Modified: / 12.4.1996 / 10:14:18 / stefan"
   751     "Modified: / 12.4.1996 / 10:14:18 / stefan"
   794 
   814 
   795     |nPrios "{ Class: SmallInteger }"
   815     |nPrios "{ Class: SmallInteger }"
   796      p l|
   816      p l|
   797 
   817 
   798     KnownProcesses isNil ifTrue:[
   818     KnownProcesses isNil ifTrue:[
   799         KnownProcesses := WeakArray new:30.
   819 	KnownProcesses := WeakArray new:30.
   800         KnownProcesses addDependent:self class.
   820 	KnownProcesses addDependent:self class.
   801         KnownProcessIds := OrderedCollection new.
   821 	KnownProcessIds := OrderedCollection new.
   802     ].
   822     ].
   803 
   823 
   804     "
   824     "
   805      create a collection with process lists; accessed using the priority as key
   825      create a collection with process lists; accessed using the priority as key
   806     "
   826     "
   809 
   829 
   810     readFdArray := Array new:5.
   830     readFdArray := Array new:5.
   811     readCheckArray := Array new:5.
   831     readCheckArray := Array new:5.
   812     readSemaphoreArray := Array new:5.
   832     readSemaphoreArray := Array new:5.
   813     writeFdArray := Array new:3.
   833     writeFdArray := Array new:3.
       
   834     writeCheckArray := Array new:3.
   814     writeSemaphoreArray := Array new:3.
   835     writeSemaphoreArray := Array new:3.
   815     timeoutArray := Array new:5.
   836     timeoutArray := Array new:5.
   816     timeoutSemaphoreArray := Array new:5.
   837     timeoutSemaphoreArray := Array new:5.
   817     timeoutActionArray := Array new:5.
   838     timeoutActionArray := Array new:5.
   818     timeoutProcessArray := Array new:5.
   839     timeoutProcessArray := Array new:5.
   819 
   840 
   820     anyTimeouts := false.
   841     anyTimeouts := false.
   821     dispatching := false.
   842     dispatching := false.
   822     exitWhenNoMoreUserProcesses isNil ifTrue:[
   843     exitWhenNoMoreUserProcesses isNil ifTrue:[
   823         exitWhenNoMoreUserProcesses := false. "/ mhmh - how about true ?
   844 	exitWhenNoMoreUserProcesses := false. "/ mhmh - how about true ?
   824     ].
   845     ].
   825     useIOInterrupts := OperatingSystem supportsIOInterrupts.
   846     useIOInterrupts := OperatingSystem supportsIOInterrupts.
   826     gotIOInterrupt := false.
   847     gotIOInterrupt := false.
   827     osChildExitActions := Dictionary new.
   848     osChildExitActions := Dictionary new.
   828     gotChildSignalInterrupt := false.
   849     gotChildSignalInterrupt := false.
   875     "
   896     "
   876      lay all processes to rest, collect restartable ones
   897      lay all processes to rest, collect restartable ones
   877     "
   898     "
   878     processesToRestart := OrderedCollection new.
   899     processesToRestart := OrderedCollection new.
   879     KnownProcesses do:[:p |
   900     KnownProcesses do:[:p |
   880         (p notNil and:[p ~~ 0]) ifTrue:[
   901 	(p notNil and:[p ~~ 0]) ifTrue:[
   881             "how, exactly should this be done ?"
   902 	    "how, exactly should this be done ?"
   882 
   903 
   883             p isRestartable == true ifTrue:[
   904 	    p isRestartable == true ifTrue:[
   884                 p nextLink:nil.
   905 		p nextLink:nil.
   885                 processesToRestart add:p
   906 		processesToRestart add:p
   886             ] ifFalse:[
   907 	    ] ifFalse:[
   887                 p setId:nil state:#dead
   908 		p setId:nil state:#dead
   888             ]
   909 	    ]
   889         ].
   910 	].
   890     ].
   911     ].
   891     scheduler setId:nil state:#dead. 
   912     scheduler setId:nil state:#dead. 
   892 
   913 
   893     "
   914     "
   894      now, start from scratch
   915      now, start from scratch
   895     "
   916     "
   896     KnownProcesses := nil.
   917     KnownProcesses := nil.
   897     self initialize.
   918     self initialize.
   898 
   919 
   899     processesToRestart do:[:p |
   920     processesToRestart do:[:p |
   900         p imageRestart
   921 	p imageRestart
   901     ]
   922     ]
   902 
   923 
   903     "Modified: / 7.6.1998 / 02:23:56 / cg"
   924     "Modified: / 7.6.1998 / 02:23:56 / cg"
   904 ! !
   925 ! !
   905 
   926 
   913      This is only used with win32's native threads."
   934      This is only used with win32's native threads."
   914 
   935 
   915     |id pri l s|
   936     |id pri l s|
   916 
   937 
   917     OperatingSystem interruptsBlocked ifFalse:[
   938     OperatingSystem interruptsBlocked ifFalse:[
   918         MiniDebugger 
   939 	MiniDebugger 
   919             enterWithMessage:'immediateInterrupt with no interruptsBlocked'
   940 	    enterWithMessage:'immediateInterrupt with no interruptsBlocked'
   920             mayProceed:true.
   941 	    mayProceed:true.
   921     ].
   942     ].
   922 
   943 
   923     (why == 2) ifTrue:[
   944     (why == 2) ifTrue:[
   924          s := #wrapWait.
   945 	 s := #wrapWait.
   925     ] ifFalse:[
   946     ] ifFalse:[
   926         (why == 3) ifTrue:[
   947 	(why == 3) ifTrue:[
   927             s := #osWait.
   948 	    s := #osWait.
   928         ] ifFalse:[
   949 	] ifFalse:[
   929             s := #stopped.
   950 	    s := #stopped.
   930         ].
   951 	].
   931     ].
   952     ].
   932     activeProcess setStateTo:s if:#active.
   953     activeProcess setStateTo:s if:#active.
   933 
   954 
   934     pri := activeProcess priority.
   955     pri := activeProcess priority.
   935     l := quiescentProcessLists at:pri.
   956     l := quiescentProcessLists at:pri.
   936 
   957 
   937     "notice: this is slightly faster than putting the if-code into
   958     "notice: this is slightly faster than putting the if-code into
   938      the ifAbsent block, because [] is a shared cheap block, created at compile time
   959      the ifAbsent block, because [] is a shared cheap block, created at compile time
   939     "
   960     "
   940     (l isNil or:[(l remove:activeProcess ifAbsent:nil) isNil]) ifTrue:[
   961     (l isNil or:[(l remove:activeProcess ifAbsent:nil) isNil]) ifTrue:[
   941         "/ 'Processor [warning]: bad immediateInterrupt: not on run list' errorPrintCR.
   962 	"/ 'Processor [warning]: bad immediateInterrupt: not on run list' errorPrintCR.
   942         MiniDebugger enterWithMessage:'bad immediateInterrupt: not on run list' mayProceed:true.
   963 	MiniDebugger enterWithMessage:'bad immediateInterrupt: not on run list' mayProceed:true.
   943         ^ self
   964 	^ self
   944     ].
   965     ].
   945 
   966 
   946 "/    id := scheduler id.
   967 "/    id := scheduler id.
   947 "/    pri := scheduler priority.
   968 "/    pri := scheduler priority.
   948 "/    scheduler state:#active.
   969 "/    scheduler state:#active.
   965      This is only used with win32's native threads."
   986      This is only used with win32's native threads."
   966 
   987 
   967     |index pri aProcess l|
   988     |index pri aProcess l|
   968 
   989 
   969     OperatingSystem interruptsBlocked ifFalse:[
   990     OperatingSystem interruptsBlocked ifFalse:[
   970         MiniDebugger 
   991 	MiniDebugger 
   971             enterWithMessage:'resumeImmediateInterrupt with no interruptsBlocked'
   992 	    enterWithMessage:'resumeImmediateInterrupt with no interruptsBlocked'
   972             mayProceed:true.
   993 	    mayProceed:true.
   973     ].
   994     ].
   974     index := KnownProcessIds identityIndexOf:id.
   995     index := KnownProcessIds identityIndexOf:id.
   975     index ~~ 0 ifTrue:[
   996     index ~~ 0 ifTrue:[
   976         aProcess := KnownProcesses at:index.
   997 	aProcess := KnownProcesses at:index.
   977         "/
   998 	"/
   978         "/ CG: the situation below may happen, if the wrapCall
   999 	"/ CG: the situation below may happen, if the wrapCall
   979         "/ finishes before the process was layed to sleep
  1000 	"/ finishes before the process was layed to sleep
   980         "/ (i.e. schedulerIRQ arrives before the threadSwitch
  1001 	"/ (i.e. schedulerIRQ arrives before the threadSwitch
   981         "/ was finished.
  1002 	"/ was finished.
   982         "/ In that case, simply resume it and everything is OK.
  1003 	"/ In that case, simply resume it and everything is OK.
   983         "/
  1004 	"/
   984 "/        aProcess state ~~ #wrapWait ifTrue:[
  1005 "/        aProcess state ~~ #wrapWait ifTrue:[
   985 "/            'ProcSched [info]: oops - resumeImmIRQ for non wrapWait process' infoPrintCR.
  1006 "/            'ProcSched [info]: oops - resumeImmIRQ for non wrapWait process' infoPrintCR.
   986 "/            ^ self
  1007 "/            ^ self
   987 "/        ].
  1008 "/        ].
   988         pri := aProcess priority.
  1009 	pri := aProcess priority.
   989         l := quiescentProcessLists at:pri.
  1010 	l := quiescentProcessLists at:pri.
   990         "if already running, ignore"
  1011 	"if already running, ignore"
   991         l notNil ifTrue:[
  1012 	l notNil ifTrue:[
   992             (l identityIndexOf:aProcess) ~~ 0 ifTrue:[
  1013 	    (l identityIndexOf:aProcess) ~~ 0 ifTrue:[
   993                 'ProcSched [info]: oops - resumeImmIRQ for already running process' infoPrintCR.
  1014 		'ProcSched [info]: oops - resumeImmIRQ for already running process' infoPrintCR.
   994                 ^ self
  1015 		^ self
   995             ]
  1016 	    ]
   996         ] ifFalse:[
  1017 	] ifFalse:[
   997             l := LinkedList new.
  1018 	    l := LinkedList new.
   998             quiescentProcessLists at:pri put:l.
  1019 	    quiescentProcessLists at:pri put:l.
   999         ].
  1020 	].
  1000         l addLast:aProcess.
  1021 	l addLast:aProcess.
  1001         aProcess state:#run.
  1022 	aProcess state:#run.
  1002     ] ifFalse:[
  1023     ] ifFalse:[
  1003         'ProcSched [info]: oops - resumeImmIRQ for unknown process' infoPrintCR.
  1024 	'ProcSched [info]: oops - resumeImmIRQ for unknown process' infoPrintCR.
  1004     ]
  1025     ]
  1005 
  1026 
  1006     "Modified: / 28.9.1998 / 11:36:53 / cg"
  1027     "Modified: / 28.9.1998 / 11:36:53 / cg"
  1007 ! !
  1028 ! !
  1008 
  1029 
  1014     "child changed state - switch to scheduler process which will decide 
  1035     "child changed state - switch to scheduler process which will decide 
  1015      what to do now."
  1036      what to do now."
  1016 
  1037 
  1017     gotChildSignalInterrupt := true.
  1038     gotChildSignalInterrupt := true.
  1018     activeProcess ~~ scheduler ifTrue:[
  1039     activeProcess ~~ scheduler ifTrue:[
  1019         interruptedProcess := activeProcess.
  1040 	interruptedProcess := activeProcess.
  1020         self threadSwitch:scheduler
  1041 	self threadSwitch:scheduler
  1021     ]
  1042     ]
  1022 
  1043 
  1023     "Modified: 12.4.1996 / 10:12:18 / stefan"
  1044     "Modified: 12.4.1996 / 10:12:18 / stefan"
  1024 !
  1045 !
  1025 
  1046 
  1083      The method returns the value from aBlockReturningPid (i.e a pid or nil)."
  1104      The method returns the value from aBlockReturningPid (i.e a pid or nil)."
  1084 
  1105 
  1085     |pid blocked osProcessStatus|
  1106     |pid blocked osProcessStatus|
  1086 
  1107 
  1087     OperatingSystem supportsChildInterrupts ifTrue:[
  1108     OperatingSystem supportsChildInterrupts ifTrue:[
  1088         "/ SIGCHLD is supported,
  1109 	"/ SIGCHLD is supported,
  1089         "/ aBlock will be evaluated, as soon as a SIGCHLD interrupt for pid has been received.
  1110 	"/ aBlock will be evaluated, as soon as a SIGCHLD interrupt for pid has been received.
  1090 
  1111 
  1091         OperatingSystem enableChildSignalInterrupts.
  1112 	OperatingSystem enableChildSignalInterrupts.
  1092         blocked := OperatingSystem blockInterrupts.
  1113 	blocked := OperatingSystem blockInterrupts.
  1093         pid := aBlockReturningPid value.
  1114 	pid := aBlockReturningPid value.
  1094         pid notNil ifTrue:[
  1115 	pid notNil ifTrue:[
  1095             osChildExitActions at:pid put:actionBlock.
  1116 	    osChildExitActions at:pid put:actionBlock.
  1096         ].
  1117 	].
  1097         blocked ifFalse:[
  1118 	blocked ifFalse:[
  1098             OperatingSystem unblockInterrupts.
  1119 	    OperatingSystem unblockInterrupts.
  1099         ].
  1120 	].
  1100     ] ifFalse:[
  1121     ] ifFalse:[
  1101         "/ SIGCHLD is not supported, fork a high prio process 
  1122 	"/ SIGCHLD is not supported, fork a high prio process 
  1102         "/ to poll for for the exit of pid.
  1123 	"/ to poll for for the exit of pid.
  1103 
  1124 
  1104         blocked := OperatingSystem blockInterrupts.
  1125 	blocked := OperatingSystem blockInterrupts.
  1105         pid := aBlockReturningPid value.
  1126 	pid := aBlockReturningPid value.
  1106         pid notNil ifTrue:[
  1127 	pid notNil ifTrue:[
  1107             osChildExitActions at:pid put:actionBlock.
  1128 	    osChildExitActions at:pid put:actionBlock.
  1108         ].
  1129 	].
  1109         blocked ifFalse:[
  1130 	blocked ifFalse:[
  1110             OperatingSystem unblockInterrupts.
  1131 	    OperatingSystem unblockInterrupts.
  1111         ].
  1132 	].
  1112 
  1133 
  1113         [
  1134 	[
  1114             [
  1135 	    [
  1115               |polling myDelay t|
  1136 	      |polling myDelay t|
  1116 
  1137 
  1117               polling := true.
  1138 	      polling := true.
  1118               myDelay := Delay forMilliseconds:(t := EventPollingInterval).
  1139 	      myDelay := Delay forMilliseconds:(t := EventPollingInterval).
  1119               [polling] whileTrue:[
  1140 	      [polling] whileTrue:[
  1120                   t ~~ EventPollingInterval ifTrue:[
  1141 		  t ~~ EventPollingInterval ifTrue:[
  1121                       "/ interval changed -> need a new delay
  1142 		      "/ interval changed -> need a new delay
  1122                       myDelay delay:(t := EventPollingInterval).
  1143 		      myDelay delay:(t := EventPollingInterval).
  1123                   ].
  1144 		  ].
  1124                   myDelay wait.
  1145 		  myDelay wait.
  1125                   (osChildExitActions includesKey:pid) ifFalse:[
  1146 		  (osChildExitActions includesKey:pid) ifFalse:[
  1126                       polling := false.
  1147 		      polling := false.
  1127                   ] ifTrue:[
  1148 		  ] ifTrue:[
  1128                       osProcessStatus := OperatingSystem childProcessWait:false pid:pid.
  1149 		      osProcessStatus := OperatingSystem childProcessWait:false pid:pid.
  1129                       osProcessStatus notNil ifTrue:[
  1150 		      osProcessStatus notNil ifTrue:[
  1130                           (osProcessStatus pid = pid) ifTrue:[
  1151 			  (osProcessStatus pid = pid) ifTrue:[
  1131                               osChildExitActions removeKey:pid ifAbsent:nil.
  1152 			      osChildExitActions removeKey:pid ifAbsent:nil.
  1132                               actionBlock value:osProcessStatus.
  1153 			      actionBlock value:osProcessStatus.
  1133                               polling := false.
  1154 			      polling := false.
  1134                           ] ifFalse:[
  1155 			  ] ifFalse:[
  1135                               osProcessStatus stillAlive
  1156 			      osProcessStatus stillAlive
  1136                           ]
  1157 			  ]
  1137                       ]
  1158 		      ]
  1138                   ]. 
  1159 		  ]. 
  1139               ]
  1160 	      ]
  1140           ] valueOnUnwindDo:[
  1161 	  ] valueOnUnwindDo:[
  1141               osChildExitActions removeKey:pid ifAbsent:nil
  1162 	      osChildExitActions removeKey:pid ifAbsent:nil
  1142           ]
  1163 	  ]
  1143         ] forkAt:TimingPriority.
  1164 	] forkAt:TimingPriority.
  1144     ].
  1165     ].
  1145     ^ pid
  1166     ^ pid
  1146 
  1167 
  1147     "Created: / 25.3.1997 / 10:54:56 / stefan"
  1168     "Created: / 25.3.1997 / 10:54:56 / stefan"
  1148     "Modified: / 25.3.1997 / 11:21:05 / stefan"
  1169     "Modified: / 25.3.1997 / 11:21:05 / stefan"
  1166     self scheduleInterruptActionsOf:aProcess.
  1187     self scheduleInterruptActionsOf:aProcess.
  1167     "
  1188     "
  1168      and, make the process runnable
  1189      and, make the process runnable
  1169     "
  1190     "
  1170     aProcess state ~~ #stopped ifTrue:[
  1191     aProcess state ~~ #stopped ifTrue:[
  1171         aProcess state == #osWait ifTrue:[
  1192 	aProcess state == #osWait ifTrue:[
  1172             ('Processor [warning]: ignored scheduleForInterrupt:Process ',(aProcess id) printString,' state osWait') errorPrintCR.
  1193 	    ('Processor [warning]: ignored scheduleForInterrupt:Process ',(aProcess id) printString,' state osWait') errorPrintCR.
  1173             "/ self halt.
  1194 	    "/ self halt.
  1174         ] ifFalse:[
  1195 	] ifFalse:[
  1175             "
  1196 	    "
  1176              and, make the process runnable
  1197 	     and, make the process runnable
  1177             "
  1198 	    "
  1178             self resume:aProcess
  1199 	    self resume:aProcess
  1179         ]
  1200 	]
  1180     ]
  1201     ]
  1181 
  1202 
  1182     "Modified: / 24.8.1998 / 18:31:32 / cg"
  1203     "Modified: / 24.8.1998 / 18:31:32 / cg"
  1183 !
  1204 !
  1184 
  1205 
  1226     currentPriority := pri.
  1247     currentPriority := pri.
  1227 %{
  1248 %{
  1228     extern OBJ ___threadSwitch();
  1249     extern OBJ ___threadSwitch();
  1229 
  1250 
  1230     if (__isSmallInteger(id)) {
  1251     if (__isSmallInteger(id)) {
  1231         ok = ___threadSwitch(__context, __intVal(id), (singleStep == true) ? 1 : 0);
  1252 	ok = ___threadSwitch(__context, __intVal(id), (singleStep == true) ? 1 : 0);
  1232     } else {
  1253     } else {
  1233         ok = false;
  1254 	ok = false;
  1234     }
  1255     }
  1235 %}.
  1256 %}.
  1236     "time passes spent in some other process ...
  1257     "time passes spent in some other process ...
  1237      ... here again"
  1258      ... here again"
  1238 
  1259 
  1240     activeProcess := oldProcess.
  1261     activeProcess := oldProcess.
  1241     activeProcessId := oldId.
  1262     activeProcessId := oldId.
  1242     currentPriority := oldProcess priority.
  1263     currentPriority := oldProcess priority.
  1243 
  1264 
  1244     ok == true ifFalse:[
  1265     ok == true ifFalse:[
  1245         "
  1266 	"
  1246          switch failed for some reason -
  1267 	 switch failed for some reason -
  1247          destroy (hard-terminate) the bad process.
  1268 	 destroy (hard-terminate) the bad process.
  1248          This happens when:
  1269 	 This happens when:
  1249          - the stack went above the absolute limit
  1270 	 - the stack went above the absolute limit
  1250            (VM switches back to scheduler)
  1271 	   (VM switches back to scheduler)
  1251          - a halted process cannot execute its interrupt
  1272 	 - a halted process cannot execute its interrupt
  1252            actions (win32 only)
  1273 	   actions (win32 only)
  1253         "
  1274 	"
  1254         (id := p id) ~~ 0 ifTrue:[
  1275 	(id := p id) ~~ 0 ifTrue:[
  1255             id notNil ifTrue:[
  1276 	    id notNil ifTrue:[
  1256                 'Processor [warning]: problem with process ' errorPrint. 
  1277 		'Processor [warning]: problem with process ' errorPrint. 
  1257                 id errorPrint. 
  1278 		id errorPrint. 
  1258                 (nm := p name) notNil ifTrue:[
  1279 		(nm := p name) notNil ifTrue:[
  1259                     ' (' errorPrint. nm errorPrint. ')' errorPrint.
  1280 		    ' (' errorPrint. nm errorPrint. ')' errorPrint.
  1260                 ].
  1281 		].
  1261 
  1282 
  1262 		ok == #halted ifTrue:[
  1283 		ok == #halted ifTrue:[
  1263 		    "/ that process was halted (win32 only)
  1284 		    "/ that process was halted (win32 only)
  1264 		    p state:#halted.
  1285 		    p state:#halted.
  1265                    '; stopped it.' errorPrintCR.
  1286 		   '; stopped it.' errorPrintCR.
  1266                    self suspend:p.
  1287 		   self suspend:p.
  1267 		] ifFalse:[
  1288 		] ifFalse:[
  1268                    '; hard-terminate it.' errorPrintCR.
  1289 		   '; hard-terminate it.' errorPrintCR.
  1269                    'Processor [info]: cleanup may take a while if stack is huge' infoPrintCR.
  1290 		   'Processor [info]: cleanup may take a while if stack is huge' infoPrintCR.
  1270                    p state:#cleanup.
  1291 		   p state:#cleanup.
  1271                    self terminateNoSignal:p.
  1292 		   self terminateNoSignal:p.
  1272 		]
  1293 		]
  1273             ]
  1294 	    ]
  1274         ]
  1295 	]
  1275     ].
  1296     ].
  1276     zombie notNil ifTrue:[
  1297     zombie notNil ifTrue:[
  1277         self class threadDestroy:zombie.
  1298 	self class threadDestroy:zombie.
  1278         zombie := nil
  1299 	zombie := nil
  1279     ].
  1300     ].
  1280     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1301     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1281 ! !
  1302 ! !
  1282 
  1303 
  1283 !ProcessorScheduler methodsFor:'priority constants'!
  1304 !ProcessorScheduler methodsFor:'priority constants'!
  1591     "
  1612     "
  1592      check for valid argument
  1613      check for valid argument
  1593     "
  1614     "
  1594     newPrio := prio.
  1615     newPrio := prio.
  1595     newPrio < 1 ifTrue:[
  1616     newPrio < 1 ifTrue:[
  1596         newPrio := 1.
  1617 	newPrio := 1.
  1597     ] ifFalse:[
  1618     ] ifFalse:[
  1598         newPrio > HighestPriority ifTrue:[
  1619 	newPrio > HighestPriority ifTrue:[
  1599             newPrio := HighestPriority
  1620 	    newPrio := HighestPriority
  1600         ]
  1621 	]
  1601     ].
  1622     ].
  1602 
  1623 
  1603     [
  1624     [
  1604         wasBlocked := OperatingSystem blockInterrupts.
  1625 	wasBlocked := OperatingSystem blockInterrupts.
  1605 
  1626 
  1606         aProcess setPriority:newPrio.
  1627 	aProcess setPriority:newPrio.
  1607 
  1628 
  1608         oldList := quiescentProcessLists at:oldPrio.
  1629 	oldList := quiescentProcessLists at:oldPrio.
  1609         oldList notNil ifTrue:[
  1630 	oldList notNil ifTrue:[
  1610             (oldList remove:aProcess ifAbsent:nil) notNil ifTrue:[
  1631 	    (oldList remove:aProcess ifAbsent:nil) notNil ifTrue:[
  1611                 newList := quiescentProcessLists at:newPrio.
  1632 		newList := quiescentProcessLists at:newPrio.
  1612                 newList isNil ifTrue:[
  1633 		newList isNil ifTrue:[
  1613                     quiescentProcessLists at:newPrio put:(newList := LinkedList new).
  1634 		    quiescentProcessLists at:newPrio put:(newList := LinkedList new).
  1614                 ].
  1635 		].
  1615                 newList addLast:aProcess.
  1636 		newList addLast:aProcess.
  1616 
  1637 
  1617                 "if its the current process lowering its prio 
  1638 		"if its the current process lowering its prio 
  1618                  or another one raising, we have to reschedule"
  1639 		 or another one raising, we have to reschedule"
  1619 
  1640 
  1620                 aProcess == activeProcess ifTrue:[
  1641 		aProcess == activeProcess ifTrue:[
  1621                     currentPriority := newPrio.
  1642 		    currentPriority := newPrio.
  1622                     newPrio < oldPrio ifTrue:[
  1643 		    newPrio < oldPrio ifTrue:[
  1623                         self threadSwitch:scheduler.    
  1644 			self threadSwitch:scheduler.    
  1624                     ]
  1645 		    ]
  1625                 ] ifFalse:[
  1646 		] ifFalse:[
  1626                     newPrio > currentPriority ifTrue:[
  1647 		    newPrio > currentPriority ifTrue:[
  1627                         self threadSwitch:aProcess.
  1648 			self threadSwitch:aProcess.
  1628                     ]
  1649 		    ]
  1629                 ].
  1650 		].
  1630             ]
  1651 	    ]
  1631         ]
  1652 	]
  1632     ] valueNowOrOnUnwindDo:[
  1653     ] valueNowOrOnUnwindDo:[
  1633         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1654 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1634     ]
  1655     ]
  1635 
  1656 
  1636     "Modified: / 4.8.1998 / 00:08:54 / cg"
  1657     "Modified: / 4.8.1998 / 00:08:54 / cg"
  1637 !
  1658 !
  1638 
  1659 
  1673     "ignore, if process is already dead"
  1694     "ignore, if process is already dead"
  1674     (aProcess isNil or:[aProcess id isNil]) ifTrue:[^ self].
  1695     (aProcess isNil or:[aProcess id isNil]) ifTrue:[^ self].
  1675 
  1696 
  1676 
  1697 
  1677     aProcess == activeProcess ifTrue:[
  1698     aProcess == activeProcess ifTrue:[
  1678         "special handling for waiting schedulers"
  1699 	"special handling for waiting schedulers"
  1679         aProcess == scheduler ifTrue:[
  1700 	aProcess == scheduler ifTrue:[
  1680             suspendScheduler := false.
  1701 	    suspendScheduler := false.
  1681         ].
  1702 	].
  1682         ^ self
  1703 	^ self
  1683     ].
  1704     ].
  1684 
  1705 
  1685     wasBlocked := OperatingSystem blockInterrupts.
  1706     wasBlocked := OperatingSystem blockInterrupts.
  1686 
  1707 
  1687     pri := aProcess priority.
  1708     pri := aProcess priority.
  1688 
  1709 
  1689     l := quiescentProcessLists at:pri.
  1710     l := quiescentProcessLists at:pri.
  1690     "if already running, ignore"
  1711     "if already running, ignore"
  1691     l notNil ifTrue:[
  1712     l notNil ifTrue:[
  1692         (l identityIndexOf:aProcess) ~~ 0 ifTrue:[
  1713 	(l identityIndexOf:aProcess) ~~ 0 ifTrue:[
  1693             wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1714 	    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1694             ^ self
  1715 	    ^ self
  1695         ]
  1716 	]
  1696     ] ifFalse:[
  1717     ] ifFalse:[
  1697         l := LinkedList new.
  1718 	l := LinkedList new.
  1698         quiescentProcessLists at:pri put:l.
  1719 	quiescentProcessLists at:pri put:l.
  1699     ].
  1720     ].
  1700     l addLast:aProcess.
  1721     l addLast:aProcess.
  1701     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1722     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1702 
  1723 
  1703     aProcess state:#run
  1724     aProcess state:#run
  1733 
  1754 
  1734     "ignore, if process is already dead"
  1755     "ignore, if process is already dead"
  1735     (aProcess isNil or:[aProcess id isNil]) ifTrue:[^ self].
  1756     (aProcess isNil or:[aProcess id isNil]) ifTrue:[^ self].
  1736 
  1757 
  1737     (s := aProcess state) == #osWait ifTrue:[
  1758     (s := aProcess state) == #osWait ifTrue:[
  1738         'Processor [warning]: bad resume: #osWait' errorPrintCR.
  1759 	'Processor [warning]: bad resume: #osWait' errorPrintCR.
  1739         "/ MiniDebugger enterWithMessage:'bad resume: state osWait'.
  1760 	"/ MiniDebugger enterWithMessage:'bad resume: state osWait'.
  1740         ^ self.
  1761 	^ self.
  1741     ].
  1762     ].
  1742     s == #stopped ifTrue:[
  1763     s == #stopped ifTrue:[
  1743         'Processor [warning]: bad resume: #stopped' errorPrintCR.
  1764 	'Processor [warning]: bad resume: #stopped' errorPrintCR.
  1744         ^ self.
  1765 	^ self.
  1745     ].
  1766     ].
  1746 
  1767 
  1747     aProcess == activeProcess ifTrue:[
  1768     aProcess == activeProcess ifTrue:[
  1748         "special handling for waiting schedulers"
  1769 	"special handling for waiting schedulers"
  1749         aProcess == scheduler ifTrue:[
  1770 	aProcess == scheduler ifTrue:[
  1750             suspendScheduler := false.
  1771 	    suspendScheduler := false.
  1751         ].
  1772 	].
  1752         ^ self
  1773 	^ self
  1753     ].
  1774     ].
  1754 
  1775 
  1755     wasBlocked := OperatingSystem blockInterrupts.
  1776     wasBlocked := OperatingSystem blockInterrupts.
  1756 
  1777 
  1757     pri := aProcess priority.
  1778     pri := aProcess priority.
  1758 
  1779 
  1759     l := quiescentProcessLists at:pri.
  1780     l := quiescentProcessLists at:pri.
  1760     "if already running, ignore"
  1781     "if already running, ignore"
  1761     l notNil ifTrue:[
  1782     l notNil ifTrue:[
  1762         (l identityIndexOf:aProcess) ~~ 0 ifTrue:[
  1783 	(l identityIndexOf:aProcess) ~~ 0 ifTrue:[
  1763             wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1784 	    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1764             ^ self
  1785 	    ^ self
  1765         ]
  1786 	]
  1766     ] ifFalse:[
  1787     ] ifFalse:[
  1767         l := LinkedList new.
  1788 	l := LinkedList new.
  1768         quiescentProcessLists at:pri put:l.
  1789 	quiescentProcessLists at:pri put:l.
  1769     ].
  1790     ].
  1770     l addLast:aProcess.
  1791     l addLast:aProcess.
  1771     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1792     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1772 
  1793 
  1773     (pri > currentPriority) ifTrue:[
  1794     (pri > currentPriority) ifTrue:[
  1774         "
  1795 	"
  1775          its prio is higher; immediately transfer control to it
  1796 	 its prio is higher; immediately transfer control to it
  1776         "
  1797 	"
  1777         self threadSwitch:aProcess
  1798 	self threadSwitch:aProcess
  1778     ] ifFalse:[
  1799     ] ifFalse:[
  1779         "
  1800 	"
  1780          its prio is lower; it will have to wait for a while ...
  1801 	 its prio is lower; it will have to wait for a while ...
  1781         "
  1802 	"
  1782         aProcess state:#run 
  1803 	aProcess state:#run 
  1783     ]
  1804     ]
  1784 
  1805 
  1785     "Modified: / 24.8.1998 / 18:28:42 / cg"
  1806     "Modified: / 24.8.1998 / 18:28:42 / cg"
  1786 !
  1807 !
  1787 
  1808 
  1799 suspend:aProcess
  1820 suspend:aProcess
  1800     "remove the argument, aProcess from the list of runnable processes.
  1821     "remove the argument, aProcess from the list of runnable processes.
  1801      If the process is the current one, reschedule.
  1822      If the process is the current one, reschedule.
  1802 
  1823 
  1803      Notice:
  1824      Notice:
  1804          This method should only be called by Process>>suspend or
  1825 	 This method should only be called by Process>>suspend or
  1805          Process>>suspendWithState:"
  1826 	 Process>>suspendWithState:"
  1806 
  1827 
  1807     |pri l p wasBlocked|
  1828     |pri l p wasBlocked|
  1808 
  1829 
  1809     "
  1830     "
  1810      some debugging stuff
  1831      some debugging stuff
  1811     "
  1832     "
  1812     aProcess isNil ifTrue:[
  1833     aProcess isNil ifTrue:[
  1813         InvalidProcessSignal raiseWith:aProcess errorString:'PROCESSOR: nil suspend'.
  1834 	InvalidProcessSignal raiseWith:aProcess errorString:'PROCESSOR: nil suspend'.
  1814         ^ self
  1835 	^ self
  1815     ].
  1836     ].
  1816     aProcess id isNil ifTrue:[
  1837     aProcess id isNil ifTrue:[
  1817         InvalidProcessSignal raiseWith:aProcess errorString:'PROCESSOR: bad suspend: already dead'.
  1838 	InvalidProcessSignal raiseWith:aProcess errorString:'PROCESSOR: bad suspend: already dead'.
  1818         self threadSwitch:scheduler.
  1839 	self threadSwitch:scheduler.
  1819         ^ self
  1840 	^ self
  1820     ].
  1841     ].
  1821     aProcess == scheduler ifTrue:[
  1842     aProcess == scheduler ifTrue:[
  1822         "only the scheduler may suspend itself"
  1843 	"only the scheduler may suspend itself"
  1823         activeProcess == scheduler ifTrue:[
  1844 	activeProcess == scheduler ifTrue:[
  1824             suspendScheduler := true.
  1845 	    suspendScheduler := true.
  1825             [suspendScheduler] whileTrue:[
  1846 	    [suspendScheduler] whileTrue:[
  1826                 self dispatch.
  1847 		self dispatch.
  1827             ].
  1848 	    ].
  1828             ^ self
  1849 	    ^ self
  1829         ].
  1850 	].
  1830 
  1851 
  1831         InvalidProcessSignal raiseWith:aProcess errorString:'PROCESSOR: scheduler should never be suspended'.
  1852 	InvalidProcessSignal raiseWith:aProcess errorString:'PROCESSOR: scheduler should never be suspended'.
  1832         ^ self
  1853 	^ self
  1833     ].
  1854     ].
  1834 
  1855 
  1835     wasBlocked := OperatingSystem blockInterrupts.
  1856     wasBlocked := OperatingSystem blockInterrupts.
  1836 
  1857 
  1837     pri := aProcess priority.
  1858     pri := aProcess priority.
  1839 
  1860 
  1840     "notice: this is slightly faster than putting the if-code into
  1861     "notice: this is slightly faster than putting the if-code into
  1841      the ifAbsent block, because [] is a shared cheap block, created at compile time
  1862      the ifAbsent block, because [] is a shared cheap block, created at compile time
  1842     "
  1863     "
  1843     (l isNil or:[(l remove:aProcess ifAbsent:nil) isNil]) ifTrue:[
  1864     (l isNil or:[(l remove:aProcess ifAbsent:nil) isNil]) ifTrue:[
  1844         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1865 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1845         'Processor [warning]: bad suspend: not on run list' errorPrintCR.
  1866 	'Processor [warning]: bad suspend: not on run list' errorPrintCR.
  1846         "/ MiniDebugger enterWithMessage:'bad suspend: not on run list'.
  1867 	"/ MiniDebugger enterWithMessage:'bad suspend: not on run list'.
  1847         aProcess == activeProcess ifTrue:[
  1868 	aProcess == activeProcess ifTrue:[
  1848             self threadSwitch:scheduler.
  1869 	    self threadSwitch:scheduler.
  1849         ].
  1870 	].
  1850         ^ self
  1871 	^ self
  1851     ].
  1872     ].
  1852 
  1873 
  1853     (aProcess == activeProcess) ifTrue:[
  1874     (aProcess == activeProcess) ifTrue:[
  1854         "we can immediately switch sometimes"
  1875 	"we can immediately switch sometimes"
  1855         l isEmpty ifFalse:[
  1876 	l isEmpty ifFalse:[
  1856             p := l first
  1877 	    p := l first
  1857         ] ifTrue:[
  1878 	] ifTrue:[
  1858             p := scheduler
  1879 	    p := scheduler
  1859         ].
  1880 	].
  1860         self threadSwitch:p 
  1881 	self threadSwitch:p 
  1861     ].
  1882     ].
  1862 
  1883 
  1863     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1884     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1864 
  1885 
  1865     "Modified: / 23.9.1996 / 13:49:24 / stefan"
  1886     "Modified: / 23.9.1996 / 13:49:24 / stefan"
  2001     "recompute dynamic priorities."
  2022     "recompute dynamic priorities."
  2002 
  2023 
  2003     |processesDecreased processesToIncrease|
  2024     |processesDecreased processesToIncrease|
  2004 
  2025 
  2005     scheduledProcesses notNil ifTrue:[
  2026     scheduledProcesses notNil ifTrue:[
  2006         "/ this is written a bit cryptic - to avoid creation
  2027 	"/ this is written a bit cryptic - to avoid creation
  2007         "/ of garbage objects (Id'sets) if possible.
  2028 	"/ of garbage objects (Id'sets) if possible.
  2008         "/ since this runs 50 times a second and most of the
  2029 	"/ since this runs 50 times a second and most of the
  2009         "/ time, no rescheduling is req'd
  2030 	"/ time, no rescheduling is req'd
  2010 
  2031 
  2011         scheduledProcesses do:[:aProcess |
  2032 	scheduledProcesses do:[:aProcess |
  2012             |range prio|
  2033 	    |range prio|
  2013 
  2034 
  2014             "/ decrease priority of processes that did run
  2035 	    "/ decrease priority of processes that did run
  2015             (range := aProcess priorityRange) notNil ifTrue:[
  2036 	    (range := aProcess priorityRange) notNil ifTrue:[
  2016                 aProcess priority > range start ifTrue:[
  2037 		aProcess priority > range start ifTrue:[
  2017                     processesDecreased isNil ifTrue:[
  2038 		    processesDecreased isNil ifTrue:[
  2018                         processesDecreased := IdentitySet new.
  2039 			processesDecreased := IdentitySet new.
  2019                     ].
  2040 		    ].
  2020                     processesDecreased add:aProcess.
  2041 		    processesDecreased add:aProcess.
  2021                 ]
  2042 		]
  2022             ]
  2043 	    ]
  2023         ].
  2044 	].
  2024 
  2045 
  2025         processesDecreased notNil ifTrue:[
  2046 	processesDecreased notNil ifTrue:[
  2026             processesDecreased do:[:aProcess |
  2047 	    processesDecreased do:[:aProcess |
  2027                 |newPri|
  2048 		|newPri|
  2028 
  2049 
  2029                 "/ newPri := aProcess priority - 1.
  2050 		"/ newPri := aProcess priority - 1.
  2030                 newPri := aProcess priorityRange start.
  2051 		newPri := aProcess priorityRange start.
  2031                 self changePriority:newPri for:aProcess.
  2052 		self changePriority:newPri for:aProcess.
  2032             ].
  2053 	    ].
  2033         ].
  2054 	].
  2034 
  2055 
  2035         "/ and increase all prios of those that did not run, but are runnable
  2056 	"/ and increase all prios of those that did not run, but are runnable
  2036 
  2057 
  2037         TimeSlicingPriorityLimit to:1 by:-1 do:[:i |
  2058 	TimeSlicingPriorityLimit to:1 by:-1 do:[:i |
  2038             |list|
  2059 	    |list|
  2039 
  2060 
  2040             (list := quiescentProcessLists at:i) size > 0 ifTrue:[
  2061 	    (list := quiescentProcessLists at:i) size > 0 ifTrue:[
  2041                 list do:[:aProcess |
  2062 		list do:[:aProcess |
  2042                     |range prio|
  2063 		    |range prio|
  2043 
  2064 
  2044                     (range := aProcess priorityRange) notNil ifTrue:[
  2065 		    (range := aProcess priorityRange) notNil ifTrue:[
  2045                         (processesDecreased isNil
  2066 			(processesDecreased isNil
  2046                         or:[(processesDecreased includes:aProcess) not]) ifTrue:[
  2067 			or:[(processesDecreased includes:aProcess) not]) ifTrue:[
  2047                             aProcess priority < range stop ifTrue:[
  2068 			    aProcess priority < range stop ifTrue:[
  2048                                 processesToIncrease isNil ifTrue:[
  2069 				processesToIncrease isNil ifTrue:[
  2049                                     processesToIncrease := IdentitySet new.
  2070 				    processesToIncrease := IdentitySet new.
  2050                                 ].
  2071 				].
  2051                                 processesToIncrease add:aProcess
  2072 				processesToIncrease add:aProcess
  2052                             ]
  2073 			    ]
  2053                         ]
  2074 			]
  2054                     ]
  2075 		    ]
  2055                 ]
  2076 		]
  2056             ]
  2077 	    ]
  2057         ].
  2078 	].
  2058         processesToIncrease notNil ifTrue:[
  2079 	processesToIncrease notNil ifTrue:[
  2059             processesToIncrease do:[:aProcess |
  2080 	    processesToIncrease do:[:aProcess |
  2060                 self changePriority:(aProcess priority + 1) for:aProcess.
  2081 		self changePriority:(aProcess priority + 1) for:aProcess.
  2061             ].
  2082 	    ].
  2062         ].
  2083 	].
  2063     ].
  2084     ].
  2064 
  2085 
  2065     "Modified: / 21.9.1998 / 09:07:54 / cg"
  2086     "Modified: / 21.9.1998 / 09:07:54 / cg"
  2066 !
  2087 !
  2067 
  2088 
  2085     wasBlocked := OperatingSystem blockInterrupts.
  2106     wasBlocked := OperatingSystem blockInterrupts.
  2086 
  2107 
  2087     i := TimeSlicingPriorityLimit.
  2108     i := TimeSlicingPriorityLimit.
  2088     [(i > 0) and:[(list := quiescentProcessLists at:i) size <= 1]] whileTrue: [i := i - 1].
  2109     [(i > 0) and:[(list := quiescentProcessLists at:i) size <= 1]] whileTrue: [i := i - 1].
  2089     i ~~ 0 ifTrue: [
  2110     i ~~ 0 ifTrue: [
  2090         "/ shuffle that list
  2111 	"/ shuffle that list
  2091         list addLast:(list removeFirst).
  2112 	list addLast:(list removeFirst).
  2092     ].
  2113     ].
  2093     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2114     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2094 
  2115 
  2095     "Modified: / 4.8.1998 / 00:13:32 / cg"
  2116     "Modified: / 4.8.1998 / 00:13:32 / cg"
  2096 !
  2117 !
  2099     "start preemptive scheduling (timeSlicing)"
  2120     "start preemptive scheduling (timeSlicing)"
  2100 
  2121 
  2101     timeSliceProcess notNil ifTrue: [^ self].
  2122     timeSliceProcess notNil ifTrue: [^ self].
  2102 
  2123 
  2103     timeSliceProcess := [
  2124     timeSliceProcess := [
  2104         [
  2125 	[
  2105             |myDelay t flipFlop|
  2126 	    |myDelay t flipFlop|
  2106 
  2127 
  2107             myDelay := Delay forMilliseconds:(t := TimeSliceInterval).
  2128 	    myDelay := Delay forMilliseconds:(t := TimeSliceInterval).
  2108             flipFlop := true.
  2129 	    flipFlop := true.
  2109 
  2130 
  2110             [true] whileTrue: [
  2131 	    [true] whileTrue: [
  2111                 t ~~ TimeSliceInterval ifTrue:[
  2132 		t ~~ TimeSliceInterval ifTrue:[
  2112                     "/ interval changed -> need a new delay
  2133 		    "/ interval changed -> need a new delay
  2113                     myDelay delay:(t := TimeSliceInterval).
  2134 		    myDelay delay:(t := TimeSliceInterval).
  2114                 ].
  2135 		].
  2115                 myDelay wait.
  2136 		myDelay wait.
  2116                 self slice.
  2137 		self slice.
  2117 
  2138 
  2118                 "/ every other tick, recompute priorities.
  2139 		"/ every other tick, recompute priorities.
  2119                 flipFlop := flipFlop not.
  2140 		flipFlop := flipFlop not.
  2120                 flipFlop ifTrue:[
  2141 		flipFlop ifTrue:[
  2121                     scheduledProcesses isNil ifTrue:[
  2142 		    scheduledProcesses isNil ifTrue:[
  2122                         scheduledProcesses := IdentitySet new.
  2143 			scheduledProcesses := IdentitySet new.
  2123                     ] ifFalse:[
  2144 		    ] ifFalse:[
  2124                         supportDynamicPriorities == true ifTrue:[
  2145 			supportDynamicPriorities == true ifTrue:[
  2125                             self recomputeDynamicPriorities.
  2146 			    self recomputeDynamicPriorities.
  2126                         ].
  2147 			].
  2127                         scheduledProcesses removeAll.
  2148 			scheduledProcesses removeAll.
  2128                     ].
  2149 		    ].
  2129 
  2150 
  2130                 ].
  2151 		].
  2131             ]
  2152 	    ]
  2132         ] valueOnUnwindDo:[
  2153 	] valueOnUnwindDo:[
  2133             timeSliceProcess := nil
  2154 	    timeSliceProcess := nil
  2134         ]
  2155 	]
  2135     ] newProcess.
  2156     ] newProcess.
  2136     timeSliceProcess priority:HighestPriority.
  2157     timeSliceProcess priority:HighestPriority.
  2137     timeSliceProcess name:'time slicer'.
  2158     timeSliceProcess name:'time slicer'.
  2138     timeSliceProcess restartable:true.
  2159     timeSliceProcess restartable:true.
  2139     timeSliceProcess beSystemProcess.
  2160     timeSliceProcess beSystemProcess.
  2150 
  2171 
  2151 stopTimeSlicing
  2172 stopTimeSlicing
  2152     "stop preemptive scheduling (timeSlicing)"
  2173     "stop preemptive scheduling (timeSlicing)"
  2153 
  2174 
  2154     timeSliceProcess notNil ifTrue: [
  2175     timeSliceProcess notNil ifTrue: [
  2155         timeSliceProcess terminate.
  2176 	timeSliceProcess terminate.
  2156         timeSliceProcess := nil.
  2177 	timeSliceProcess := nil.
  2157         scheduledProcesses := nil
  2178 	scheduledProcesses := nil
  2158     ]
  2179     ]
  2159 
  2180 
  2160     "
  2181     "
  2161      Processor stopTimeSlicing
  2182      Processor stopTimeSlicing
  2162     "
  2183     "
  2196      wasBlocked fd|
  2217      wasBlocked fd|
  2197 
  2218 
  2198     wasBlocked := OperatingSystem blockInterrupts.
  2219     wasBlocked := OperatingSystem blockInterrupts.
  2199     idx := readSemaphoreArray identityIndexOf:aSemaphore startingAt:1.
  2220     idx := readSemaphoreArray identityIndexOf:aSemaphore startingAt:1.
  2200     [idx ~~ 0] whileTrue:[
  2221     [idx ~~ 0] whileTrue:[
  2201         useIOInterrupts ifTrue:[
  2222 	useIOInterrupts ifTrue:[
  2202             fd := readFdArray at:idx.
  2223 	    fd := readFdArray at:idx.
  2203             fd notNil ifTrue:[
  2224 	    fd notNil ifTrue:[
  2204                 OperatingSystem disableIOInterruptsOn:fd
  2225 		OperatingSystem disableIOInterruptsOn:fd
  2205             ].
  2226 	    ].
  2206         ].
  2227 	].
  2207         readFdArray at:idx put:nil.
  2228 	readFdArray at:idx put:nil.
  2208         readSemaphoreArray at:idx put:nil.
  2229 	readSemaphoreArray at:idx put:nil.
  2209         readCheckArray at:idx put:nil.
  2230 	readCheckArray at:idx put:nil.
  2210         idx := readSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2231 	idx := readSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2211     ].
  2232     ].
  2212     idx := writeSemaphoreArray identityIndexOf:aSemaphore startingAt:1.
  2233     idx := writeSemaphoreArray identityIndexOf:aSemaphore startingAt:1.
  2213     [idx ~~ 0] whileTrue:[
  2234     [idx ~~ 0] whileTrue:[
  2214         useIOInterrupts ifTrue:[
  2235 	useIOInterrupts ifTrue:[
  2215             fd := writeFdArray at:idx.
  2236 	    fd := writeFdArray at:idx.
  2216             fd notNil ifTrue:[
  2237 	    fd notNil ifTrue:[
  2217                 OperatingSystem disableIOInterruptsOn:fd
  2238 		OperatingSystem disableIOInterruptsOn:fd
  2218             ].
  2239 	    ].
  2219         ].
  2240 	].
  2220         writeFdArray at:idx put:nil.
  2241 	writeFdArray at:idx put:nil.
  2221         writeSemaphoreArray at:idx put:nil.
  2242 	writeSemaphoreArray at:idx put:nil.
  2222         idx := writeSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2243 	writeCheckArray at:idx put:nil.
       
  2244 	idx := writeSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2223     ].
  2245     ].
  2224     idx := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:1.
  2246     idx := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:1.
  2225     [idx ~~ 0] whileTrue:[
  2247     [idx ~~ 0] whileTrue:[
  2226         timeoutArray at:idx put:nil.
  2248 	timeoutArray at:idx put:nil.
  2227         timeoutSemaphoreArray at:idx put:nil.
  2249 	timeoutSemaphoreArray at:idx put:nil.
  2228         timeoutActionArray at:idx put:nil.
  2250 	timeoutActionArray at:idx put:nil.
  2229         timeoutProcessArray at:idx put:nil.
  2251 	timeoutProcessArray at:idx put:nil.
  2230         idx := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2252 	idx := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2231     ].
  2253     ].
  2232     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2254     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2233 
  2255 
  2234     "Modified: 4.8.1997 / 15:19:33 / cg"
  2256     "Modified: 4.8.1997 / 15:19:33 / cg"
  2235 !
  2257 !
  2305      arrives. This will only happen, if the OS supports selecting on fileDescriptors."
  2327      arrives. This will only happen, if the OS supports selecting on fileDescriptors."
  2306 
  2328 
  2307     self signal:aSemaphore onInput:aFileDescriptor orCheck:nil
  2329     self signal:aSemaphore onInput:aFileDescriptor orCheck:nil
  2308 !
  2330 !
  2309 
  2331 
       
  2332 signal:aSemaphore onInputStream:aStream
       
  2333     "arrange for a semaphore to be triggered when input on aStream arrives. 
       
  2334      This will do a select, if the OS supports selecting on that filedescriptor,
       
  2335      otherwise, it will be polled every few milliseconds (MSDOS)."
       
  2336 
       
  2337     aStream canBeSelected ifTrue:[
       
  2338 	"/ can this stream be selected on ?
       
  2339 	self signal:aSemaphore onInput:aStream aFileDescriptor orCheck:nil
       
  2340     ] ifFalse:[
       
  2341 	"/ nope - must poll ...
       
  2342 	self signal:aSemaphore onInput:nil orCheck:[aStream canReadWithoutBlocking]
       
  2343     ]
       
  2344 !
       
  2345 
  2310 signal:aSemaphore onInput:aFileDescriptor orCheck:aBlock
  2346 signal:aSemaphore onInput:aFileDescriptor orCheck:aBlock
  2311     "arrange for a semaphore to be triggered when input on aFileDescriptor
  2347     "arrange for a semaphore to be triggered when input on aFileDescriptor
  2312      arrives OR checkblock evaluates to true. The checkBlock will be evaluated
  2348      arrives OR checkblock evaluates to true. 
  2313      by the scheduler from time to time (i.e. every few milliseconds).
  2349      The checkBlock will be evaluated by the scheduler from time to time 
       
  2350      (i.e. every few milliseconds).
  2314      (This is req'd for buffered input, where a select may not detect 
  2351      (This is req'd for buffered input, where a select may not detect 
  2315       data which has already been read into a buffer - as in Xlib.
  2352       data which has already been read into a buffer - as in Xlib.
  2316       Or on systems, where we cannot select on a displays eventQ, such as windows)"
  2353       Or on systems, where we cannot select on a displays eventQ, such as windows)"
  2317 
  2354 
  2318     |idx "{ Class: SmallInteger }"
  2355     |idx "{ Class: SmallInteger }"
  2321     fd := aFileDescriptor.
  2358     fd := aFileDescriptor.
  2322 
  2359 
  2323     wasBlocked := OperatingSystem blockInterrupts.
  2360     wasBlocked := OperatingSystem blockInterrupts.
  2324 
  2361 
  2325     fd isNil ifTrue:[
  2362     fd isNil ifTrue:[
  2326 	'Processor [info]: no fd to select on - polling with checkBlock' infoPrintCR.
       
  2327 	(readCheckArray identityIndexOf:aBlock startingAt:1) == 0 ifTrue:[
  2363 	(readCheckArray identityIndexOf:aBlock startingAt:1) == 0 ifTrue:[
  2328 	    readFdArray := readFdArray copyWith:nil.
  2364 	    idx := readFdArray identityIndexOf:nil startingAt:1.
  2329 	    readSemaphoreArray := readSemaphoreArray copyWith:aSemaphore.
  2365 	    idx ~~ 0 ifTrue:[
  2330 	    readCheckArray := readCheckArray copyWith:aBlock.
  2366 		readFdArray at:idx put:aFileDescriptor.
       
  2367 		readSemaphoreArray at:idx put:aSemaphore.
       
  2368 		readCheckArray at:idx put:aBlock
       
  2369 	    ] ifFalse:[
       
  2370 		readFdArray := readFdArray copyWith:nil.
       
  2371 		readSemaphoreArray := readSemaphoreArray copyWith:aSemaphore.
       
  2372 		readCheckArray := readCheckArray copyWith:aBlock.
       
  2373 	    ]
  2331 	]
  2374 	]
  2332     ] ifFalse:[
  2375     ] ifFalse:[
  2333         (readFdArray identityIndexOf:aFileDescriptor startingAt:1) == 0 ifTrue:[
  2376 	(readFdArray identityIndexOf:aFileDescriptor startingAt:1) == 0 ifTrue:[
  2334             idx := readFdArray identityIndexOf:nil startingAt:1.
  2377 	    idx := readFdArray identityIndexOf:nil startingAt:1.
  2335             idx ~~ 0 ifTrue:[
  2378 	    idx ~~ 0 ifTrue:[
  2336                 readFdArray at:idx put:aFileDescriptor.
  2379 		readFdArray at:idx put:aFileDescriptor.
  2337                 readSemaphoreArray at:idx put:aSemaphore.
  2380 		readSemaphoreArray at:idx put:aSemaphore.
  2338                 readCheckArray at:idx put:aBlock
  2381 		readCheckArray at:idx put:aBlock
  2339             ] ifFalse:[
  2382 	    ] ifFalse:[
  2340                 readFdArray := readFdArray copyWith:aFileDescriptor.
  2383 		readFdArray := readFdArray copyWith:aFileDescriptor.
  2341                 readSemaphoreArray := readSemaphoreArray copyWith:aSemaphore.
  2384 		readSemaphoreArray := readSemaphoreArray copyWith:aSemaphore.
  2342                 readCheckArray := readCheckArray copyWith:aBlock.
  2385 		readCheckArray := readCheckArray copyWith:aBlock.
  2343             ].
  2386 	    ].
  2344             useIOInterrupts ifTrue:[
  2387 	    useIOInterrupts ifTrue:[
  2345                 OperatingSystem enableIOInterruptsOn:aFileDescriptor
  2388 		OperatingSystem enableIOInterruptsOn:aFileDescriptor
  2346             ].
  2389 	    ].
  2347 	]
  2390 	]
  2348     ].
  2391     ].
  2349     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2392     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2350 
  2393 
  2351     "Modified: 4.8.1997 / 15:20:45 / cg"
  2394     "Modified: 4.8.1997 / 15:20:45 / cg"
  2352 !
  2395 !
  2353 
  2396 
  2354 signal:aSemaphore onOutput:aFileDescriptor
  2397 signal:aSemaphore onOutputStream:aStream
       
  2398     "arrange for a semaphore to be triggered when output on aStream is possible. 
       
  2399      This will do a select, if the OS supports selecting on that filedescriptor,
       
  2400      otherwise, it will be polled every few milliseconds (MSDOS)."
       
  2401 
       
  2402     aStream canBeSelected ifTrue:[
       
  2403 	"/ can this stream be selected on ?
       
  2404 	self signal:aSemaphore onOutput:aStream aFileDescriptor orCheck:nil
       
  2405     ] ifFalse:[
       
  2406 	"/ nope - must poll ...
       
  2407 	self signal:aSemaphore onOutput:nil orCheck:[aStream canWriteWithoutBlocking]
       
  2408     ]
       
  2409 !
       
  2410 
       
  2411 signal:aSemaphore onOutput:aFileDescriptor orCheck:aBlock
  2355     "arrange for a semaphore to be triggered when output on aFileDescriptor
  2412     "arrange for a semaphore to be triggered when output on aFileDescriptor
  2356      is possible. (i.e. can be written without blocking).
  2413      is possible (i.e. can be written without blocking) or aBlock returns true.
  2357      This will only happen, if the OS supports selecting on fileDescriptors."
  2414      The checkBlock will be evaluated by the scheduler from time to time 
       
  2415      (i.e. every few milliseconds).
       
  2416      This checkBlock is required for poor windows, where a WaitForObject does
       
  2417      not know abóut sockets."
  2358 
  2418 
  2359     |idx "{ Class: SmallInteger }"
  2419     |idx "{ Class: SmallInteger }"
  2360      wasBlocked|
  2420      wasBlocked|
  2361 
  2421 
  2362     wasBlocked := OperatingSystem blockInterrupts.
  2422     wasBlocked := OperatingSystem blockInterrupts.
  2363     (writeFdArray identityIndexOf:aFileDescriptor startingAt:1) == 0 ifTrue:[
  2423 
  2364         idx := writeFdArray identityIndexOf:nil startingAt:1.
  2424     aFileDescriptor isNil ifTrue:[
  2365         idx ~~ 0 ifTrue:[
  2425 	(writeCheckArray identityIndexOf:aBlock startingAt:1) == 0 ifTrue:[
  2366             writeFdArray at:idx put:aFileDescriptor.
  2426 	    idx := writeFdArray identityIndexOf:nil startingAt:1.
  2367             writeSemaphoreArray at:idx put:aSemaphore.
  2427 	    idx ~~ 0 ifTrue:[
  2368         ] ifFalse:[
  2428 		writeFdArray at:idx put:aFileDescriptor.
  2369             writeFdArray := writeFdArray copyWith:aFileDescriptor.
  2429 		writeSemaphoreArray at:idx put:aSemaphore.
  2370             writeSemaphoreArray := writeSemaphoreArray copyWith:aSemaphore.
  2430 		writeCheckArray at:idx put:aBlock
  2371         ].
  2431 	    ] ifFalse:[
  2372         useIOInterrupts ifTrue:[
  2432 		writeFdArray := writeFdArray copyWith:nil.
  2373             OperatingSystem enableIOInterruptsOn:aFileDescriptor
  2433 		writeSemaphoreArray := writeSemaphoreArray copyWith:aSemaphore.
  2374         ].
  2434 		writeCheckArray := writeCheckArray copyWith:aBlock.
  2375 
  2435 	    ]
  2376     ].
  2436 	]
       
  2437     ] ifFalse:[
       
  2438 	(writeFdArray identityIndexOf:aFileDescriptor startingAt:1) == 0 ifTrue:[
       
  2439 	    idx := writeFdArray identityIndexOf:nil startingAt:1.
       
  2440 	    idx ~~ 0 ifTrue:[
       
  2441 		writeFdArray at:idx put:aFileDescriptor.
       
  2442 		writeSemaphoreArray at:idx put:aSemaphore.
       
  2443 		writeCheckArray at:idx put:aBlock
       
  2444 	    ] ifFalse:[
       
  2445 		writeFdArray := writeFdArray copyWith:aFileDescriptor.
       
  2446 		writeSemaphoreArray := writeSemaphoreArray copyWith:aSemaphore.
       
  2447 		writeCheckArray := writeCheckArray copyWith:aBlock.
       
  2448 	    ].
       
  2449 	    useIOInterrupts ifTrue:[
       
  2450 		OperatingSystem enableIOInterruptsOn:aFileDescriptor
       
  2451 	    ].
       
  2452 	]
       
  2453     ].
       
  2454 
  2377     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2455     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2378 
  2456 
  2379     "Modified: 4.8.1997 / 15:21:49 / cg"
  2457     "Modified: 4.8.1997 / 15:21:49 / cg"
  2380 ! !
  2458 ! !
  2381 
  2459 
  2388      If enabled, arrangements are made for data-availability to trigger an
  2466      If enabled, arrangements are made for data-availability to trigger an
  2389      interrupt.
  2467      interrupt.
  2390      Using IO interrupts reduces the idle CPU usage of ST/X by some percent
  2468      Using IO interrupts reduces the idle CPU usage of ST/X by some percent
  2391      (typically 2-7%).
  2469      (typically 2-7%).
  2392      Notice: 
  2470      Notice: 
  2393         some systems do not support IO-interrupts (or have a broken stdio-lib), 
  2471 	some systems do not support IO-interrupts (or have a broken stdio-lib), 
  2394         and this feature is always disabled;
  2472 	and this feature is always disabled;
  2395      Also notice:
  2473      Also notice:
  2396         we found that in some Xlib-implementations, interrupted reads are not
  2474 	we found that in some Xlib-implementations, interrupted reads are not
  2397         handled correctly (especially in multi-headed applications), and this
  2475 	handled correctly (especially in multi-headed applications), and this
  2398         fefature should be disabled to avoid a blocking XPending.
  2476 	fefature should be disabled to avoid a blocking XPending.
  2399 
  2477 
  2400      If this method is used to disable IO interrupts in multi-headed apps, 
  2478      If this method is used to disable IO interrupts in multi-headed apps, 
  2401      it should be invoked BEFORE the display event dispatcher processes are started."
  2479      it should be invoked BEFORE the display event dispatcher processes are started."
  2402 
  2480 
  2403     OperatingSystem supportsIOInterrupts ifTrue:[
  2481     OperatingSystem supportsIOInterrupts ifTrue:[
  2404         useIOInterrupts := aBoolean
  2482 	useIOInterrupts := aBoolean
  2405     ].
  2483     ].
  2406 
  2484 
  2407     "Created: / 15.7.1998 / 13:32:29 / cg"
  2485     "Created: / 15.7.1998 / 13:32:29 / cg"
  2408 ! !
  2486 ! !
  2409 
  2487 
  2608     now := OperatingSystem getMillisecondTime.
  2686     now := OperatingSystem getMillisecondTime.
  2609     blocksToEvaluate := nil.
  2687     blocksToEvaluate := nil.
  2610     n := timeoutArray size.
  2688     n := timeoutArray size.
  2611     anyTimeouts := false.
  2689     anyTimeouts := false.
  2612     1 to:n do:[:index |
  2690     1 to:n do:[:index |
  2613         aTime := timeoutArray at:index.
  2691 	aTime := timeoutArray at:index.
  2614         aTime notNil ifTrue:[
  2692 	aTime notNil ifTrue:[
  2615             (OperatingSystem millisecondTime:aTime isAfter:now) ifFalse:[
  2693 	    (OperatingSystem millisecondTime:aTime isAfter:now) ifFalse:[
  2616                 "this one should be triggered"
  2694 		"this one should be triggered"
  2617 
  2695 
  2618                 sema := timeoutSemaphoreArray at:index.
  2696 		sema := timeoutSemaphoreArray at:index.
  2619                 sema notNil ifTrue:[
  2697 		sema notNil ifTrue:[
  2620                     timeoutSemaphoreArray at:index put:nil.
  2698 		    timeoutSemaphoreArray at:index put:nil.
  2621                     sema signalOnce.
  2699 		    sema signalOnce.
  2622                 ] ifFalse:[
  2700 		] ifFalse:[
  2623                     "to support pure-events"
  2701 		    "to support pure-events"
  2624                     block := timeoutActionArray at:index.
  2702 		    block := timeoutActionArray at:index.
  2625                     block notNil ifTrue:[
  2703 		    block notNil ifTrue:[
  2626                         blocksToEvaluate isNil ifTrue:[
  2704 			blocksToEvaluate isNil ifTrue:[
  2627                             blocksToEvaluate := OrderedCollection new:10.
  2705 			    blocksToEvaluate := OrderedCollection new:10.
  2628                             processes := OrderedCollection new:10.
  2706 			    processes := OrderedCollection new:10.
  2629                         ].
  2707 			].
  2630                         blocksToEvaluate add:block.
  2708 			blocksToEvaluate add:block.
  2631                         processes add:(timeoutProcessArray at:index).
  2709 			processes add:(timeoutProcessArray at:index).
  2632                         timeoutActionArray at:index put:nil.
  2710 			timeoutActionArray at:index put:nil.
  2633                         timeoutProcessArray at:index put:nil.
  2711 			timeoutProcessArray at:index put:nil.
  2634                     ]
  2712 		    ]
  2635                 ].
  2713 		].
  2636                 timeoutArray at:index put:nil.
  2714 		timeoutArray at:index put:nil.
  2637             ] ifTrue:[
  2715 	    ] ifTrue:[
  2638                 anyTimeouts := true
  2716 		anyTimeouts := true
  2639             ]
  2717 	    ]
  2640         ]
  2718 	]
  2641     ].
  2719     ].
  2642 
  2720 
  2643     blocksToEvaluate notNil ifTrue:[
  2721     blocksToEvaluate notNil ifTrue:[
  2644         blocksToEvaluate keysAndValuesDo:[:index :block |
  2722 	blocksToEvaluate keysAndValuesDo:[:index :block |
  2645             |p|
  2723 	    |p|
  2646 
  2724 
  2647             p := processes at:index.
  2725 	    p := processes at:index.
  2648             (p isNil or:[p == scheduler or:[PureEventDriven]]) ifTrue:[
  2726 	    (p isNil or:[p == scheduler or:[PureEventDriven]]) ifTrue:[
  2649                 block value
  2727 		block value
  2650             ] ifFalse:[
  2728 	    ] ifFalse:[
  2651                 p isDead ifTrue:[
  2729 		p isDead ifTrue:[
  2652                     
  2730                     
  2653                     "/ a timedBlock for a process which has already terminated
  2731 		    "/ a timedBlock for a process which has already terminated
  2654                     "/ issue a warning and do not execute it.
  2732 		    "/ issue a warning and do not execute it.
  2655                     "/ (exeuting here may be dangerous, since it would run at scheduler priority here,
  2733 		    "/ (exeuting here may be dangerous, since it would run at scheduler priority here,
  2656                     "/  and thereby could block the whole smalltalk system.
  2734 		    "/  and thereby could block the whole smalltalk system.
  2657                     "/  For this reason is it IGNORED here.)
  2735 		    "/  For this reason is it IGNORED here.)
  2658                     
  2736                     
  2659                     ('ProcessorScheduler [warning]: cannot evaluate timedBlock for dead process: ''' , p name , '''') infoPrintCR.
  2737 		    ('ProcessorScheduler [warning]: cannot evaluate timedBlock for dead process: ''' , p name , '''') infoPrintCR.
  2660                     ('ProcessorScheduler [warning]: the timedBlock is: ' , block displayString) infoPrintCR.
  2738 		    ('ProcessorScheduler [warning]: the timedBlock is: ' , block displayString) infoPrintCR.
  2661                 ] ifFalse:[
  2739 		] ifFalse:[
  2662                     p interruptWith:block
  2740 		    p interruptWith:block
  2663                 ]
  2741 		]
  2664             ]
  2742 	    ]
  2665         ]
  2743 	]
  2666     ]
  2744     ]
  2667 
  2745 
  2668     "Modified: / 9.11.1998 / 21:25:02 / cg"
  2746     "Modified: / 9.11.1998 / 21:25:02 / cg"
  2669 !
  2747 !
  2670 
  2748 
  2720 
  2798 
  2721     "/ must enable interrupts, to be able to get out of a
  2799     "/ must enable interrupts, to be able to get out of a
  2722     "/ long wait (especially, to handle sigChild in the meantime)
  2800     "/ long wait (especially, to handle sigChild in the meantime)
  2723 
  2801 
  2724     (wasBlocked := OperatingSystem interruptsBlocked) ifTrue:[
  2802     (wasBlocked := OperatingSystem interruptsBlocked) ifTrue:[
  2725         OperatingSystem unblockInterrupts.
  2803 	OperatingSystem unblockInterrupts.
  2726     ].
  2804     ].
  2727 
  2805 
  2728     fd := OperatingSystem 
  2806     fd := OperatingSystem 
  2729               selectOnAnyReadable:readFdArray 
  2807 	      selectOnAnyReadable:readFdArray 
  2730                          writable:writeFdArray
  2808 			 writable:writeFdArray
  2731                         exception:nil 
  2809 			exception:nil 
  2732                       withTimeOut:millis.
  2810 		      withTimeOut:millis.
  2733 
  2811 
  2734     wasBlocked ifTrue:[
  2812     wasBlocked ifTrue:[
  2735         OperatingSystem blockInterrupts.
  2813 	OperatingSystem blockInterrupts.
  2736     ].
  2814     ].
  2737 
  2815 
  2738     fd isNil ifTrue:[
  2816     fd isNil ifTrue:[
  2739         "/ either still nothing to do,
  2817 	"/ either still nothing to do,
  2740         "/ or error (which should not happen)
  2818 	"/ or error (which should not happen)
  2741 
  2819 
  2742         (err := OperatingSystem lastErrorSymbol) notNil ifTrue:[
  2820 	(err := OperatingSystem lastErrorSymbol) notNil ifTrue:[
  2743             err == #EBADF ifTrue:[
  2821 	    err == #EBADF ifTrue:[
  2744 
  2822 
  2745                 "/ mhmh - one of the fd's given to me is corrupt.
  2823 		"/ mhmh - one of the fd's given to me is corrupt.
  2746                 "/ find out which one .... and remove it
  2824 		"/ find out which one .... and remove it
  2747 
  2825 
  2748                 'Processor [info]: obsolete FD in select - clearing' infoPrintCR.
  2826 		'Processor [info]: obsolete FD in select - clearing' infoPrintCR.
  2749                 OperatingSystem clearLastErrorNumber.
  2827 		OperatingSystem clearLastErrorNumber.
  2750                 self removeCorruptedFds
  2828 		self removeCorruptedFds
  2751             ] ifFalse:[
  2829 	    ] ifFalse:[
  2752                 err == #ENOENT ifTrue:[
  2830 		err == #ENOENT ifTrue:[
  2753                     'Processor [warning]: ENOENT in select; rd=' infoPrint.
  2831 		    'Processor [warning]: ENOENT in select; rd=' infoPrint.
  2754                     readFdArray infoPrint.
  2832 		    readFdArray infoPrint.
  2755                     ' wr=' infoPrint.
  2833 		    ' wr=' infoPrint.
  2756                     writeFdArray infoPrintCR.
  2834 		    writeFdArray infoPrintCR.
  2757                 ] ifFalse:[
  2835 		] ifFalse:[
  2758                     'Processor [warning]: error in select: ' infoPrint. err infoPrintCR.
  2836 		    'Processor [warning]: error in select: ' infoPrint. err infoPrintCR.
  2759                 ]
  2837 		]
  2760             ].
  2838 	    ].
  2761         ]
  2839 	]
  2762     ] ifFalse:[
  2840     ] ifFalse:[
  2763         index := readFdArray indexOf:fd.
  2841 	index := readFdArray indexOf:fd.
  2764         index ~~ 0 ifTrue:[
  2842 	index ~~ 0 ifTrue:[
  2765             sema := readSemaphoreArray at:index.
  2843 	    sema := readSemaphoreArray at:index.
  2766             sema notNil ifTrue:[
  2844 	    sema notNil ifTrue:[
  2767                 sema signalOnce.
  2845 		sema signalOnce.
  2768                 ^ true
  2846 		^ true
  2769             ].
  2847 	    ].
  2770             action := readCheckArray at:index.
  2848 	    action := readCheckArray at:index.
  2771             action notNil ifTrue:[
  2849 	    action notNil ifTrue:[
  2772                 action value.
  2850 		action value.
  2773                  ^ true
  2851 		 ^ true
  2774             ]
  2852 	    ]
  2775         ]
  2853 	]
  2776     ].
  2854     ].
  2777     ^ false
  2855     ^ false
  2778 
  2856 
  2779     "Modified: / 12.4.1996 / 09:31:22 / stefan"
  2857     "Modified: / 12.4.1996 / 09:31:22 / stefan"
  2780     "Modified: / 14.6.1998 / 17:31:51 / cg"
  2858     "Modified: / 14.6.1998 / 17:31:51 / cg"
  2789      Notice, that at the time of the message, we are still in the context
  2867      Notice, that at the time of the message, we are still in the context
  2790      of whichever process is currently running."
  2868      of whichever process is currently running."
  2791 
  2869 
  2792     gotIOInterrupt := true.
  2870     gotIOInterrupt := true.
  2793     activeProcess ~~ scheduler ifTrue:[
  2871     activeProcess ~~ scheduler ifTrue:[
  2794         interruptedProcess := activeProcess.
  2872 	interruptedProcess := activeProcess.
  2795         self threadSwitch:scheduler
  2873 	self threadSwitch:scheduler
  2796     ]
  2874     ]
  2797 
  2875 
  2798     "Modified: 21.12.1995 / 16:17:40 / stefan"
  2876     "Modified: 21.12.1995 / 16:17:40 / stefan"
  2799     "Modified: 4.8.1997 / 14:23:08 / cg"
  2877     "Modified: 4.8.1997 / 14:23:08 / cg"
  2800 !
  2878 !
  2812     readFdArray keysAndValuesDo:[:idx :fd |
  2890     readFdArray keysAndValuesDo:[:idx :fd |
  2813 	|rslt sema|
  2891 	|rslt sema|
  2814 
  2892 
  2815 	(fd notNil "and:[fd >= 0]") ifTrue:[
  2893 	(fd notNil "and:[fd >= 0]") ifTrue:[
  2816 	    rslt := OperatingSystem
  2894 	    rslt := OperatingSystem
  2817 		        selectOnAnyReadable:(Array with:fd)
  2895 			selectOnAnyReadable:(Array with:fd)
  2818 			           writable:nil
  2896 				   writable:nil
  2819 			          exception:nil
  2897 				  exception:nil
  2820 			        withTimeOut:0.
  2898 				withTimeOut:0.
  2821 
  2899 
  2822 	    (rslt isNil and:[OperatingSystem lastErrorSymbol == #EBADF]) ifTrue:[
  2900 	    (rslt isNil and:[OperatingSystem lastErrorSymbol == #EBADF]) ifTrue:[
  2823 	        ('Processor [info]: removing invalid read-select fileDescriptor: ' , fd printString) errorPrintCR.
  2901 		('Processor [info]: removing invalid read-select fileDescriptor: ' , fd printString) errorPrintCR.
  2824 	        readFdArray at:idx put:nil.
  2902 		readFdArray at:idx put:nil.
  2825 	        OperatingSystem clearLastErrorNumber.
  2903 		readCheckArray at:idx put:nil.
  2826 	        (sema := readSemaphoreArray at:idx) notNil ifTrue:[
  2904 		OperatingSystem clearLastErrorNumber.
       
  2905 		(sema := readSemaphoreArray at:idx) notNil ifTrue:[
  2827 		    readSemaphoreArray at:idx put:nil.
  2906 		    readSemaphoreArray at:idx put:nil.
  2828 		    sema signal.
  2907 		    sema signal.
  2829 	        ].
  2908 		].
  2830 	    ]
  2909 	    ]
  2831 	].
  2910 	].
  2832     ].
  2911     ].
  2833 
  2912 
  2834     writeFdArray keysAndValuesDo:[:idx :fd |
  2913     writeFdArray keysAndValuesDo:[:idx :fd |
  2835 	|rslt sema|
  2914 	|rslt sema|
  2836 
  2915 
  2837 	rslt := OperatingSystem
  2916 	(fd notNil) ifTrue:[
  2838 		    selectOnAnyReadable:nil
  2917 	    rslt := OperatingSystem
  2839 			       writable:(Array with:fd)
  2918 			selectOnAnyReadable:nil
  2840 			      exception:nil
  2919 				   writable:(Array with:fd)
  2841 			    withTimeOut:0.
  2920 				  exception:nil
  2842 
  2921 				withTimeOut:0.
  2843 	(rslt isNil and:[OperatingSystem lastErrorSymbol == #EBADF]) ifTrue:[
  2922 
  2844 	    ('Processor [info]: removing invalid write-select fileDescriptor: ' , fd printString) errorPrintCR.
  2923 	    (rslt isNil and:[OperatingSystem lastErrorSymbol == #EBADF]) ifTrue:[
  2845 	    writeFdArray at:idx put:nil.
  2924 		('Processor [info]: removing invalid write-select fileDescriptor: ' , fd printString) errorPrintCR.
  2846 	    OperatingSystem clearLastErrorNumber.
  2925 		writeFdArray at:idx put:nil.
  2847 	    (sema := writeSemaphoreArray at:idx) notNil ifTrue:[
  2926 		writeCheckArray at:idx put:nil.
  2848 		writeSemaphoreArray at:idx put:nil.
  2927 		OperatingSystem clearLastErrorNumber.
  2849 		sema signal.
  2928 		(sema := writeSemaphoreArray at:idx) notNil ifTrue:[
  2850 	    ].
  2929 		    writeSemaphoreArray at:idx put:nil.
       
  2930 		    sema signal.
       
  2931 		].
       
  2932 	    ]
  2851 	]
  2933 	]
  2852     ].
  2934     ].
  2853 
  2935 
  2854     "Modified: 12.4.1996 / 09:32:58 / stefan"
  2936     "Modified: 12.4.1996 / 09:32:58 / stefan"
  2855     "Modified: 27.1.1997 / 20:09:27 / cg"
  2937     "Modified: 27.1.1997 / 20:09:27 / cg"
  2858 schedulerInterrupt
  2940 schedulerInterrupt
  2859     "forced reschedule - switch to scheduler process which will decide
  2941     "forced reschedule - switch to scheduler process which will decide
  2860      what to do now."
  2942      what to do now."
  2861 
  2943 
  2862     activeProcess ~~ scheduler ifTrue:[
  2944     activeProcess ~~ scheduler ifTrue:[
  2863         interruptedProcess := activeProcess.
  2945 	interruptedProcess := activeProcess.
  2864         self threadSwitch:scheduler
  2946 	self threadSwitch:scheduler
  2865     ]
  2947     ]
  2866 !
  2948 !
  2867 
  2949 
  2868 timeToNextTimeout
  2950 timeToNextTimeout
  2869     "return the delta-T (in millis) to next timeout, or nil if
  2951     "return the delta-T (in millis) to next timeout, or nil if
  2903      This method is called by the VM' interrupt handling mechanism.
  2985      This method is called by the VM' interrupt handling mechanism.
  2904      Notice, that at the time of the message, we are still in the context
  2986      Notice, that at the time of the message, we are still in the context
  2905      of whichever process is currently running."
  2987      of whichever process is currently running."
  2906 
  2988 
  2907     activeProcess ~~ scheduler ifTrue:[
  2989     activeProcess ~~ scheduler ifTrue:[
  2908         interruptedProcess := activeProcess.
  2990 	interruptedProcess := activeProcess.
  2909         self threadSwitch:scheduler
  2991 	self threadSwitch:scheduler
  2910     ]
  2992     ]
  2911 
  2993 
  2912     "Modified: 18.10.1996 / 20:35:54 / cg"
  2994     "Modified: 18.10.1996 / 20:35:54 / cg"
  2913 !
  2995 !
  2914 
  2996 
  2991     ].
  3073     ].
  2992 
  3074 
  2993     OperatingSystem supportsIOInterrupts ifTrue:[
  3075     OperatingSystem supportsIOInterrupts ifTrue:[
  2994 	dT := 999999
  3076 	dT := 999999
  2995     ] ifFalse:[
  3077     ] ifFalse:[
  2996         dT := EventPollingInterval
  3078 	dT := EventPollingInterval
  2997     ].
  3079     ].
  2998 
  3080 
  2999     millis isNil ifTrue:[
  3081     millis isNil ifTrue:[
  3000 	millis := dT.
  3082 	millis := dT.
  3001     ] ifFalse:[
  3083     ] ifFalse:[
  3008 ! !
  3090 ! !
  3009 
  3091 
  3010 !ProcessorScheduler class methodsFor:'documentation'!
  3092 !ProcessorScheduler class methodsFor:'documentation'!
  3011 
  3093 
  3012 version
  3094 version
  3013     ^ '$Header: /cvs/stx/stx/libbasic/ProcessorScheduler.st,v 1.180 1999-10-08 09:03:21 ca Exp $'
  3095     ^ '$Header: /cvs/stx/stx/libbasic/ProcessorScheduler.st,v 1.181 1999-12-14 18:46:28 cg Exp $'
  3014 ! !
  3096 ! !
  3015 ProcessorScheduler initialize!
  3097 ProcessorScheduler initialize!