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 " |
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)" |
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 " |
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 |
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. |
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 |
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 ] |
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 ! |
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" |