ProcessorScheduler.st
branchjv
changeset 23072 0402b3e0d43b
parent 23071 77ad9497363c
parent 21027 ad86468de3a0
child 23073 7e7d5e29738c
equal deleted inserted replaced
23071:77ad9497363c 23072:0402b3e0d43b
    76     To allow pureEvent mode, kludges are built into some places in the
    76     To allow pureEvent mode, kludges are built into some places in the
    77     system, where either a process is forked, or a timeout is used instead
    77     system, where either a process is forked, or a timeout is used instead
    78     (for examples, see ProcessMonitor or MemoryMonitor).
    78     (for examples, see ProcessMonitor or MemoryMonitor).
    79 
    79 
    80     This pure-event mode may not be supported in the future
    80     This pure-event mode may not be supported in the future
    81     (actually, it is no longer maintained, so dont run the system without Processes).
    81     (actually, it is no longer maintained, so don't run the system without Processes).
    82 
    82 
    83     [instance variables:]
    83     [instance variables:]
    84 	quiescentProcessLists           - list of waiting processes
    84         quiescentProcessLists           - list of waiting processes
    85 	scheduler                       - the scheduler process itself
    85         scheduler                       - the scheduler process itself
    86 	zombie                          - internal temporary (recently died process)
    86         zombie                          - internal temporary (recently died process)
    87 	activeProcess                   - the current process
    87         activeProcess                   - the current process
    88 	activeProcessId                 - the current processes id
    88         activeProcessId                 - the current processes id
    89 	currentPriority                 - the current processes priority
    89         currentPriority                 - the current processes priority
    90 	readFdArray                     - fd-sema-checkBlock triple-association
    90         readFdArray                     - fd-sema-checkBlock triple-association
    91 	readSemaphoreArray                (stupid historic 3-separate arrays for hi-speed-optimization reasons)
    91         readSemaphoreArray                (stupid historic 3-separate arrays for hi-speed-optimization reasons)
    92 	readCheckArray
    92         readCheckArray
    93 	writeFdArray                    - fd-sema-checkBlock triple-association
    93         writeFdArray                    - fd-sema-checkBlock triple-association
    94 	writeSemaphoreArray               (stupid historic 3-separate arrays for hi-speed-optimization reasons)
    94         writeSemaphoreArray               (stupid historic 3-separate arrays for hi-speed-optimization reasons)
    95 	writeCheckArray
    95         writeCheckArray
    96 	timeoutArray                    - time-action-process-sema quadruple-association
    96         timeoutArray                    - time-action-process-sema quadruple-association
    97 	timeoutActionArray                (stupid historic 3-separate arrays for hi-speed-optimization reasons)
    97         timeoutActionArray                (stupid historic 3-separate arrays for hi-speed-optimization reasons)
    98 	timeoutProcessArray
    98         timeoutProcessArray
    99 	timeoutSemaphoreArray
    99         timeoutSemaphoreArray
   100 	idleActions                     - actions to be executed when idle
   100         idleActions                     - actions to be executed when idle
   101 	preWaitActions                  - actions to be executed BEFORE going into an OS-wait
   101         preWaitActions                  - actions to be executed BEFORE going into an OS-wait
   102 	anyTimeouts                     - flag if any timeouts are pending
   102         anyTimeouts                     - flag if any timeouts are pending
   103 	dispatching                     - flag if dispatch process is running (i.e. NOT initializing)
   103         dispatching                     - flag if dispatch process is running (i.e. NOT initializing)
   104 	interruptedProcess              - the currently interrupted process.
   104         interruptedProcess              - the currently interrupted process.
   105 	useIOInterrupts                 - flag if the OS supports I/O interrupts and if they are used (to get me out of an OS wait)
   105         useIOInterrupts                 - flag if the OS supports I/O interrupts and if they are used (to get me out of an OS wait)
   106 	gotIOInterrupt                  - flag if I came out of a wait due to an I/O interrupt
   106         gotIOInterrupt                  - flag if I came out of a wait due to an I/O interrupt
   107 	osChildExitActions              - OS chid process actions
   107         osChildExitActions              - OS chid process actions
   108 	gotChildSignalInterrupt         - flag if I came out of a wait due to an OS child interrupt
   108         gotChildSignalInterrupt         - flag if I came out of a wait due to an OS child interrupt
   109 	exitWhenNoMoreUserProcesses     - flag which controls if ST/X should exit when the last process dies (for standalone apps)
   109         exitWhenNoMoreUserProcesses     - flag which controls if ST/X should exit when the last process dies (for standalone apps)
   110 	suspendScheduler                - internal use
   110         suspendScheduler                - internal use
   111 	timeSliceProcess                - the timeSlicer process
   111         timeSliceProcess                - the timeSlicer process
   112 	supportDynamicPriorities        - flag if dynamic priorities should be supported by the timeSlicer
   112         supportDynamicPriorities        - flag if dynamic priorities should be supported by the timeSlicer
   113 	scheduledProcesses              - list of scheduled processes for the timeSlicers dynamic prio handling
   113         scheduledProcesses              - list of scheduled processes for the timeSlicers dynamic prio handling
   114 
   114 
   115     [class variables:]
   115     [class variables:]
   116 
   116 
   117 	KnownProcesses          <WeakArray>     all known processes
   117         KnownProcesses          <WeakArray>     all known processes
   118 	KnownProcessIds         <Collection>    and their IDs
   118         KnownProcessIds         <Collection>    and their IDs
   119 
   119 
   120 	PureEventDriven         <Boolean>       true, if no process support
   120         PureEventDriven         <Boolean>       true, if no process support
   121 						is available
   121                                                 is available
   122 
   122 
   123 	UserSchedulingPriority  <Integer>       the priority at which normal
   123         UserSchedulingPriority  <Integer>       the priority at which normal
   124 						user interfaces run
   124                                                 user interfaces run
   125 
   125 
   126 	UserInterruptPriority                   the priority at which user-
   126         UserInterruptPriority                   the priority at which user-
   127 						interrupts (Cntl-C) processing
   127                                                 interrupts (Cntl-C) processing
   128 						takes place. Processes with
   128                                                 takes place. Processes with
   129 						a greater or equal priority are
   129                                                 a greater or equal priority are
   130 						not interruptable.
   130                                                 not interruptable.
   131 
   131 
   132 	TimingPriority                          the priority used for timing.
   132         TimingPriority                          the priority used for timing.
   133 						Processes with a greater or
   133                                                 Processes with a greater or
   134 						equal priority are not interrupted
   134                                                 equal priority are not interrupted
   135 						by timers.
   135                                                 by timers.
   136 
   136 
   137 	HighestPriority                         The highest allowed prio for processes
   137         HighestPriority                         The highest allowed prio for processes
   138 
   138 
   139 	SchedulingPriority                      The priority of the scheduler (must
   139         SchedulingPriority                      The priority of the scheduler (must
   140 						me higher than any other).
   140                                                 me higher than any other).
   141 
   141 
   142 	MaxNumberOfProcesses                    if non-nil, no more than this
   142         MaxNumberOfProcesses                    if non-nil, no more than this
   143 						number of processes are allowed
   143                                                 number of processes are allowed
   144 						(for debugging)
   144                                                 (for debugging)
   145 
   145 
   146 	TimeSliceInterval                       for preemptive priority scheduling only:
   146         TimeSliceInterval                       for preemptive priority scheduling only:
   147 						the time interval in millis, at which processes
   147                                                 the time interval in millis, at which processes
   148 						are timesliced
   148                                                 are timesliced
   149 
   149 
   150 	TimeSlicingPriorityLimit                for preemptive priority scheduling only:
   150         TimeSlicingPriorityLimit                for preemptive priority scheduling only:
   151 						processes are only timesliced, if running
   151                                                 processes are only timesliced, if running
   152 						at or below this priority.
   152                                                 at or below this priority.
   153 
   153 
   154 	EventPollingInterval                    for systems which do not support select on
   154         EventPollingInterval                    for systems which do not support select on
   155 						a fileDescriptor: the polling interval in millis.
   155                                                 a fileDescriptor: the polling interval in millis.
   156 
   156 
   157     most interesting methods:
   157     most interesting methods:
   158 
   158 
   159 	Processor>>suspend:                  (see also Process>>suspend)
   159         Processor>>suspend:                  (see also Process>>suspend)
   160 	Processor>>resume:                   (see also Process>>resume)
   160         Processor>>resume:                   (see also Process>>resume)
   161 	Processor>>terminate:                (see also Process>>terminate)
   161         Processor>>terminate:                (see also Process>>terminate)
   162 	Processor>>yield
   162         Processor>>yield
   163 	Processor>>changePriority:for:       (see also Process>>priority:
   163         Processor>>changePriority:for:       (see also Process>>priority:
   164 
   164 
   165 	Processor>>signal:afterSeconds:      (see also Delay>>forSeconds:)
   165         Processor>>signal:afterSeconds:      (see also Delay>>forSeconds:)
   166 	Processor>>signal:afterMilliseconds: (see also Delay>>forMilliseconds:)
   166         Processor>>signal:afterMilliseconds: (see also Delay>>forMilliseconds:)
   167 	Processor>>signal:onInput:           (see also ExternalStream>>readWait)
   167         Processor>>signal:onInput:           (see also ExternalStream>>readWait)
   168 	Processor>>signal:onOutput:          (see also ExternalStream>>writeWait)
   168         Processor>>signal:onOutput:          (see also ExternalStream>>writeWait)
   169 	Processor>>disableSemaphore:
   169         Processor>>disableSemaphore:
   170 
   170 
   171 
   171 
   172     [see also:]
   172     [see also:]
   173 	Process
   173         Process
   174 	Delay Semaphore SemaphoreSet SharedQueue
   174         Delay Semaphore SemaphoreSet SharedQueue
   175 	WindowGroup
   175         WindowGroup
   176 	(``Working with processes'': programming/processes.html)
   176         (``Working with processes'': programming/processes.html)
   177 
   177 
   178     [author:]
   178     [author:]
   179 	Claus Gittinger
   179         Claus Gittinger
   180 "
   180 "
   181 !
   181 !
   182 
   182 
   183 scheduling
   183 scheduling
   184 "
   184 "
   272     ].
   272     ].
   273 
   273 
   274     Processor isNil ifTrue:[
   274     Processor isNil ifTrue:[
   275 	"create the one and only processor"
   275 	"create the one and only processor"
   276 
   276 
   277 	Processor := self basicNew initialize.
   277 	Smalltalk at:#Processor put:(self basicNew initialize).
   278     ].
   278     ].
   279 
   279 
   280     "
   280     "
   281      allow configurations without processes
   281      allow configurations without processes
   282      (but such configurations are no longer distributed)
   282      (but such configurations are no longer distributed)
   363     "physical creation of a process.
   363     "physical creation of a process.
   364      (warning: low level entry, no administration done).
   364      (warning: low level entry, no administration done).
   365      This may raise an exception, if a VM process could not be created."
   365      This may raise an exception, if a VM process could not be created."
   366 
   366 
   367     MaxNumberOfProcesses notNil ifTrue:[
   367     MaxNumberOfProcesses notNil ifTrue:[
   368 	KnownProcessIds size >= MaxNumberOfProcesses ifTrue:[
   368         KnownProcessIds size >= MaxNumberOfProcesses ifTrue:[
   369 	    (KnownProcessIds count:[:el | el notNil]) >= MaxNumberOfProcesses ifTrue:[
   369             (KnownProcessIds count:[:el | el notNil]) >= MaxNumberOfProcesses ifTrue:[
   370 		"
   370                 "
   371 		 the number of processes has reached the (soft) limit.
   371                  the number of processes has reached the (soft) limit.
   372 		 This limit prevents runaway programs from creating too many
   372                  This limit prevents runaway programs from creating too many
   373 		 processes. If you continue in the debugger, the process will be
   373                  processes. If you continue in the debugger, the process will be
   374 		 created as usual. If you dont want this, abort or terminate.
   374                  created as usual. If you don't want this, abort or terminate.
   375 		"
   375                 "
   376 		self error:'too many processes'.
   376                 self error:'too many processes'.
   377 	    ]
   377             ]
   378 	]
   378         ]
   379     ].
   379     ].
   380 
   380 
   381 %{
   381 %{
   382     int tid;
   382     int tid;
   383     extern int __threadCreate();
   383     extern int __threadCreate();
   384 
   384 
   385     tid = __threadCreate(aProcess,
   385     tid = __threadCreate(aProcess,
   386 			 0   /* stackSize: no longer needed */,
   386                          0   /* stackSize: no longer needed */,
   387 			 __isSmallInteger(id) ? __intVal(id)     /* assign id */
   387                          __isSmallInteger(id) ? __intVal(id)     /* assign id */
   388 					      : -1              /* let VM assign one */  );
   388                                               : -1              /* let VM assign one */  );
   389     if (tid) {
   389     if (tid) {
   390 	RETURN ( __mkSmallInteger(tid));
   390         RETURN ( __mkSmallInteger(tid));
   391     }
   391     }
   392 %}
   392 %}
   393 .
   393 .
   394     "
   394     "
   395      arrive here, if creation of process in VM failed.
   395      arrive here, if creation of process in VM failed.
   396      This may happen, if the VM does not support more processes,
   396      This may happen, if the VM does not support more processes,
   397      or if it ran out of memory, when allocating internal data
   397      or if it ran out of memory, when allocating internal data
   398      structures.
   398      structures.
   399     "
   399     "
   400     ^ ObjectMemory allocationFailureSignal raise.
   400     ^ AllocationFailure raise.
   401 !
   401 !
   402 
   402 
   403 threadDestroy:id
   403 threadDestroy:id
   404     "physical destroy other process ...
   404     "physical destroy other process ...
   405      (warning: low level entry, no administration done)"
   405      (warning: low level entry, no administration done)"
   577     "Processor currentPriority"
   577     "Processor currentPriority"
   578 !
   578 !
   579 
   579 
   580 interruptCounter
   580 interruptCounter
   581     "for statistics: counts the overall number of interrupts"
   581     "for statistics: counts the overall number of interrupts"
   582     
   582 
   583     ^ interruptCounter
   583     ^ interruptCounter
   584 
   584 
   585     "
   585     "
   586      Processor interruptCounter
   586      Processor interruptCounter
   587     "
   587     "
   605     ^ scheduler
   605     ^ scheduler
   606 !
   606 !
   607 
   607 
   608 timedActionCounter
   608 timedActionCounter
   609     "for statistics: counts the overall number of timer actions"
   609     "for statistics: counts the overall number of timer actions"
   610     
   610 
   611     ^ timedActionCounter
   611     ^ timedActionCounter
   612 
   612 
   613     "
   613     "
   614      Processor timedActionCounter
   614      Processor timedActionCounter
   615     "
   615     "
   664 
   664 
   665     "
   665     "
   666      handle all timeout actions
   666      handle all timeout actions
   667     "
   667     "
   668     anyTimeouts ifTrue:[
   668     anyTimeouts ifTrue:[
   669 	self evaluateTimeouts
   669         self evaluateTimeouts
   670     ].
   670     ].
   671 
   671 
   672     "first do a quick check for semaphores using checkActions - this is needed for
   672     "first do a quick check for semaphores using checkActions - this is needed for
   673      devices like the X-connection, where some events might be in the event
   673      devices like the X-connection, where some events might be in the event
   674      queue but the sockets input queue is empty.
   674      queue but the sockets input queue is empty.
   676      Also, this is needed for poor MSDOS, where WaitForObject does not work with
   676      Also, this is needed for poor MSDOS, where WaitForObject does not work with
   677      sockets and pipes (sigh)
   677      sockets and pipes (sigh)
   678     "
   678     "
   679     nActions := readCheckArray size.
   679     nActions := readCheckArray size.
   680     1 to:nActions do:[:index |
   680     1 to:nActions do:[:index |
   681 	checkBlock := readCheckArray at:index.
   681         checkBlock := readCheckArray at:index.
   682 	(checkBlock notNil and:[checkBlock value]) ifTrue:[
   682         (checkBlock notNil and:[checkBlock value]) ifTrue:[
   683 	    sema := readSemaphoreArray at:index.
   683             sema := readSemaphoreArray at:index.
   684 	    sema notNil ifTrue:[
   684             sema notNil ifTrue:[
   685 		sema signalOnce.
   685                 sema signalOnce.
   686 	    ].
   686             ].
   687 	]
   687         ]
   688     ].
   688     ].
   689     nActions := writeCheckArray size.
   689     nActions := writeCheckArray size.
   690     1 to:nActions do:[:index |
   690     1 to:nActions do:[:index |
   691 	checkBlock := writeCheckArray at:index.
   691         checkBlock := writeCheckArray at:index.
   692 	(checkBlock notNil and:[checkBlock value]) ifTrue:[
   692         (checkBlock notNil and:[checkBlock value]) ifTrue:[
   693 	    sema := writeSemaphoreArray at:index.
   693             sema := writeSemaphoreArray at:index.
   694 	    sema notNil ifTrue:[
   694             sema notNil ifTrue:[
   695 		sema signalOnce.
   695                 sema signalOnce.
   696 	    ].
   696             ].
   697 	]
   697         ]
   698     ].
   698     ].
   699 
   699 
   700     "now, someone might be runnable ..."
   700     "now, someone might be runnable ..."
   701 
   701 
   702     p := self highestPriorityRunnableProcess.
   702     p := self highestPriorityRunnableProcess.
   703     p isNil ifTrue:[
   703     p isNil ifTrue:[
   704 	"/ no one runnable, hard wait for event or timeout
   704         "/ no one runnable, hard wait for event or timeout
   705 	"/ Trace ifTrue:['w' printCR.].
   705         "/ Trace ifTrue:['w' printCR.].
   706 	self waitForEventOrTimeout.
   706         self waitForEventOrTimeout.
   707 
   707 
   708 	"/ check for OS process termination
   708         "/ check for OS process termination
   709 	gotChildSignalInterrupt ifTrue:[
   709         gotChildSignalInterrupt ifTrue:[
   710 	    gotChildSignalInterrupt := false.
   710             gotChildSignalInterrupt := false.
   711 	    self handleChildSignalInterrupt
   711             self handleChildSignalInterrupt
   712 	].
   712         ].
   713 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   713         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   714 	^ self
   714         ^ self
   715     ].
   715     ].
   716 
   716 
   717     pri := p priority.
   717     pri := p priority.
   718 
   718 
   719     "
   719     "
   724      This is done by enabling ioInterrupts for all file descriptors.
   724      This is done by enabling ioInterrupts for all file descriptors.
   725      If ioInterrupts are not available (OS does not support them),
   725      If ioInterrupts are not available (OS does not support them),
   726      we schedule a timer interrupt to interrupt us after 1/20s of a second
   726      we schedule a timer interrupt to interrupt us after 1/20s of a second
   727      - effectively polling the filedescriptors 20 times a second.
   727      - effectively polling the filedescriptors 20 times a second.
   728      (which is bad, since low prio processes will be hurt in performance)
   728      (which is bad, since low prio processes will be hurt in performance)
   729      Therefore, dont let benchmarks run with low prio ...
   729      Therefore, don't let benchmarks run with low prio ...
   730 
   730 
   731      Higher prio processes must be suspended,
   731      Higher prio processes must be suspended,
   732      same prio ones must yield or suspend to get back control
   732      same prio ones must yield or suspend to get back control
   733     "
   733     "
   734 
   734 
   740  (a future version will have a process running to handle a timeout queue)
   740  (a future version will have a process running to handle a timeout queue)
   741 "
   741 "
   742 
   742 
   743 "
   743 "
   744     pri < TimingPriority ifTrue:[
   744     pri < TimingPriority ifTrue:[
   745 	anyTimeouts ifTrue:[
   745         anyTimeouts ifTrue:[
   746 	    millis := self timeToNextTimeout.
   746             millis := self timeToNextTimeout.
   747 	    millis == 0 ifTrue:[
   747             millis == 0 ifTrue:[
   748 		wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   748                 wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   749 		^ self
   749                 ^ self
   750 	    ]
   750             ]
   751 	]
   751         ]
   752     ].
   752     ].
   753 "
   753 "
   754 
   754 
   755     "
   755     "
   756      if the process to run has a lower than UserInterruptPriority,
   756      if the process to run has a lower than UserInterruptPriority,
   759      or by installing a poll-interrupt after 50ms (if the OS does not).
   759      or by installing a poll-interrupt after 50ms (if the OS does not).
   760     "
   760     "
   761     pri < UserInterruptPriority ifTrue:[
   761     pri < UserInterruptPriority ifTrue:[
   762 
   762 
   763 "comment out this if above is uncommented"
   763 "comment out this if above is uncommented"
   764 	anyTimeouts ifTrue:[
   764         anyTimeouts ifTrue:[
   765 	    millis := self timeToNextTimeout.
   765             millis := self timeToNextTimeout.
   766 	    millis == 0 ifTrue:[
   766             millis == 0 ifTrue:[
   767 		wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   767                 wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   768 		^ self
   768                 ^ self
   769 	    ].
   769             ].
   770 	].
   770         ].
   771 "---"
   771 "---"
   772 
   772 
   773 	useIOInterrupts ifTrue:[
   773         useIOInterrupts ifTrue:[
   774 "/            readFdArray do:[:fd |
   774 "/            readFdArray do:[:fd |
   775 "/                (fd notNil and:[fd >= 0]) ifTrue:[
   775 "/                (fd notNil and:[fd >= 0]) ifTrue:[
   776 "/                    OperatingSystem enableIOInterruptsOn:fd
   776 "/                    OperatingSystem enableIOInterruptsOn:fd
   777 "/                ].
   777 "/                ].
   778 "/            ].
   778 "/            ].
   779 	] ifFalse:[
   779         ] ifFalse:[
   780 	    millis notNil ifTrue:[
   780             millis notNil ifTrue:[
   781 		millis := millis min:EventPollingInterval
   781                 millis := millis min:EventPollingInterval
   782 	    ] ifFalse:[
   782             ] ifFalse:[
   783 		millis := EventPollingInterval
   783                 millis := EventPollingInterval
   784 	    ]
   784             ]
   785 	]
   785         ]
   786     ].
   786     ].
   787 
   787 
   788     millis notNil ifTrue:[
   788     millis notNil ifTrue:[
   789 	"/ Trace ifTrue:['C' print. millis printCR.].
   789         "/ Trace ifTrue:['C' print. millis printCR.].
   790 	"schedule a clock interrupt after millis milliseconds"
   790         "schedule a clock interrupt after millis milliseconds"
   791 	OperatingSystem enableTimer:millis rounded.
   791         OperatingSystem enableTimer:millis rounded.
   792     ].
   792     ].
   793 
   793 
   794     scheduledProcesses notNil ifTrue:[
   794     scheduledProcesses notNil ifTrue:[
   795 	scheduledProcesses add:p
   795         scheduledProcesses add:p
   796     ].
   796     ].
   797 
   797 
   798     "
   798     "
   799      now let the process run - will come back here by reschedule
   799      now let the process run - will come back here by reschedule
   800      from ioInterrupt, scheduler or timerInterrupt ... (running at max+1)
   800      from ioInterrupt, scheduler or timerInterrupt ... (running at max+1)
   802     "/ Trace ifTrue:['->' print. p printCR.].
   802     "/ Trace ifTrue:['->' print. p printCR.].
   803     self threadSwitch:p.
   803     self threadSwitch:p.
   804     "/ Trace ifTrue:['<-' printCR.].
   804     "/ Trace ifTrue:['<-' printCR.].
   805 
   805 
   806     "... when we arrive here, we are back on stage.
   806     "... when we arrive here, we are back on stage.
   807 	 Either by an ALARM or IO signal, or by a suspend of another process
   807          Either by an ALARM or IO signal, or by a suspend of another process
   808     "
   808     "
   809 
   809 
   810     millis notNil ifTrue:[
   810     millis notNil ifTrue:[
   811 	OperatingSystem disableTimer.
   811         OperatingSystem disableTimer.
   812     ].
   812     ].
   813 
   813 
   814     "/ check for OS process termination
   814     "/ check for OS process termination
   815     gotChildSignalInterrupt ifTrue:[
   815     gotChildSignalInterrupt ifTrue:[
   816 	gotChildSignalInterrupt := false.
   816         gotChildSignalInterrupt := false.
   817 	self handleChildSignalInterrupt
   817         self handleChildSignalInterrupt
   818     ].
   818     ].
   819 
   819 
   820     "/ check for new input
   820     "/ check for new input
   821 
   821 
   822     OperatingSystem unblockInterrupts.
   822     OperatingSystem unblockInterrupts.
   823 
   823 
   824     (gotIOInterrupt or:[useIOInterrupts not]) ifTrue:[
   824     (gotIOInterrupt or:[useIOInterrupts not]) ifTrue:[
   825 	gotIOInterrupt := false.
   825         gotIOInterrupt := false.
   826 	self checkForIOWithTimeout:0.
   826         self checkForIOWithTimeout:0.
   827     ].
   827     ].
   828 
   828 
   829     wasBlocked ifTrue:[OperatingSystem blockInterrupts].
   829     wasBlocked ifTrue:[OperatingSystem blockInterrupts].
   830 
   830 
   831     "Modified: / 12.4.1996 / 10:14:18 / stefan"
   831     "Modified: / 12.4.1996 / 10:14:18 / stefan"
   839     |dispatchAction handlerAction ignoredSignals|
   839     |dispatchAction handlerAction ignoredSignals|
   840 
   840 
   841     "avoid confusion if entered twice"
   841     "avoid confusion if entered twice"
   842 
   842 
   843     dispatching == true ifTrue:[
   843     dispatching == true ifTrue:[
   844 	'Processor [info]: already in dispatch' infoPrintCR.
   844         'Processor [info]: already in dispatch' infoPrintCR.
   845 	^ self
   845         ^ self
   846     ].
   846     ].
   847     dispatching := true.
   847     dispatching := true.
   848 
   848 
   849     "/ create the relevant blocks & signalSet outside of the
   849     "/ create the relevant blocks & signalSet outside of the
   850     "/ while-loop
   850     "/ while-loop
   851     "/ (thanks to stefans objectAllocation monitor,
   851     "/ (thanks to stefans objectAllocation monitor,
   852     "/  this safes a bit of memory allocation in the scheduler)
   852     "/  this safes a bit of memory allocation in the scheduler)
   853 
   853 
   854     dispatchAction := [ [dispatching] whileTrue:[ self dispatch ] ].
   854     dispatchAction := 
   855 
   855         [ 
   856     handlerAction := [:ex |
   856             [dispatching] whileTrue:[ 
   857 			(HaltInterrupt accepts:ex creator) ifTrue:[
   857                 self dispatch 
   858 			    "/ in a standalone application, we do not want those
   858             ] 
   859 			    Smalltalk isStandAloneApp ifTrue:[
   859         ].
   860 				Smalltalk isStandAloneDebug ifFalse:[
   860 
   861 				    ('Processor [info]: ignored (', ex creator printString, ')') infoPrintCR.
   861     handlerAction := 
   862 				    ex proceed.
   862         [:ex |
   863 				]
   863             (HaltInterrupt accepts:ex creator) ifTrue:[
   864 			    ].
   864                 "/ in a standalone application, we do not want those
   865 			].
   865                 (Smalltalk isStandAloneApp and:[Smalltalk isStandAloneDebug not]) ifTrue:[
   866 
   866                     ('Processor [info]: ignored (', ex creator printString, ')') infoPrintCR.
   867 			('Processor [info]: caught (and ignored) signal (', ex creator printString, ')') infoPrintCR.
   867                     ex proceed.
   868 			ex return
   868                 ].
   869 		     ].
   869                 "/ MiniDebugger enter. -- should this be done when some --debug/--verbose was given?
       
   870                 ex proceed.
       
   871             ].
       
   872 
       
   873             ('Processor [info]: caught (and ignored) signal (', ex creator printString, ')') infoPrintCR.
       
   874             ex return
       
   875          ].
   870 
   876 
   871     ignoredSignals := SignalSet
   877     ignoredSignals := SignalSet
   872 			with:HaltInterrupt
   878                         with:HaltInterrupt
   873 			with:TerminateProcessRequest
   879                         with:TerminateProcessRequest
   874 			with:RecursionError
   880                         with:RecursionError
   875 			with:AbortAllOperationRequest.
   881                         with:AbortAllOperationRequest.
   876 
   882 
   877     "/
   883     "/
   878     "/ I made this an extra call to dispatch; this allows recompilation
   884     "/ I made this an extra call to dispatch; this allows recompilation
   879     "/  of the dispatch-handling code in the running system.
   885     "/  of the dispatch-handling code in the running system.
   880     "/
   886     "/
   881     [dispatching] whileTrue:[
   887     [dispatching] whileTrue:[
   882 	ignoredSignals handle:handlerAction do:dispatchAction
   888         ignoredSignals 
       
   889             handle:handlerAction 
       
   890             do:dispatchAction
   883     ].
   891     ].
   884 
   892 
   885     "/ we arrive here in standalone Apps,
   893     "/ we arrive here in standalone Apps,
   886     "/ when the last process at or above UserSchedulingPriority process died.
   894     "/ when the last process at or above UserSchedulingPriority process died.
   887     "/ regular ST/X stays in above loop forever
   895     "/ regular ST/X stays in above loop forever
  1131      what to do now."
  1139      what to do now."
  1132 
  1140 
  1133     gotChildSignalInterrupt := true.
  1141     gotChildSignalInterrupt := true.
  1134     interruptCounter := interruptCounter + 1 bitAnd:SmallInteger maxVal.
  1142     interruptCounter := interruptCounter + 1 bitAnd:SmallInteger maxVal.
  1135     activeProcess ~~ scheduler ifTrue:[
  1143     activeProcess ~~ scheduler ifTrue:[
  1136         interruptCounter := interruptCounter + 1 bitAnd:SmallInteger maxVal.
  1144 	interruptCounter := interruptCounter + 1 bitAnd:SmallInteger maxVal.
  1137         interruptedProcess := activeProcess.
  1145 	interruptedProcess := activeProcess.
  1138         self threadSwitch:scheduler
  1146 	self threadSwitch:scheduler
  1139     ]
  1147     ]
  1140 
  1148 
  1141     "Modified: 12.4.1996 / 10:12:18 / stefan"
  1149     "Modified: 12.4.1996 / 10:12:18 / stefan"
  1142 !
  1150 !
  1143 
  1151 
  1209     OperatingSystem enableChildSignalInterrupts.        "/ no-op in windows
  1217     OperatingSystem enableChildSignalInterrupts.        "/ no-op in windows
  1210     wasBlocked := OperatingSystem blockInterrupts.
  1218     wasBlocked := OperatingSystem blockInterrupts.
  1211     "/ start the OS-Process
  1219     "/ start the OS-Process
  1212     pid := aBlockReturningPid value.
  1220     pid := aBlockReturningPid value.
  1213     pid notNil ifTrue:[
  1221     pid notNil ifTrue:[
  1214         osChildExitActions at:pid put:actionBlock.
  1222 	osChildExitActions at:pid put:actionBlock.
  1215     ].
  1223     ].
  1216     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1224     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1217     ^ pid
  1225     ^ pid
  1218 
  1226 
  1219     "Created: / 25.3.1997 / 10:54:56 / stefan"
  1227     "Created: / 25.3.1997 / 10:54:56 / stefan"
  1285     activeProcess := aProcess.
  1293     activeProcess := aProcess.
  1286     activeProcessId := id.
  1294     activeProcessId := id.
  1287 
  1295 
  1288     "
  1296     "
  1289      no interrupts now - activeProcess has already been changed
  1297      no interrupts now - activeProcess has already been changed
  1290      (dont add any message sends here)
  1298      (don't add any message sends here)
  1291     "
  1299     "
  1292 "/    ok := self threadSwitchFrom:oldProcess to:aProcess id:id singleStep:singleStep.
  1300 "/    ok := self threadSwitchFrom:oldProcess to:aProcess id:id singleStep:singleStep.
  1293 %{
  1301 %{
  1294     extern OBJ ___threadSwitch();
  1302     extern OBJ ___threadSwitch();
  1295 
  1303 
  1296     if (__isSmallInteger(id)) {
  1304     if (__isSmallInteger(id)) {
  1297 	ok = ___threadSwitch(__context, __intVal(id), (singleStep == true) ? 1 : 0, 0);
  1305         ok = ___threadSwitch(__context, __intVal(id), (singleStep == true) ? 1 : 0, 0);
  1298     } else {
  1306     } else {
  1299 	ok = false;
  1307         ok = false;
  1300     }
  1308     }
  1301 %}.
  1309 %}.
  1302 
  1310 
  1303     "time passes spent in some other process ...
  1311     "time passes spent in some other process ...
  1304      ... here again"
  1312      ... here again"
  1306     p := activeProcess.
  1314     p := activeProcess.
  1307     activeProcess := oldProcess.
  1315     activeProcess := oldProcess.
  1308     activeProcessId := oldId.
  1316     activeProcessId := oldId.
  1309     currentPriority := oldProcess priority.
  1317     currentPriority := oldProcess priority.
  1310 
  1318 
  1311     ok == true ifFalse:[
  1319     ok ~~ true ifTrue:[
  1312 	"
  1320         "
  1313 	 switch failed for some reason -
  1321          switch failed for some reason -
  1314 	 destroy (hard-terminate) the bad process.
  1322          destroy (hard-terminate) the bad process.
  1315 	 This happens when:
  1323          This happens when:
  1316 	 - the stack went above the absolute limit
  1324          - the stack went above the absolute limit
  1317 	   (VM switches back to scheduler)
  1325            (VM switches back to scheduler)
  1318 	 - a halted process cannot execute its interrupt
  1326          - a halted process cannot execute its interrupt
  1319 	   actions (win32 only)
  1327            actions (win32 only)
  1320 	"
  1328         "
  1321 	(id := p id) ~~ SysProcessId ifTrue:[
  1329         id := p id.
  1322 	    id notNil ifTrue:[
  1330         (id ~~ SysProcessId and:[id notNil]) ifTrue:[
  1323 		'Processor [warning]: problem with process ' errorPrint.
  1331             'Processor [warning]: problem with process ' errorPrint.
  1324 		id errorPrint.
  1332             id errorPrint.
  1325 		(nm := p name) notNil ifTrue:[
  1333             (nm := p name) notNil ifTrue:[
  1326 		    ' (' errorPrint. nm errorPrint. ')' errorPrint.
  1334                 ' (' errorPrint. nm errorPrint. ')' errorPrint.
  1327 		].
  1335             ].
  1328 
  1336 
  1329 		ok == #halted ifTrue:[
  1337             ok == #halted ifTrue:[
  1330 		    "/ that process was halted (win32 only)
  1338                 "/ that process was halted (win32 only)
  1331 		    p state:#halted.
  1339                 p state:#halted.
  1332 		   '; stopped it.' errorPrintCR.
  1340                '; stopped it.' errorPrintCR.
  1333 		   self suspend:p.
  1341                self suspend:p.
  1334 		] ifFalse:[
  1342             ] ifFalse:[
  1335 		   '; hard-terminate it.' errorPrintCR.
  1343                '; hard-terminate it.' errorPrintCR.
  1336 		   'Processor [info]: cleanup may take a while if stack is huge' infoPrintCR.
  1344                'Processor [info]: cleanup may take a while if stack is huge' infoPrintCR.
  1337 		   p state:#cleanup.
  1345                p state:#cleanup.
  1338 		   self terminateNoSignal:p.
  1346                self terminateNoSignal:p.
  1339 		]
  1347             ]
  1340 	    ]
  1348         ]
  1341 	]
       
  1342     ].
  1349     ].
  1343     zombie notNil ifTrue:[
  1350     zombie notNil ifTrue:[
  1344 	self class threadDestroy:zombie.
  1351         self class threadDestroy:zombie.
  1345 	zombie := nil
  1352         zombie := nil
  1346     ].
  1353     ].
  1347     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1354     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1348 
  1355 
  1349     "Modified: / 23-07-2010 / 10:32:11 / cg"
  1356     "Modified: / 23-07-2010 / 10:32:11 / cg"
  1350 ! !
  1357 ! !
  1547     "
  1554     "
  1548 
  1555 
  1549     "Modified: 17.4.1997 / 12:59:33 / stefan"
  1556     "Modified: 17.4.1997 / 12:59:33 / stefan"
  1550 !
  1557 !
  1551 
  1558 
       
  1559 anyScheduledWindowGroupAtAll
       
  1560     "return true, if there is any window group with active topviews.
       
  1561      This is used to determine if we should stop scheduling
       
  1562      in standAlone applications."
       
  1563 
       
  1564     Screen notNil ifTrue:[
       
  1565         Screen allScreens notEmptyOrNil ifTrue:[
       
  1566             WindowGroup scheduledWindowGroups notEmptyOrNil ifTrue:[^ true]. 
       
  1567         ].
       
  1568     ].
       
  1569     ^ false
       
  1570 
       
  1571     "
       
  1572      Processor anyScheduledWindowGroupAtAll
       
  1573     "
       
  1574 !
       
  1575 
  1552 anyUserProcessAtAll
  1576 anyUserProcessAtAll
  1553     "return true, if there is any user process still running,
  1577     "return true, if there is any user process still running,
  1554      or waiting on a semaphore.
  1578      or waiting on a semaphore.
  1555      This is used to determine if we should stop scheduling
  1579      This is used to determine if we should stop scheduling
  1556      in standAlone applications.
  1580      in standAlone applications.
  1557      A user process has a non-zero processGroup."
  1581      A user process has a non-zero processGroup.
  1558 
  1582      Should be called with interrupts blocked."
  1559     |listArray l prio "{ Class: SmallInteger }"
  1583 
  1560      wasBlocked|
  1584     |listArray l prio "{ Class: SmallInteger }"|
  1561 
  1585 
  1562     prio := HighestPriority.
  1586     prio := HighestPriority.
  1563     wasBlocked := OperatingSystem blockInterrupts.
       
  1564 
  1587 
  1565     listArray := quiescentProcessLists.
  1588     listArray := quiescentProcessLists.
  1566 
  1589 
  1567     [prio >= 1] whileTrue:[
  1590     [prio >= 1] whileTrue:[
  1568 	l := listArray at:prio.
  1591         l := listArray at:prio.
  1569 	l notNil ifTrue:[
  1592         l notNil ifTrue:[
  1570 	    l linksDo:[:aProcess |
  1593             l linksDo:[:aProcess |
  1571 		aProcess isUserProcess ifTrue:[
  1594                 aProcess isUserProcess ifTrue:[
  1572 		    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1595                     "/ 'anyUserProcess: found quiescent ' _errorPrint. aProcess asString _errorPrintCR.
  1573 		    ^ true.
  1596                     ^ true.
  1574 		]
  1597                 ]
  1575 	    ]
  1598             ]
  1576 	].
  1599         ].
  1577 	prio := prio - 1
  1600         prio := prio - 1
  1578     ].
  1601     ].
  1579 
  1602 
       
  1603     (scheduledProcesses notNil 
       
  1604     and:[scheduledProcesses contains:[:p | p notNil and:[p isUserProcess and:[p state ~~ #dead]] ]]) ifTrue:[
       
  1605        "/ 'anyUserProcess: found scheduled ' _errorPrint. 
       
  1606        "/ (scheduledProcesses detect:[:p | p notNil and:[p isUserProcess and:[p state ~~ #dead]] ]) asString _errorPrintCR.
       
  1607         ^ true.
       
  1608     ].    
       
  1609         
  1580     "/ any user process waiting on a sema?
  1610     "/ any user process waiting on a sema?
  1581     (readSemaphoreArray contains:[:sema |
  1611     (readSemaphoreArray contains:[:sema |
  1582 	sema notNil and:[sema waitingProcesses contains:[:p | p notNil and:[p isUserProcess] ]]]
  1612         sema notNil and:[sema waitingProcesses contains:[:p | p notNil and:[p isUserProcess and:[p state ~~ #dead]] ]]]
  1583     ) ifTrue:[
  1613     ) ifTrue:[
  1584 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1614        "/ 'anyUserProcess: found on read sema' _errorPrintCR.
  1585 	^ true.
  1615         ^ true.
  1586     ].
  1616     ].
  1587     (writeSemaphoreArray contains:[:sema |
  1617     (writeSemaphoreArray contains:[:sema |
  1588 	sema notNil and:[sema waitingProcesses contains:[:p | p notNil and:[p isUserProcess] ]]]
  1618         sema notNil and:[sema waitingProcesses contains:[:p | p notNil and:[p isUserProcess and:[p state ~~ #dead]] ]]]
  1589     ) ifTrue:[
  1619     ) ifTrue:[
  1590 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1620        "/ 'anyUserProcess: found on write sema' _errorPrintCR.
  1591 	^ true.
  1621         ^ true.
  1592     ].
  1622     ].
  1593     (timeoutSemaphoreArray contains:[:sema |
  1623     (timeoutSemaphoreArray contains:[:sema |
  1594 	sema notNil and:[sema waitingProcesses contains:[:p | p notNil and:[p isUserProcess] ]]]
  1624         sema notNil and:[sema waitingProcesses contains:[:p | p notNil and:[p isUserProcess and:[p state ~~ #dead]] ]]]
  1595     ) ifTrue:[
  1625     ) ifTrue:[
  1596 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1626        "/ 'anyUserProcess: found on timeout sema' _errorPrintCR.
  1597 	^ true.
  1627         ^ true.
  1598     ].
  1628     ].
  1599     (timeoutProcessArray contains:[:p | p notNil and:[p isUserProcess] ]
  1629     (timeoutProcessArray contains:[:p | p notNil and:[p isUserProcess] ]
  1600     ) ifTrue:[
  1630     ) ifTrue:[
  1601 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1631         ^ true.
  1602 	^ true.
  1632     ].
  1603     ].
  1633 
  1604 
       
  1605     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
       
  1606     ^ false
  1634     ^ false
  1607 
  1635 
  1608     "
  1636     "
  1609      Processor anyUserProcessAtAll
  1637      Processor anyUserProcessAtAll
  1610     "
  1638     "
  1909 suspend:aProcess
  1937 suspend:aProcess
  1910     "remove the argument, aProcess from the list of runnable processes.
  1938     "remove the argument, aProcess from the list of runnable processes.
  1911      If the process is the current one, reschedule.
  1939      If the process is the current one, reschedule.
  1912 
  1940 
  1913      Notice:
  1941      Notice:
  1914 	 This method should only be called by Process>>suspend or
  1942          This method should only be called by Process>>suspend or
  1915 	 Process>>suspendWithState:"
  1943          Process>>suspendWithState:"
  1916 
  1944 
  1917     |pri l p wasBlocked|
  1945     |pri l p wasBlocked|
  1918 
  1946 
  1919     "
  1947     "
  1920      some debugging stuff
  1948      some debugging stuff
  1921     "
  1949     "
  1922     aProcess isNil ifTrue:[
  1950     aProcess isNil ifTrue:[
  1923 	InvalidProcessSignal raiseRequestWith:aProcess errorString:'nil suspend'.
  1951         InvalidProcessSignal raiseRequestWith:aProcess errorString:'nil suspend'.
  1924 	^ self
  1952         ^ self
  1925     ].
  1953     ].
  1926     aProcess isDead ifTrue:[
  1954     aProcess isDead ifTrue:[
  1927 	InvalidProcessSignal raiseRequestWith:aProcess errorString:'bad suspend: already dead'.
  1955         InvalidProcessSignal raiseRequestWith:aProcess errorString:'bad suspend: already dead'.
  1928 	self threadSwitch:scheduler.
  1956         self threadSwitch:scheduler.
  1929 	^ self
  1957         ^ self
  1930     ].
  1958     ].
  1931     aProcess == scheduler ifTrue:[
  1959     aProcess == scheduler ifTrue:[
  1932 	"only the scheduler may suspend itself"
  1960         "only the scheduler may suspend itself"
  1933 	activeProcess == scheduler ifTrue:[
  1961         activeProcess == scheduler ifTrue:[
  1934 	    suspendScheduler := true.
  1962             suspendScheduler := true.
  1935 	    [suspendScheduler] whileTrue:[
  1963             [suspendScheduler] whileTrue:[
  1936 		self dispatch.
  1964                 self dispatch.
  1937 	    ].
  1965             ].
  1938 	    ^ self
  1966             ^ self
  1939 	].
  1967         ].
  1940 
  1968 
  1941 	InvalidProcessSignal raiseRequestWith:aProcess errorString:'attempt to suspend scheduler'.
  1969         InvalidProcessSignal raiseRequestWith:aProcess errorString:'attempt to suspend scheduler'.
  1942 	^ self
  1970         ^ self
  1943     ].
  1971     ].
  1944 
  1972 
  1945     aProcess hasInterruptActions ifTrue:[
  1973     (aProcess == activeProcess) ifTrue:[
  1946 	aProcess interrupt.
  1974         "this is a no-op if the process has no interrupt actions"
       
  1975         aProcess interrupt.
  1947     ].
  1976     ].
  1948 
  1977 
  1949     wasBlocked := OperatingSystem blockInterrupts.
  1978     wasBlocked := OperatingSystem blockInterrupts.
  1950 
  1979 
  1951     pri := aProcess priority.
  1980     pri := aProcess priority.
  1953 
  1982 
  1954     "notice: this is slightly faster than putting the if-code into
  1983     "notice: this is slightly faster than putting the if-code into
  1955      the ifAbsent block, because [] is a shared cheap block, created at compile time
  1984      the ifAbsent block, because [] is a shared cheap block, created at compile time
  1956     "
  1985     "
  1957     (l isNil or:[(l removeIdentical:aProcess ifAbsent:nil) isNil]) ifTrue:[
  1986     (l isNil or:[(l removeIdentical:aProcess ifAbsent:nil) isNil]) ifTrue:[
  1958 	"/ 'Processor [warning]: bad suspend: process is not running' errorPrintCR.
  1987         "/ 'Processor [warning]: bad suspend: process is not running' errorPrintCR.
  1959 	"/ MiniDebugger enterWithMessage:'bad suspend: process is not running'.
  1988         "/ MiniDebugger enterWithMessage:'bad suspend: process is not running'.
  1960 	aProcess == activeProcess ifTrue:[
  1989         aProcess == activeProcess ifTrue:[
  1961 	    self threadSwitch:scheduler.
  1990             self threadSwitch:scheduler.
  1962 	].
  1991         ].
  1963 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1992         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1964 	^ self
  1993         ^ self
  1965     ].
  1994     ].
  1966 
  1995 
  1967     (aProcess == activeProcess) ifTrue:[
  1996     (aProcess == activeProcess) ifTrue:[
  1968 	"we can immediately switch sometimes"
  1997         "we can immediately switch sometimes"
  1969 	l isEmpty ifTrue:[
  1998         l isEmpty ifTrue:[
  1970 	    p := scheduler
  1999             p := scheduler
  1971 	] ifFalse:[
  2000         ] ifFalse:[
  1972 	    p := l firstLink
  2001             p := l firstLink
  1973 	].
  2002         ].
  1974 	self threadSwitch:p
  2003         self threadSwitch:p
  1975     ].
  2004     ].
  1976 
  2005 
  1977     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2006     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  1978 
  2007 
  1979     "Modified: / 23.9.1996 / 13:49:24 / stefan"
  2008     "Modified: / 23.9.1996 / 13:49:24 / stefan"
  2015      (see zombie handling)"
  2044      (see zombie handling)"
  2016 
  2045 
  2017     |pri id l wasBlocked|
  2046     |pri id l wasBlocked|
  2018 
  2047 
  2019     aProcess isNil ifTrue:[^ self].
  2048     aProcess isNil ifTrue:[^ self].
       
  2049 
  2020     aProcess == scheduler ifTrue:[
  2050     aProcess == scheduler ifTrue:[
  2021 	InvalidProcessSignal raiseWith:aProcess errorString:'attempt to terminate scheduler'.
  2051         InvalidProcessSignal raiseWith:aProcess errorString:'attempt to terminate scheduler'.
  2022 	^ self
  2052         ^ self
  2023     ].
  2053     ].
  2024 
  2054 
  2025     wasBlocked := OperatingSystem blockInterrupts.
  2055     wasBlocked := OperatingSystem blockInterrupts.
  2026 
  2056 
  2027     id := aProcess id.
  2057     id := aProcess id.
  2028     id isNil ifTrue:[   "already dead"
  2058     id isNil ifTrue:[   "already dead"
  2029 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2059         self checkForEndOfDispatch.
  2030 	^ self
  2060         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
       
  2061         ^ self
  2031     ].
  2062     ].
  2032 
  2063 
  2033     aProcess setId:nil state:#dead.
  2064     aProcess setId:nil state:#dead.
  2034 
  2065 
  2035     "remove the process from the runnable list"
  2066     "remove the process from the runnable list"
  2036 
  2067 
  2037     pri := aProcess priority.
  2068     pri := aProcess priority.
  2038     l := quiescentProcessLists at:pri.
  2069     l := quiescentProcessLists at:pri.
  2039     l notNil ifTrue:[
  2070     l notNil ifTrue:[
  2040 	(l removeIdentical:aProcess ifAbsent:nil) "notNil ifTrue:[
  2071         (l removeIdentical:aProcess ifAbsent:nil) "notNil ifTrue:[
  2041 	    l isEmpty ifTrue:[
  2072             l isEmpty ifTrue:[
  2042 		quiescentProcessLists at:pri put:nil
  2073                 quiescentProcessLists at:pri put:nil
  2043 	    ]
  2074             ]
  2044 	]."
  2075         ]."
  2045     ].
  2076     ].
  2046 
  2077 
  2047     aProcess == activeProcess ifTrue:[
  2078     aProcess == activeProcess ifTrue:[
  2048 	"
  2079         "
  2049 	 hard case - it's the currently running process
  2080          hard case - it's the currently running process
  2050 	 we must have the next active process destroy this one
  2081          we must have the next active process destroy this one
  2051 	 (we cannot destroy the chair we are sitting on ... :-)
  2082          (we cannot destroy the chair we are sitting on ... :-)
  2052 	"
  2083         "
  2053 	zombie notNil ifTrue:[
  2084         zombie notNil ifTrue:[
  2054 	    self error:'active process is zombie' mayProceed:true.
  2085             self error:'active process is zombie' mayProceed:true.
  2055 	    self class threadDestroy:zombie.
  2086             self class threadDestroy:zombie.
  2056 	].
  2087         ].
  2057 
  2088 
  2058 	self unRemember:aProcess.
  2089         self unRemember:aProcess.
  2059 	zombie := id.
  2090         zombie := id.
  2060 
  2091 
  2061 	wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2092         self checkForEndOfDispatch.
  2062 	self threadSwitch:scheduler.
  2093         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2063 	"not reached"
  2094         self threadSwitch:scheduler.
  2064 	^ self
  2095         "not reached"
       
  2096         ^ self
  2065     ].
  2097     ].
  2066 
  2098 
  2067     self unRemember:aProcess.
  2099     self unRemember:aProcess.
  2068     self class threadDestroy:id.
  2100     self class threadDestroy:id.
  2069 
  2101 
       
  2102     self checkForEndOfDispatch.
  2070     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2103     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2071 
  2104 
  2072     "Modified: / 23-09-1996 / 13:50:24 / stefan"
  2105     "Modified: / 23-09-1996 / 13:50:24 / stefan"
  2073     "Modified: / 20-03-1997 / 16:03:39 / cg"
  2106     "Modified: / 20-03-1997 / 16:03:39 / cg"
  2074     "Modified (comment): / 10-08-2011 / 19:57:08 / cg"
  2107     "Modified (comment): / 10-08-2011 / 19:57:08 / cg"
  2309     |myDelay t flipFlop|
  2342     |myDelay t flipFlop|
  2310 
  2343 
  2311     myDelay := Delay forMilliseconds:(t := TimeSliceInterval).
  2344     myDelay := Delay forMilliseconds:(t := TimeSliceInterval).
  2312     flipFlop := true.
  2345     flipFlop := true.
  2313 
  2346 
  2314     'Processor [info]: timeslicer started' infoPrintCR.
  2347     Smalltalk verbose ifTrue:[ 'Processor [info]: timeslicer started' infoPrintCR ].
  2315     [
  2348     [
  2316 	t ~~ TimeSliceInterval ifTrue:[
  2349         t ~~ TimeSliceInterval ifTrue:[
  2317 	    "/ interval changed -> need a new delay
  2350             "/ interval changed -> need a new delay
  2318 	    myDelay delay:(t := TimeSliceInterval).
  2351             myDelay delay:(t := TimeSliceInterval).
  2319 	].
  2352         ].
  2320 	myDelay wait.
  2353         myDelay wait.
  2321 	self slice.
  2354         self slice.
  2322 
  2355 
  2323 	"/ every other tick, recompute priorities.
  2356         "/ every other tick, recompute priorities.
  2324 	flipFlop := flipFlop not.
  2357         flipFlop := flipFlop not.
  2325 	flipFlop ifTrue:[
  2358         flipFlop ifTrue:[
  2326 	    scheduledProcesses notNil ifTrue:[
  2359             scheduledProcesses notNil ifTrue:[
  2327 		supportDynamicPriorities ifTrue:[
  2360                 supportDynamicPriorities ifTrue:[
  2328 		    self recomputeDynamicPriorities.
  2361                     self recomputeDynamicPriorities.
  2329 		].
  2362                 ].
  2330 		scheduledProcesses clearContents.
  2363                 scheduledProcesses clearContents.
  2331 	    ] ifFalse:[
  2364             ] ifFalse:[
  2332 		scheduledProcesses := IdentitySet new.
  2365                 scheduledProcesses := IdentitySet new.
  2333 	    ].
  2366             ].
  2334 	].
  2367         ].
  2335     ] loop.
  2368     ] loop.
  2336 ! !
  2369 ! !
  2337 
  2370 
  2338 !ProcessorScheduler methodsFor:'semaphore signalling'!
  2371 !ProcessorScheduler methodsFor:'semaphore signalling'!
  2339 
  2372 
  2340 disableFd:aFileDescriptor doSignal:doSignal
  2373 disableFd:aFileDescriptor doSignal:doSignal
  2341     "disable triggering of a semaphore for aFileDescriptor..
  2374     "disable triggering of a semaphore for aFileDescriptor..
  2342      If doSignal is true, the associated semaphore is signaled."
  2375      If doSignal is true, the associated semaphore is signaled.
       
  2376      Answer a collection of semaphores that haven't been signaled."
  2343 
  2377 
  2344     |idx "{ Class: SmallInteger }"
  2378     |idx "{ Class: SmallInteger }"
  2345      wasBlocked sema|
  2379      wasBlocked sema semaCollection|
  2346 
  2380 
  2347     wasBlocked := OperatingSystem blockInterrupts.
  2381     wasBlocked := OperatingSystem blockInterrupts.
  2348     useIOInterrupts ifTrue:[
  2382     useIOInterrupts ifTrue:[
  2349 	OperatingSystem disableIOInterruptsOn:aFileDescriptor.
  2383 	OperatingSystem disableIOInterruptsOn:aFileDescriptor.
  2350     ].
  2384     ].
  2351 
  2385 
  2352     idx := readFdArray identityIndexOf:aFileDescriptor startingAt:1.
  2386     idx := readFdArray indexOf:aFileDescriptor startingAt:1.
  2353     [idx ~~ 0] whileTrue:[
  2387     [idx ~~ 0] whileTrue:[
  2354 	readFdArray at:idx put:nil.
  2388 	readFdArray at:idx put:nil.
  2355 	readCheckArray at:idx put:nil.
  2389 	readCheckArray at:idx put:nil.
  2356 	(sema := readSemaphoreArray at:idx) notNil ifTrue:[
  2390 	(sema := readSemaphoreArray at:idx) notNil ifTrue:[
  2357 	    readSemaphoreArray at:idx put:nil.
  2391 	    readSemaphoreArray at:idx put:nil.
  2358 	    doSignal ifTrue:[
  2392 	    semaCollection isNil ifTrue:[semaCollection := Set new].
  2359 		sema signalForAll.
  2393 	    semaCollection add:sema.
  2360 	    ].
       
  2361 	].
  2394 	].
  2362 	idx := readFdArray identityIndexOf:aFileDescriptor startingAt:idx+1.
  2395 	idx := readFdArray indexOf:aFileDescriptor startingAt:idx+1.
  2363     ].
  2396     ].
  2364     idx := writeFdArray identityIndexOf:aFileDescriptor startingAt:1.
  2397     idx := writeFdArray indexOf:aFileDescriptor startingAt:1.
  2365     [idx ~~ 0] whileTrue:[
  2398     [idx ~~ 0] whileTrue:[
  2366 	writeFdArray at:idx put:nil.
  2399 	writeFdArray at:idx put:nil.
  2367 	writeCheckArray at:idx put:nil.
  2400 	writeCheckArray at:idx put:nil.
  2368 	(sema := writeSemaphoreArray at:idx) notNil ifTrue:[
  2401 	(sema := writeSemaphoreArray at:idx) notNil ifTrue:[
  2369 	    writeSemaphoreArray at:idx put:nil.
  2402 	    writeSemaphoreArray at:idx put:nil.
  2370 	    doSignal ifTrue:[
  2403 	    semaCollection isNil ifTrue:[semaCollection := Set new].
  2371 		sema signalForAll.
  2404 	    semaCollection add:sema.
  2372 	    ].
       
  2373 	].
  2405 	].
  2374 	idx := writeFdArray identityIndexOf:aFileDescriptor startingAt:idx+1.
  2406 	idx := writeFdArray indexOf:aFileDescriptor startingAt:idx+1.
  2375     ].
  2407     ].
  2376     idx := exceptFdArray identityIndexOf:aFileDescriptor startingAt:1.
  2408     idx := exceptFdArray indexOf:aFileDescriptor startingAt:1.
  2377     [idx ~~ 0] whileTrue:[
  2409     [idx ~~ 0] whileTrue:[
  2378 	exceptFdArray at:idx put:nil.
  2410 	exceptFdArray at:idx put:nil.
  2379 	(sema := exceptSemaphoreArray at:idx) notNil ifTrue:[
  2411 	(sema := exceptSemaphoreArray at:idx) notNil ifTrue:[
  2380 	    exceptSemaphoreArray at:idx put:nil.
  2412 	    exceptSemaphoreArray at:idx put:nil.
  2381 	    doSignal ifTrue:[
  2413 	    semaCollection isNil ifTrue:[semaCollection := Set new].
  2382 		sema signalForAll.
  2414 	    semaCollection add:sema.
       
  2415 	].
       
  2416 	idx := exceptFdArray indexOf:aFileDescriptor startingAt:idx+1.
       
  2417     ].
       
  2418 
       
  2419     semaCollection isNil ifTrue:[
       
  2420 	semaCollection := #().
       
  2421     ] ifFalse:[
       
  2422 	doSignal ifTrue:[
       
  2423 	    semaCollection do:[:eachSema|
       
  2424 		eachSema signalForAll.
       
  2425 		semaCollection := #().
  2383 	    ].
  2426 	    ].
  2384 	].
  2427 	].
  2385 	idx := exceptFdArray identityIndexOf:aFileDescriptor startingAt:idx+1.
       
  2386     ].
  2428     ].
  2387     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2429     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
       
  2430     ^ semaCollection
  2388 !
  2431 !
  2389 
  2432 
  2390 disableSemaphore:aSemaphore
  2433 disableSemaphore:aSemaphore
  2391     "disable triggering of a semaphore"
  2434     "disable triggering of a semaphore"
  2392 
  2435 
  2395 
  2438 
  2396     wasBlocked := OperatingSystem blockInterrupts.
  2439     wasBlocked := OperatingSystem blockInterrupts.
  2397     idx := 0.
  2440     idx := 0.
  2398     [idx := readSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2441     [idx := readSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2399      idx ~~ 0] whileTrue:[
  2442      idx ~~ 0] whileTrue:[
  2400         useIOInterrupts ifTrue:[
  2443 	useIOInterrupts ifTrue:[
  2401             fd := readFdArray at:idx.
  2444 	    fd := readFdArray at:idx.
  2402             fd notNil ifTrue:[
  2445 	    fd notNil ifTrue:[
  2403                 OperatingSystem disableIOInterruptsOn:fd
  2446 		OperatingSystem disableIOInterruptsOn:fd
  2404             ].
  2447 	    ].
  2405         ].
  2448 	].
  2406         readFdArray at:idx put:nil.
  2449 	readFdArray at:idx put:nil.
  2407         readSemaphoreArray at:idx put:nil.
  2450 	readSemaphoreArray at:idx put:nil.
  2408         readCheckArray at:idx put:nil.
  2451 	readCheckArray at:idx put:nil.
  2409     ].
  2452     ].
  2410     idx := 0.
  2453     idx := 0.
  2411     [idx := writeSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2454     [idx := writeSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2412      idx ~~ 0] whileTrue:[
  2455      idx ~~ 0] whileTrue:[
  2413         useIOInterrupts ifTrue:[
  2456 	useIOInterrupts ifTrue:[
  2414             fd := writeFdArray at:idx.
  2457 	    fd := writeFdArray at:idx.
  2415             fd notNil ifTrue:[
  2458 	    fd notNil ifTrue:[
  2416                 OperatingSystem disableIOInterruptsOn:fd
  2459 		OperatingSystem disableIOInterruptsOn:fd
  2417             ].
  2460 	    ].
  2418         ].
  2461 	].
  2419         writeFdArray at:idx put:nil.
  2462 	writeFdArray at:idx put:nil.
  2420         writeSemaphoreArray at:idx put:nil.
  2463 	writeSemaphoreArray at:idx put:nil.
  2421         writeCheckArray at:idx put:nil.
  2464 	writeCheckArray at:idx put:nil.
  2422     ].
  2465     ].
  2423     idx := 0.
  2466     idx := 0.
  2424     [idx := exceptSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2467     [idx := exceptSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1.
  2425      idx ~~ 0] whileTrue:[
  2468      idx ~~ 0] whileTrue:[
  2426         exceptFdArray at:idx put:nil.
  2469 	exceptFdArray at:idx put:nil.
  2427         exceptSemaphoreArray at:idx put:nil.
  2470 	exceptSemaphoreArray at:idx put:nil.
  2428     ].
  2471     ].
  2429     self removeTimeoutForSemaphore:aSemaphore.
  2472     self removeTimeoutForSemaphore:aSemaphore.
  2430     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2473     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2431 
  2474 
  2432     "Modified: 4.8.1997 / 15:19:33 / cg"
  2475     "Modified: 4.8.1997 / 15:19:33 / cg"
  2902 
  2945 
  2903     "Modified: 23.9.1996 / 14:34:18 / cg"
  2946     "Modified: 23.9.1996 / 14:34:18 / cg"
  2904 !
  2947 !
  2905 
  2948 
  2906 addTimedBlock:aBlock for:aProcess atMilliseconds:aMillisecondTime
  2949 addTimedBlock:aBlock for:aProcess atMilliseconds:aMillisecondTime
  2907     "add the argument, aBlock to the list of time-scheduled-blocks; to be
  2950     "add the argument, aBlock to the list of time-scheduled-blocks; 
  2908      evaluated by aProcess when the millisecondClock value passes
  2951      to be evaluated by aProcess when the millisecondClock value passes
  2909      aMillisecondTime.
  2952      aMillisecondTime.
  2910      If that block is already in the timeout list,
  2953      If that block is already in the timeout list, its trigger-time is changed.
  2911      its trigger-time is changed.
  2954      The process specified by the argument, aProcess 
  2912      The process specified by the argument, aProcess will be interrupted
  2955      will be interrupted for execution of the block.
  2913      for execution of the block.
       
  2914      If aProcess is nil, the block will be evaluated by the scheduler itself
  2956      If aProcess is nil, the block will be evaluated by the scheduler itself
  2915      (which is dangerous - the block should not raise any error conditions).
  2957      (which is dangerous: the block should not raise any error conditions).
  2916      If the process is active at trigger time, the interrupt will occur in
  2958      If the process is active at trigger time, the interrupt will occur in
  2917      whatever method it is executing; if suspended at trigger time, it will be
  2959      whatever method it is executing; 
  2918      resumed.
  2960      if suspended at trigger time, it will be resumed.
  2919      The block will be removed from the timed-block list after evaluation
  2961      The block will be removed from the timed-block list after evaluation
  2920      (i.e. it will trigger only once).
  2962      (i.e. it will trigger only once).
  2921      Returns an ID, which can be used in #removeTimeoutWidthID:"
  2963      Returns an ID, which can be used in #removeTimeoutWidthID:"
  2922 
  2964 
  2923     |index "{ Class: SmallInteger }"
  2965     |index "{ Class: SmallInteger }"
  2924      wasBlocked|
  2966      wasBlocked|
  2925 
  2967 
  2926     wasBlocked := OperatingSystem blockInterrupts.
  2968     wasBlocked := OperatingSystem blockInterrupts.
  2927     index := timeoutActionArray identityIndexOf:aBlock startingAt:1.
  2969     index := timeoutActionArray identityIndexOf:aBlock startingAt:1.
  2928     index ~~ 0 ifTrue:[
  2970     index ~~ 0 ifTrue:[
  2929 	timeoutArray at:index put:aMillisecondTime
  2971         timeoutArray at:index put:aMillisecondTime
  2930     ] ifFalse:[
  2972     ] ifFalse:[
  2931 	index := timeoutArray indexOf:nil.
  2973         index := timeoutArray indexOf:nil.
  2932 	index ~~ 0 ifTrue:[
  2974         index ~~ 0 ifTrue:[
  2933 	    timeoutArray at:index put:aMillisecondTime.
  2975             timeoutArray at:index put:aMillisecondTime.
  2934 	    timeoutActionArray at:index put:aBlock.
  2976             timeoutActionArray at:index put:aBlock.
  2935 	    timeoutSemaphoreArray at:index put:nil.
  2977             timeoutSemaphoreArray at:index put:nil.
  2936 	    timeoutProcessArray at:index put:aProcess
  2978             timeoutProcessArray at:index put:aProcess
  2937 	] ifFalse:[
  2979         ] ifFalse:[
  2938 	    timeoutArray := timeoutArray copyWith:aMillisecondTime.
  2980             timeoutArray := timeoutArray copyWith:aMillisecondTime.
  2939 	    timeoutActionArray := timeoutActionArray copyWith:aBlock.
  2981             timeoutActionArray := timeoutActionArray copyWith:aBlock.
  2940 	    timeoutSemaphoreArray := timeoutSemaphoreArray copyWith:nil.
  2982             timeoutSemaphoreArray := timeoutSemaphoreArray copyWith:nil.
  2941 	    timeoutProcessArray := timeoutProcessArray copyWith:aProcess.
  2983             timeoutProcessArray := timeoutProcessArray copyWith:aProcess.
  2942 	    index := timeoutArray size.
  2984             index := timeoutArray size.
  2943 	].
  2985         ].
  2944     ].
  2986     ].
  2945 
  2987 
  2946     anyTimeouts := true.
  2988     anyTimeouts := true.
  2947     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2989     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  2948     ^ index
  2990     ^ index
  3042                 ] ifFalse:[
  3084                 ] ifFalse:[
  3043                     "to support pure-events"
  3085                     "to support pure-events"
  3044                     block := timeoutActionArray at:index.
  3086                     block := timeoutActionArray at:index.
  3045                     block notNil ifTrue:[
  3087                     block notNil ifTrue:[
  3046                         "/ usually (>99%), there is only one single timeout action to call;
  3088                         "/ usually (>99%), there is only one single timeout action to call;
  3047                         "/ avoid creation of an OrderedCollection 
  3089                         "/ avoid creation of an OrderedCollection
  3048                         firstBlockToEvaluate isNil ifTrue:[
  3090                         firstBlockToEvaluate isNil ifTrue:[
  3049                             firstBlockToEvaluate := block.
  3091                             firstBlockToEvaluate := block.
  3050                             firstProcess := timeoutProcessArray at:index.
  3092                             firstProcess := timeoutProcessArray at:index.
  3051                         ] ifFalse:[
  3093                         ] ifFalse:[
  3052                             blocksAndProcessesToEvaluate isNil ifTrue:[
  3094                             blocksAndProcessesToEvaluate isNil ifTrue:[
  3084             wasBlocked ifFalse:[ OperatingSystem unblockInterrupts ].
  3126             wasBlocked ifFalse:[ OperatingSystem unblockInterrupts ].
  3085         ].
  3127         ].
  3086     ].
  3128     ].
  3087 
  3129 
  3088     "/ usually (>99%), there is only one single timeout action to call;
  3130     "/ usually (>99%), there is only one single timeout action to call;
  3089     "/ above code avoided the creation of an OrderedCollection 
  3131     "/ above code avoided the creation of an OrderedCollection
  3090     blocksAndProcessesToEvaluate isNil ifTrue:[
  3132     blocksAndProcessesToEvaluate isNil ifTrue:[
  3091         firstBlockToEvaluate notNil ifTrue:[
  3133         firstBlockToEvaluate notNil ifTrue:[
  3092             timedActionCounter := (timedActionCounter + 1 bitAnd:SmallInteger maxVal).
  3134             timedActionCounter := (timedActionCounter + 1 bitAnd:SmallInteger maxVal).
  3093             (firstProcess isNil or:[firstProcess == scheduler or:[PureEventDriven]]) ifTrue:[
  3135             (firstProcess isNil or:[firstProcess == scheduler or:[PureEventDriven]]) ifTrue:[
  3094                 firstBlockToEvaluate value
  3136                 firstBlockToEvaluate value
  3095             ] ifFalse:[
  3137             ] ifFalse:[
  3096                 firstProcess isDead ifTrue:[
  3138                 firstProcess isDead ifTrue:[
  3097                     "/ a timedBlock for a process which has already terminated
  3139                     "/ a timedBlock for a process which has already terminated
  3098                     "/ issue a warning and do not execute it.
  3140                     "/ issue a warning and do not execute it.
  3099                     "/ (exeuting here may be dangerous, since it would run at scheduler priority here,
  3141                     "/ (executing here may be dangerous, since it would run at scheduler priority here,
  3100                     "/  and thereby could block the whole smalltalk system.
  3142                     "/  and thereby could block the whole smalltalk system.
  3101                     "/  For this reason is it IGNORED here.)
  3143                     "/  For this reason is it IGNORED here.)
  3102 "/ Could handle it in timeoutProcess, but we don't,
  3144 
  3103 "/ because otherwise timeouts might be reissued forever...
  3145                     "/ Could handle it in timeoutProcess, but we don't,
  3104 "/                    (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[
  3146                     "/ because otherwise timeouts might be reissued forever...
  3105 "/                        timeoutHandlerProcess interruptWith:block.
  3147                     "/      (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[
  3106 "/                    ] ifFalse:[
  3148                     "/          timeoutHandlerProcess interruptWith:block.
  3107                         ('ProcessorScheduler [warning]: cannot evaluate timedBlock (', firstBlockToEvaluate displayString, ') for dead process: ''' , firstProcess name , '''') infoPrintCR.
  3149                     "/      ] ifFalse:[
  3108 "/                    ].
  3150                         ('ProcessorScheduler [warning]: cannot evaluate timedBlock (', firstBlockToEvaluate displayString, ') for dead process: ''' , firstProcess name , '''') errorPrintCR.
       
  3151                     "/      ].
  3109                 ] ifFalse:[
  3152                 ] ifFalse:[
  3110                     firstProcess interruptWith:firstBlockToEvaluate
  3153                     firstProcess interruptWith:firstBlockToEvaluate
  3111                 ]
  3154                 ]
  3112             ]
  3155             ]
  3113         ].
  3156         ].
  3121                 timedActionCounter := (timedActionCounter + 1 bitAnd:SmallInteger maxVal).
  3164                 timedActionCounter := (timedActionCounter + 1 bitAnd:SmallInteger maxVal).
  3122             ] ifFalse:[
  3165             ] ifFalse:[
  3123                 p isDead ifTrue:[
  3166                 p isDead ifTrue:[
  3124                     "/ a timedBlock for a process which has already terminated
  3167                     "/ a timedBlock for a process which has already terminated
  3125                     "/ issue a warning and do not execute it.
  3168                     "/ issue a warning and do not execute it.
  3126                     "/ (exeuting here may be dangerous, since it would run at scheduler priority here,
  3169                     "/ (executing here may be dangerous, since it would run at scheduler priority here,
  3127                     "/  and thereby could block the whole smalltalk system.
  3170                     "/  and thereby could block the whole smalltalk system.
  3128                     "/  For this reason is it IGNORED here.)
  3171                     "/  For this reason is it IGNORED here.)
  3129 "/ Could handle it in timeoutProcess, but we don't,
  3172 
  3130 "/ because otherwise timeouts might be reissued forever...
  3173                     "/ Could handle it in timeoutProcess, but we don't,
  3131 "/                    (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[
  3174                     "/ because otherwise timeouts might be reissued forever...
  3132 "/                        timeoutHandlerProcess interruptWith:block.
  3175                     "/      (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[
  3133 "/                    ] ifFalse:[
  3176                     "/          timeoutHandlerProcess interruptWith:block.
  3134                         ('ProcessorScheduler [warning]: cannot evaluate timedBlock (', block displayString, ') for dead process: ''' , p name , '''') infoPrintCR.
  3177                     "/      ] ifFalse:[
  3135 "/                    ].
  3178                         ('ProcessorScheduler [warning]: cannot evaluate timedBlock (', block displayString, ') for dead process: ''' , p name , '''') errorPrintCR.
       
  3179                     "/      ].
  3136                 ] ifFalse:[
  3180                 ] ifFalse:[
  3137                     timedActionCounter := (timedActionCounter + 1 bitAnd:SmallInteger maxVal).
  3181                     timedActionCounter := (timedActionCounter + 1 bitAnd:SmallInteger maxVal).
  3138                     p interruptWith:block
  3182                     p interruptWith:block
  3139                 ]
  3183                 ]
  3140             ]
  3184             ]
  3171      wasBlocked|
  3215      wasBlocked|
  3172 
  3216 
  3173     wasBlocked := OperatingSystem blockInterrupts.
  3217     wasBlocked := OperatingSystem blockInterrupts.
  3174 
  3218 
  3175     index := 0.
  3219     index := 0.
  3176     [index := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:index+1. 
  3220     [
  3177      index ~~ 0] whileTrue:[
  3221         index := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:index+1.
       
  3222         index ~~ 0
       
  3223     ] whileTrue:[
  3178         timeoutArray at:index put:nil.
  3224         timeoutArray at:index put:nil.
  3179         timeoutSemaphoreArray at:index put:nil.
  3225         timeoutSemaphoreArray at:index put:nil.
  3180         timeoutActionArray at:index put:nil.
  3226         timeoutActionArray at:index put:nil.
  3181         timeoutProcessArray at:index put:nil.
  3227         timeoutProcessArray at:index put:nil.
  3182     ].
  3228     ].
  3261     "The timeoutHandlerProcess does nothing but wait.
  3307     "The timeoutHandlerProcess does nothing but wait.
  3262      It exists only, so that timeout blocks may be executed in its context
  3308      It exists only, so that timeout blocks may be executed in its context
  3263      (i.e. it will always just wait forever, and perform timeout actions
  3309      (i.e. it will always just wait forever, and perform timeout actions
  3264      in its interrupt handler)."
  3310      in its interrupt handler)."
  3265 
  3311 
       
  3312     |mySema|
       
  3313 
       
  3314     mySema := Semaphore new name:'timeoutHandler'.
  3266     [
  3315     [
  3267         [
  3316         [
  3268             (Semaphore new name:'timeoutHandler') wait.
  3317             mySema wait.
  3269         ] on:Exception do:[:ex|
  3318         ] on:Exception do:[:ex|
       
  3319             "/ an error occurred in one of the timeout actions.
       
  3320             
  3270             "ignore errors, but tell the user"
  3321             "ignore errors, but tell the user"
  3271             InfoPrinting == true ifTrue:[
  3322             InfoPrinting == true ifTrue:[
  3272                 ('ProcessorScheduler [warning]: error while handling timeouts in TimeoutHandlerProcess: ''' , ex description , '''') infoPrintCR.
  3323                 ('ProcessorScheduler [warning]: error while handling timeouts in TimeoutHandlerProcess: ''' , ex description , '''') infoPrintCR.
  3273                 thisContext fullPrintAll.
  3324                 thisContext fullPrintAll.
  3274             ].
  3325             ].
  3306     ].
  3357     ].
  3307     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  3358     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
  3308 ! !
  3359 ! !
  3309 
  3360 
  3310 !ProcessorScheduler methodsFor:'waiting'!
  3361 !ProcessorScheduler methodsFor:'waiting'!
       
  3362 
       
  3363 checkForEndOfDispatch
       
  3364     |wasBlocked|
       
  3365     
       
  3366     exitWhenNoMoreUserProcesses ifTrue:[
       
  3367         "/ check if there are any processes at all
       
  3368         "/ stop dispatching if there is none
       
  3369         "/ (and anyTimeouts is false, which means that no timeout blocks are present)
       
  3370         "/ and no readSemaphores are present (which means that noone is waiting for input)
       
  3371         "/ and no writeSemaphores are present
       
  3372         wasBlocked := OperatingSystem blockInterrupts.
       
  3373 
       
  3374         "/ 'scheduled: ' _errorPrint. self anyScheduledWindowGroupAtAll asString _errorPrintCR.
       
  3375         "/ 'anyUserProcess: ' _errorPrint. self anyUserProcessAtAll asString _errorPrintCR.
       
  3376         
       
  3377         self anyScheduledWindowGroupAtAll ifFalse:[
       
  3378             self anyUserProcessAtAll ifFalse:[
       
  3379                 Smalltalk verbose ifTrue:[
       
  3380                     'Processor [info]: end of dispatch' infoPrintCR.
       
  3381                 ].
       
  3382                 dispatching := false.
       
  3383                 "/ false ifTrue:[
       
  3384                 "/     MiniInspector basicNew printInstVarsOf:self.
       
  3385                 "/     MiniDebugger enter:thisContext withMessage:'about to exit' mayProceed:true.
       
  3386                 "/ ].
       
  3387             ].
       
  3388         ].
       
  3389         
       
  3390         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
       
  3391     ].
       
  3392 !
  3311 
  3393 
  3312 checkForIOWithTimeout:millis
  3394 checkForIOWithTimeout:millis
  3313     "this is called, when there is absolutely nothing to do;
  3395     "this is called, when there is absolutely nothing to do;
  3314      hard wait for either input to arrive, or output to be possible
  3396      hard wait for either input to arrive, or output to be possible
  3315      or a timeout to occur."
  3397      or a timeout to occur."
  3492      Notice, that at the time of the message, we are still in the context
  3574      Notice, that at the time of the message, we are still in the context
  3493      of whichever process is currently running."
  3575      of whichever process is currently running."
  3494 
  3576 
  3495     gotIOInterrupt := true.
  3577     gotIOInterrupt := true.
  3496     activeProcess ~~ scheduler ifTrue:[
  3578     activeProcess ~~ scheduler ifTrue:[
  3497         interruptCounter := interruptCounter + 1 bitAnd:SmallInteger maxVal.
  3579 	interruptCounter := interruptCounter + 1 bitAnd:SmallInteger maxVal.
  3498         interruptedProcess := activeProcess.
  3580 	interruptedProcess := activeProcess.
  3499         self threadSwitch:scheduler
  3581 	self threadSwitch:scheduler
  3500     ]
  3582     ]
  3501 
  3583 
  3502     "Modified: 21.12.1995 / 16:17:40 / stefan"
  3584     "Modified: 21.12.1995 / 16:17:40 / stefan"
  3503     "Modified: 4.8.1997 / 14:23:08 / cg"
  3585     "Modified: 4.8.1997 / 14:23:08 / cg"
  3504 !
       
  3505 
       
  3506 noMoreUserProcesses
       
  3507     "/ check if there are any processes at all
       
  3508     "/ stop dispatching if there is none
       
  3509     "/ (and anyTimeouts is false, which means that no timeout blocks are present)
       
  3510     "/ and no readSemaphores are present (which means that noone is waiting for input)
       
  3511     "/ and no writeSemaphores are present
       
  3512 
       
  3513     anyTimeouts ifFalse:[
       
  3514 	^ self anyUserProcessAtAll not.
       
  3515     ].
       
  3516     ^ false
       
  3517 "/    |anySema|
       
  3518 "/
       
  3519 "/
       
  3520 "/    anyTimeouts ifFalse:[
       
  3521 "/        anySema := (readSemaphoreArray findFirst:[:sema | sema notNil]) ~~ 0.
       
  3522 "/        anySema ifFalse:[
       
  3523 "/            anySema := (writeSemaphoreArray findFirst:[:sema | sema notNil]) ~~ 0.
       
  3524 "/            anySema ifFalse:[
       
  3525 "/                self anyUserProcessAtAll ifFalse:[
       
  3526 "/                    ^ true
       
  3527 "/                ]
       
  3528 "/            ].
       
  3529 "/        ].
       
  3530 "/    ].
       
  3531 "/    ^ false
       
  3532 
       
  3533     "
       
  3534      Processor noMoreUserProcesses
       
  3535     "
       
  3536 !
  3586 !
  3537 
  3587 
  3538 removeCorruptedFds
  3588 removeCorruptedFds
  3539     "this is sent when select returns an error due to some invalid
  3589     "this is sent when select returns an error due to some invalid
  3540      fileDescriptor. May happen, if someone does a readWait/writeWait on a
  3590      fileDescriptor. May happen, if someone does a readWait/writeWait on a
  3544      an #EBADF error, leading to high-frequency polling and a locked up system.
  3594      an #EBADF error, leading to high-frequency polling and a locked up system.
  3545      (you could still fix things by interrupting on the console and fixing the
  3595      (you could still fix things by interrupting on the console and fixing the
  3546       readFdArray/writeFdArray in the debugger)"
  3596       readFdArray/writeFdArray in the debugger)"
  3547 
  3597 
  3548     readFdArray keysAndValuesDo:[:idx :fd |
  3598     readFdArray keysAndValuesDo:[:idx :fd |
  3549         |result sema|
  3599 	|result sema|
  3550 
  3600 
  3551         fd notNil ifTrue:[
  3601 	fd notNil ifTrue:[
  3552             result := OperatingSystem
  3602 	    result := OperatingSystem
  3553                         selectOnAnyReadable:(Array with:fd) writable:nil exception:nil
  3603 			selectOnAnyReadable:(Array with:fd) writable:nil exception:nil
  3554                            readableInto:nil writableInto:nil exceptionInto:nil
  3604 			   readableInto:nil writableInto:nil exceptionInto:nil
  3555                            withTimeOut:0.
  3605 			   withTimeOut:0.
  3556 
  3606 
  3557             result < 0 ifTrue:[
  3607 	    result < 0 ifTrue:[
  3558                 'Processor [info]: removing invalid read-select fileDescriptor: ' infoPrint. fd infoPrint. ' idx: 'infoPrint. idx infoPrintCR.
  3608 		'Processor [info]: removing invalid read-select fileDescriptor: ' infoPrint. fd infoPrint. ' idx: 'infoPrint. idx infoPrintCR.
  3559                 readFdArray at:idx put:nil.
  3609 		readFdArray at:idx put:nil.
  3560                 readCheckArray at:idx put:nil.
  3610 		readCheckArray at:idx put:nil.
  3561                 (sema := readSemaphoreArray at:idx) notNil ifTrue:[
  3611 		(sema := readSemaphoreArray at:idx) notNil ifTrue:[
  3562                     readSemaphoreArray at:idx put:nil.
  3612 		    readSemaphoreArray at:idx put:nil.
  3563                     self removeTimeoutForSemaphore:sema.
  3613 		    self removeTimeoutForSemaphore:sema.
  3564                     sema signalForAll.
  3614 		    sema signalForAll.
  3565                 ].
  3615 		].
  3566             ]
  3616 	    ]
  3567         ].
  3617 	].
  3568     ].
  3618     ].
  3569 
  3619 
  3570     writeFdArray keysAndValuesDo:[:idx :fd |
  3620     writeFdArray keysAndValuesDo:[:idx :fd |
  3571         |result sema|
  3621 	|result sema|
  3572 
  3622 
  3573         fd notNil ifTrue:[
  3623 	fd notNil ifTrue:[
  3574             result := OperatingSystem
  3624 	    result := OperatingSystem
  3575                         selectOnAnyReadable:nil writable:(Array with:fd) exception:nil
  3625 			selectOnAnyReadable:nil writable:(Array with:fd) exception:nil
  3576                            readableInto:nil writableInto:nil exceptionInto:nil
  3626 			   readableInto:nil writableInto:nil exceptionInto:nil
  3577                            withTimeOut:0.
  3627 			   withTimeOut:0.
  3578 
  3628 
  3579             result < 0 ifTrue:[
  3629 	    result < 0 ifTrue:[
  3580                 'Processor [info]: removing invalid write-select fileDescriptor: ' infoPrint. fd infoPrint. ' idx: 'infoPrint. idx infoPrintCR.
  3630 		'Processor [info]: removing invalid write-select fileDescriptor: ' infoPrint. fd infoPrint. ' idx: 'infoPrint. idx infoPrintCR.
  3581                 writeFdArray at:idx put:nil.
  3631 		writeFdArray at:idx put:nil.
  3582                 writeCheckArray at:idx put:nil.
  3632 		writeCheckArray at:idx put:nil.
  3583                 (sema := writeSemaphoreArray at:idx) notNil ifTrue:[
  3633 		(sema := writeSemaphoreArray at:idx) notNil ifTrue:[
  3584                     writeSemaphoreArray at:idx put:nil.
  3634 		    writeSemaphoreArray at:idx put:nil.
  3585                     self removeTimeoutForSemaphore:sema.
  3635 		    self removeTimeoutForSemaphore:sema.
  3586                     sema signalForAll.
  3636 		    sema signalForAll.
  3587                 ].
  3637 		].
  3588             ]
  3638 	    ]
  3589         ]
  3639 	]
  3590     ].
  3640     ].
  3591 
  3641 
  3592     exceptFdArray keysAndValuesDo:[:idx :fd |
  3642     exceptFdArray keysAndValuesDo:[:idx :fd |
  3593         |result sema|
  3643 	|result sema|
  3594 
  3644 
  3595         fd notNil ifTrue:[
  3645 	fd notNil ifTrue:[
  3596             result := OperatingSystem
  3646 	    result := OperatingSystem
  3597                         selectOnAnyReadable:nil writable:nil exception:(Array with:fd)
  3647 			selectOnAnyReadable:nil writable:nil exception:(Array with:fd)
  3598                            readableInto:nil writableInto:nil exceptionInto:nil
  3648 			   readableInto:nil writableInto:nil exceptionInto:nil
  3599                            withTimeOut:0.
  3649 			   withTimeOut:0.
  3600 
  3650 
  3601             result < 0 ifTrue:[
  3651 	    result < 0 ifTrue:[
  3602                 'Processor [info]: removing invalid exception-select fileDescriptor: ' infoPrint. fd infoPrint. ' idx: 'infoPrint. idx infoPrintCR.
  3652 		'Processor [info]: removing invalid exception-select fileDescriptor: ' infoPrint. fd infoPrint. ' idx: 'infoPrint. idx infoPrintCR.
  3603                 exceptFdArray at:idx put:nil.
  3653 		exceptFdArray at:idx put:nil.
  3604                 (sema := exceptSemaphoreArray at:idx) notNil ifTrue:[
  3654 		(sema := exceptSemaphoreArray at:idx) notNil ifTrue:[
  3605                     exceptSemaphoreArray at:idx put:nil.
  3655 		    exceptSemaphoreArray at:idx put:nil.
  3606                     self removeTimeoutForSemaphore:sema.
  3656 		    self removeTimeoutForSemaphore:sema.
  3607                     sema signalForAll.
  3657 		    sema signalForAll.
  3608                 ].
  3658 		].
  3609             ]
  3659 	    ]
  3610         ]
  3660 	]
  3611     ].
  3661     ].
  3612 
  3662 
  3613 
  3663 
  3614     OperatingSystem isMSWINDOWSlike ifTrue:[
  3664     OperatingSystem isMSWINDOWSlike ifTrue:[
  3615         "/
  3665 	"/
  3616         "/ win32 does a WaitForMultipleObjects in select...
  3666 	"/ win32 does a WaitForMultipleObjects in select...
  3617         "/ unix waits for SIGCHLD
  3667 	"/ unix waits for SIGCHLD
  3618         "/
  3668 	"/
  3619         osChildExitActions keysDo:[:eachPid |
  3669 	osChildExitActions keysDo:[:eachPid |
  3620             |result sema|
  3670 	    |result sema|
  3621 
  3671 
  3622             eachPid notNil ifTrue:[
  3672 	    eachPid notNil ifTrue:[
  3623                 result := OperatingSystem
  3673 		result := OperatingSystem
  3624                             selectOnAnyReadable:nil writable:nil exception:(Array with:eachPid)
  3674 			    selectOnAnyReadable:nil writable:nil exception:(Array with:eachPid)
  3625                                readableInto:nil writableInto:nil exceptionInto:nil
  3675 			       readableInto:nil writableInto:nil exceptionInto:nil
  3626                                withTimeOut:0.
  3676 			       withTimeOut:0.
  3627 
  3677 
  3628                 result < 0 ifTrue:[
  3678 		result < 0 ifTrue:[
  3629                     'Processor [info]: removing invalid exception-select pid: ' infoPrint. eachPid infoPrintCR.
  3679 		    'Processor [info]: removing invalid exception-select pid: ' infoPrint. eachPid infoPrintCR.
  3630                     osChildExitActions safeRemoveKey:eachPid.
  3680 		    osChildExitActions safeRemoveKey:eachPid.
  3631                 ]
  3681 		]
  3632             ]
  3682 	    ]
  3633         ].
  3683 	].
  3634     ].
  3684     ].
  3635 
  3685 
  3636     "Modified: 12.4.1996 / 09:32:58 / stefan"
  3686     "Modified: 12.4.1996 / 09:32:58 / stefan"
  3637     "Modified: 27.1.1997 / 20:09:27 / cg"
  3687     "Modified: 27.1.1997 / 20:09:27 / cg"
  3638 !
  3688 !
  3640 schedulerInterrupt
  3690 schedulerInterrupt
  3641     "forced reschedule - switch to scheduler process which will decide
  3691     "forced reschedule - switch to scheduler process which will decide
  3642      what to do now."
  3692      what to do now."
  3643 
  3693 
  3644     activeProcess ~~ scheduler ifTrue:[
  3694     activeProcess ~~ scheduler ifTrue:[
  3645         interruptCounter := interruptCounter + 1 bitAnd:SmallInteger maxVal.
  3695 	interruptCounter := interruptCounter + 1 bitAnd:SmallInteger maxVal.
  3646         interruptedProcess := activeProcess.
  3696 	interruptedProcess := activeProcess.
  3647         self threadSwitch:scheduler
  3697 	self threadSwitch:scheduler
  3648     ]
  3698     ]
  3649 !
  3699 !
  3650 
  3700 
  3651 timeToNextTimeout
  3701 timeToNextTimeout
  3652     "return the delta-T (in millis) to next timeout, or nil if
  3702     "return the delta-T (in millis) to next timeout, or nil if
  3692      This method is called by the VM' interrupt handling mechanism.
  3742      This method is called by the VM' interrupt handling mechanism.
  3693      Notice, that at the time of the message, we are still in the context
  3743      Notice, that at the time of the message, we are still in the context
  3694      of whichever process is currently running."
  3744      of whichever process is currently running."
  3695 
  3745 
  3696     activeProcess ~~ scheduler ifTrue:[
  3746     activeProcess ~~ scheduler ifTrue:[
  3697         interruptCounter := interruptCounter + 1 bitAnd:SmallInteger maxVal.
  3747 	interruptCounter := interruptCounter + 1 bitAnd:SmallInteger maxVal.
  3698         interruptedProcess := activeProcess.
  3748 	interruptedProcess := activeProcess.
  3699         self threadSwitch:scheduler
  3749 	self threadSwitch:scheduler
  3700     ]
  3750     ]
  3701 
  3751 
  3702     "Modified: 18.10.1996 / 20:35:54 / cg"
  3752     "Modified: 18.10.1996 / 20:35:54 / cg"
  3703 !
  3753 !
  3704 
  3754 
  3711 
  3761 
  3712     |millis doingGC dT|
  3762     |millis doingGC dT|
  3713 
  3763 
  3714     doingGC := true.
  3764     doingGC := true.
  3715     [doingGC] whileTrue:[
  3765     [doingGC] whileTrue:[
  3716 	anyTimeouts ifTrue:[
  3766         anyTimeouts ifTrue:[
  3717 	    millis := self timeToNextTimeout.
  3767             millis := self timeToNextTimeout.
  3718 	    (millis notNil and:[millis <= 0]) ifTrue:[
  3768             (millis notNil and:[millis <= 0]) ifTrue:[
  3719 		^ self    "oops - hurry up checking"
  3769                 ^ self    "oops - hurry up checking"
  3720 	    ].
  3770             ].
  3721 	].
  3771         ].
  3722 
  3772 
  3723 	"
  3773         "
  3724 	 if its worth doing, collect a bit of garbage;
  3774          if its worth doing, collect a bit of garbage;
  3725 	 but not, if a backgroundCollector is active
  3775          but not, if a backgroundCollector is active
  3726 	"
  3776         "
  3727 	ObjectMemory backgroundCollectorRunning ifTrue:[
  3777         ObjectMemory backgroundCollectorRunning ifTrue:[
  3728 	    doingGC := false
  3778             doingGC := false
  3729 	] ifFalse:[
  3779         ] ifFalse:[
  3730 	    doingGC := ObjectMemory gcStepIfUseful.
  3780             doingGC := ObjectMemory gcStepIfUseful.
  3731 	].
  3781         ].
  3732 
  3782 
  3733 	"then do idle actions"
  3783         "then do idle actions"
  3734 	(idleActions notNil and:[idleActions size ~~ 0]) ifTrue:[
  3784         (idleActions notNil and:[idleActions size ~~ 0]) ifTrue:[
  3735 	    idleActions do:[:aBlock |
  3785             idleActions do:[:aBlock |
  3736 		aBlock value.
  3786                 aBlock value.
  3737 	    ].
  3787             ].
  3738 	    ^ self   "go back checking"
  3788             ^ self   "go back checking"
  3739 	].
  3789         ].
  3740 
  3790 
  3741 	doingGC ifTrue:[
  3791         doingGC ifTrue:[
  3742 	    (self checkForIOWithTimeout:0) ifTrue:[
  3792             (self checkForIOWithTimeout:0) ifTrue:[
  3743 		^ self  "go back checking"
  3793                 ^ self  "go back checking"
  3744 	    ]
  3794             ]
  3745 	]
  3795         ]
  3746     ].
  3796     ].
  3747 
  3797 
  3748     exitWhenNoMoreUserProcesses ifTrue:[
  3798     exitWhenNoMoreUserProcesses ifTrue:[
  3749 	"/ check if there are any processes at all
  3799         "/ check if there are any processes at all
  3750 	"/ stop dispatching if there is none
  3800         "/ stop dispatching if there is none
  3751 	"/ (and anyTimeouts is false, which means that no timeout blocks are present)
  3801         "/ (and anyTimeouts is false, which means that no timeout blocks are present)
  3752 	"/ and no readSemaphores are present (which means that noone is waiting for input)
  3802         "/ and no readSemaphores are present (which means that noone is waiting for input)
  3753 	"/ and no writeSemaphores are present
  3803         "/ and no writeSemaphores are present
  3754 
  3804         
  3755 	self noMoreUserProcesses ifTrue:[
  3805         "/ cg: changed to only check when a process terminated
  3756 	    dispatching := false.
  3806         "/ self checkForEndOfDispatch.
  3757 	    ^ self
  3807         dispatching ifFalse:[
  3758 	].
  3808             ^ self
       
  3809         ].
  3759     ].
  3810     ].
  3760 
  3811 
  3761     preWaitActions notNil ifTrue:[
  3812     preWaitActions notNil ifTrue:[
  3762 	preWaitActions do:[:action | action value].
  3813         preWaitActions do:[:action | action value].
  3763     ].
  3814     ].
  3764 
  3815 
  3765     "/
  3816     "/
  3766     "/ absolutely nothing to do - simply wait
  3817     "/ absolutely nothing to do - simply wait
  3767     "/
  3818     "/
  3768     OperatingSystem supportsSelect ifFalse:[
  3819     OperatingSystem supportsSelect ifFalse:[
  3769 	"SCO instant ShitStation has a bug here,
  3820         "SCO instant ShitStation has a bug here,
  3770 	 waiting always 1 sec in the select - therefore we delay a bit and
  3821          waiting always 1 sec in the select - therefore we delay a bit and
  3771 	 return - effectively polling in 50ms cycles
  3822          return - effectively polling in 50ms cycles
  3772 	"
  3823         "
  3773 	(self checkForIOWithTimeout:0) ifTrue:[
  3824         (self checkForIOWithTimeout:0) ifTrue:[
  3774 	    ^ self  "go back checking"
  3825             ^ self  "go back checking"
  3775 	].
  3826         ].
  3776 	OperatingSystem millisecondDelay:EventPollingInterval.
  3827         OperatingSystem millisecondDelay:EventPollingInterval.
  3777 	^ self
  3828         ^ self
  3778     ].
  3829     ].
  3779 
  3830 
  3780     useIOInterrupts ifTrue:[
  3831     useIOInterrupts ifTrue:[
  3781 	dT := 999999
  3832         dT := 999999
  3782     ] ifFalse:[
  3833     ] ifFalse:[
  3783 	dT := EventPollingInterval
  3834         dT := EventPollingInterval
  3784     ].
  3835     ].
  3785 
  3836 
  3786     millis isNil ifTrue:[
  3837     millis isNil ifTrue:[
  3787 	millis := dT.
  3838         millis := dT.
  3788     ] ifFalse:[
  3839     ] ifFalse:[
  3789 	millis := millis rounded min:dT.
  3840         millis := millis rounded min:dT.
  3790     ].
  3841     ].
  3791 
  3842 
  3792     self checkForIOWithTimeout:millis
  3843     self checkForIOWithTimeout:millis
  3793 
  3844 
  3794     "Modified: 14.12.1995 / 13:37:46 / stefan"
  3845     "Modified: 14.12.1995 / 13:37:46 / stefan"