77 |
77 |
78 This pure-event mode may not be supported in the future |
78 This pure-event mode may not be supported in the future |
79 (actually, it is no longer maintained, so dont run the system without Processes). |
79 (actually, it is no longer maintained, so dont run the system without Processes). |
80 |
80 |
81 [instance variables:] |
81 [instance variables:] |
82 quiescentProcessLists - list of waiting processes |
82 quiescentProcessLists - list of waiting processes |
83 scheduler - the scheduler process itself |
83 scheduler - the scheduler process itself |
84 zombie - internal temporary (recently died process) |
84 zombie - internal temporary (recently died process) |
85 activeProcess - the current process |
85 activeProcess - the current process |
86 activeProcessId - the current processes id |
86 activeProcessId - the current processes id |
87 currentPriority - the current processes priority |
87 currentPriority - the current processes priority |
88 readFdArray - fd-sema-checkBlock triple-association |
88 readFdArray - fd-sema-checkBlock triple-association |
89 readSemaphoreArray (stupid historic 3-separate arrays for hi-speed-optimization reasons) |
89 readSemaphoreArray (stupid historic 3-separate arrays for hi-speed-optimization reasons) |
90 readCheckArray |
90 readCheckArray |
91 writeFdArray - fd-sema-checkBlock triple-association |
91 writeFdArray - fd-sema-checkBlock triple-association |
92 writeSemaphoreArray (stupid historic 3-separate arrays for hi-speed-optimization reasons) |
92 writeSemaphoreArray (stupid historic 3-separate arrays for hi-speed-optimization reasons) |
93 writeCheckArray |
93 writeCheckArray |
94 timeoutArray - time-action-process-sema quadruple-association |
94 timeoutArray - time-action-process-sema quadruple-association |
95 timeoutActionArray (stupid historic 3-separate arrays for hi-speed-optimization reasons) |
95 timeoutActionArray (stupid historic 3-separate arrays for hi-speed-optimization reasons) |
96 timeoutProcessArray |
96 timeoutProcessArray |
97 timeoutSemaphoreArray |
97 timeoutSemaphoreArray |
98 idleActions - actions to be executed when idle |
98 idleActions - actions to be executed when idle |
99 preWaitActions - actions to be executed BEFORE going into an OS-wait |
99 preWaitActions - actions to be executed BEFORE going into an OS-wait |
100 anyTimeouts - flag if any timeouts are pending |
100 anyTimeouts - flag if any timeouts are pending |
101 dispatching - flag if dispatch process is running (i.e. NOT initializing) |
101 dispatching - flag if dispatch process is running (i.e. NOT initializing) |
102 interruptedProcess - the currently interrupted process. |
102 interruptedProcess - the currently interrupted process. |
103 useIOInterrupts - flag if the OS supports I/O interrupts and if they are used (to get me out of an OS wait) |
103 useIOInterrupts - flag if the OS supports I/O interrupts and if they are used (to get me out of an OS wait) |
104 gotIOInterrupt - flag if I came out of a wait due to an I/O interrupt |
104 gotIOInterrupt - flag if I came out of a wait due to an I/O interrupt |
105 osChildExitActions - OS chid process actions |
105 osChildExitActions - OS chid process actions |
106 gotChildSignalInterrupt - flag if I came out of a wait due to an OS child interrupt |
106 gotChildSignalInterrupt - flag if I came out of a wait due to an OS child interrupt |
107 exitWhenNoMoreUserProcesses - flag which controls if ST/X should exit when the last process dies (for standalone apps) |
107 exitWhenNoMoreUserProcesses - flag which controls if ST/X should exit when the last process dies (for standalone apps) |
108 suspendScheduler - internal use |
108 suspendScheduler - internal use |
109 timeSliceProcess - the timeSlicer process |
109 timeSliceProcess - the timeSlicer process |
110 supportDynamicPriorities - flag if dynamic priorities should be supported by the timeSlicer |
110 supportDynamicPriorities - flag if dynamic priorities should be supported by the timeSlicer |
111 scheduledProcesses - list of scheduled processes for the timeSlicers dynamic prio handling |
111 scheduledProcesses - list of scheduled processes for the timeSlicers dynamic prio handling |
112 |
112 |
113 [class variables:] |
113 [class variables:] |
114 |
114 |
115 KnownProcesses <WeakArray> all known processes |
115 KnownProcesses <WeakArray> all known processes |
116 KnownProcessIds <Collection> and their IDs |
116 KnownProcessIds <Collection> and their IDs |
117 |
117 |
118 PureEventDriven <Boolean> true, if no process support |
118 PureEventDriven <Boolean> true, if no process support |
119 is available |
119 is available |
120 |
120 |
121 UserSchedulingPriority <Integer> the priority at which normal |
121 UserSchedulingPriority <Integer> the priority at which normal |
122 user interfaces run |
122 user interfaces run |
123 |
123 |
124 UserInterruptPriority the priority at which user- |
124 UserInterruptPriority the priority at which user- |
125 interrupts (Cntl-C) processing |
125 interrupts (Cntl-C) processing |
126 takes place. Processes with |
126 takes place. Processes with |
127 a greater or equal priority are |
127 a greater or equal priority are |
128 not interruptable. |
128 not interruptable. |
129 |
129 |
130 TimingPriority the priority used for timing. |
130 TimingPriority the priority used for timing. |
131 Processes with a greater or |
131 Processes with a greater or |
132 equal priority are not interrupted |
132 equal priority are not interrupted |
133 by timers. |
133 by timers. |
134 |
134 |
135 HighestPriority The highest allowed prio for processes |
135 HighestPriority The highest allowed prio for processes |
136 |
136 |
137 SchedulingPriority The priority of the scheduler (must |
137 SchedulingPriority The priority of the scheduler (must |
138 me higher than any other). |
138 me higher than any other). |
139 |
139 |
140 MaxNumberOfProcesses if non-nil, no more than this |
140 MaxNumberOfProcesses if non-nil, no more than this |
141 number of processes are allowed |
141 number of processes are allowed |
142 (for debugging) |
142 (for debugging) |
143 |
143 |
144 TimeSliceInterval for preemptive priority scheduling only: |
144 TimeSliceInterval for preemptive priority scheduling only: |
145 the time interval in millis, at which processes |
145 the time interval in millis, at which processes |
146 are timesliced |
146 are timesliced |
147 |
147 |
148 TimeSlicingPriorityLimit for preemptive priority scheduling only: |
148 TimeSlicingPriorityLimit for preemptive priority scheduling only: |
149 processes are only timesliced, if running |
149 processes are only timesliced, if running |
150 at or below this priority. |
150 at or below this priority. |
151 |
151 |
152 EventPollingInterval for systems which do not support select on |
152 EventPollingInterval for systems which do not support select on |
153 a fileDescriptor: the polling interval in millis. |
153 a fileDescriptor: the polling interval in millis. |
154 |
154 |
155 most interesting methods: |
155 most interesting methods: |
156 |
156 |
157 Processor>>suspend: (see also Process>>suspend) |
157 Processor>>suspend: (see also Process>>suspend) |
158 Processor>>resume: (see also Process>>resume) |
158 Processor>>resume: (see also Process>>resume) |
159 Processor>>terminate: (see also Process>>terminate) |
159 Processor>>terminate: (see also Process>>terminate) |
160 Processor>>yield |
160 Processor>>yield |
161 Processor>>changePriority:for: (see also Process>>priority: |
161 Processor>>changePriority:for: (see also Process>>priority: |
162 |
162 |
163 Processor>>signal:afterSeconds: (see also Delay>>forSeconds:) |
163 Processor>>signal:afterSeconds: (see also Delay>>forSeconds:) |
164 Processor>>signal:afterMilliseconds: (see also Delay>>forMilliseconds:) |
164 Processor>>signal:afterMilliseconds: (see also Delay>>forMilliseconds:) |
165 Processor>>signal:onInput: (see also ExternalStream>>readWait) |
165 Processor>>signal:onInput: (see also ExternalStream>>readWait) |
166 Processor>>signal:onOutput: (see also ExternalStream>>writeWait) |
166 Processor>>signal:onOutput: (see also ExternalStream>>writeWait) |
167 Processor>>disableSemaphore: |
167 Processor>>disableSemaphore: |
168 |
168 |
169 |
169 |
170 [see also:] |
170 [see also:] |
171 Process |
171 Process |
172 Delay Semaphore SemaphoreSet SharedQueue |
172 Delay Semaphore SemaphoreSet SharedQueue |
173 WindowGroup |
173 WindowGroup |
174 (``Working with processes'': programming/processes.html) |
174 (``Working with processes'': programming/processes.html) |
175 |
175 |
176 [author:] |
176 [author:] |
177 Claus Gittinger |
177 Claus Gittinger |
178 " |
178 " |
179 ! |
179 ! |
180 |
180 |
181 scheduling |
181 scheduling |
182 " |
182 " |
210 event. |
210 event. |
211 Timeslicing will not be done for processes running above TimeSlicingPriorityLimit, which |
211 Timeslicing will not be done for processes running above TimeSlicingPriorityLimit, which |
212 allows for critical processes to run unaffected to completion. |
212 allows for critical processes to run unaffected to completion. |
213 |
213 |
214 WARNING: |
214 WARNING: |
215 timesliced priority scheduling is an experimental feature. There is no warranty, |
215 timesliced priority scheduling is an experimental feature. There is no warranty, |
216 (at the moment), that the system runs reliable in this mode. |
216 (at the moment), that the system runs reliable in this mode. |
217 The problem is, that shared collections may now be easily modified by other |
217 The problem is, that shared collections may now be easily modified by other |
218 processes, running at the same time. |
218 processes, running at the same time. |
219 The class library has being investigated for such possible trouble spots |
219 The class library has being investigated for such possible trouble spots |
220 (we have eliminated many weak spots, and added critical regions at many places, |
220 (we have eliminated many weak spots, and added critical regions at many places, |
221 but cannot guarantee that all of them have been found so far ...) |
221 but cannot guarantee that all of them have been found so far ...) |
222 We found that many existing public domain programs are not prepared for |
222 We found that many existing public domain programs are not prepared for |
223 being interrupted by a same-prio process and therefore may corrupt their |
223 being interrupted by a same-prio process and therefore may corrupt their |
224 data. If in doubt, disable this fefature. |
224 data. If in doubt, disable this fefature. |
225 |
225 |
226 We think, that the timeSlicer is a useful add-on and that the system is fit enough |
226 We think, that the timeSlicer is a useful add-on and that the system is fit enough |
227 for it to be evaluated, therefore, its included. |
227 for it to be evaluated, therefore, its included. |
228 However, use it at your own risk. |
228 However, use it at your own risk. |
229 |
229 |
230 To demonstrate the effect of timeSlicing, do the following: |
230 To demonstrate the effect of timeSlicing, do the following: |
231 |
231 |
232 - disable timeSlicing (in the launchers misc-settings menu) |
232 - disable timeSlicing (in the launchers misc-settings menu) |
233 - open a workSpace |
233 - open a workSpace |
234 - in the workspace, evaluate: |
234 - in the workspace, evaluate: |
235 [true] whileTrue:[1000 factorial] |
235 [true] whileTrue:[1000 factorial] |
236 |
236 |
237 now, (since the workSpace runs at the same prio as other window-processes), |
237 now, (since the workSpace runs at the same prio as other window-processes), |
238 other views do no longer react - all CPU is used up by the workSpace. |
238 other views do no longer react - all CPU is used up by the workSpace. |
239 However, CTRL-C in the workspace is still possible to stop the endless loop, |
239 However, CTRL-C in the workspace is still possible to stop the endless loop, |
240 since that is handled by the (higher prio) event dispatcher process. |
240 since that is handled by the (higher prio) event dispatcher process. |
260 TimeSlicingPriorityLimit := 26. |
260 TimeSlicingPriorityLimit := 26. |
261 HighestPriority := 30. |
261 HighestPriority := 30. |
262 SchedulingPriority := 31. |
262 SchedulingPriority := 31. |
263 |
263 |
264 InvalidProcessSignal isNil ifTrue:[ |
264 InvalidProcessSignal isNil ifTrue:[ |
265 InvalidProcessSignal := Error newSignalMayProceed:true. |
265 InvalidProcessSignal := Error newSignalMayProceed:true. |
266 InvalidProcessSignal nameClass:self message:#invalidProcessSignal. |
266 InvalidProcessSignal nameClass:self message:#invalidProcessSignal. |
267 InvalidProcessSignal notifierString:'invalid process'. |
267 InvalidProcessSignal notifierString:'invalid process'. |
268 ]. |
268 ]. |
269 |
269 |
270 Processor isNil ifTrue:[ |
270 Processor isNil ifTrue:[ |
271 "create the one and only processor" |
271 "create the one and only processor" |
272 |
272 |
273 Processor := self basicNew initialize. |
273 Processor := self basicNew initialize. |
274 ]. |
274 ]. |
275 |
275 |
276 " |
276 " |
277 allow configurations without processes |
277 allow configurations without processes |
278 (but such configurations are no longer distributed) |
278 (but such configurations are no longer distributed) |
279 " |
279 " |
280 PureEventDriven := self threadsAvailable not. |
280 PureEventDriven := self threadsAvailable not. |
281 PureEventDriven ifTrue:[ |
281 PureEventDriven ifTrue:[ |
282 'Processor [error]: no process support - running event driven' errorPrintCR |
282 'Processor [error]: no process support - running event driven' errorPrintCR |
283 ]. |
283 ]. |
284 |
284 self initializeVMMaxProcessId |
285 %{ |
|
286 #ifndef MAX_PROCESS_ID |
|
287 # define MAX_PROCESS_ID _MAX_INT |
|
288 #endif |
|
289 @global(ProcessorScheduler:MaxProcessId) = __MKSMALLINT(MAX_PROCESS_ID); |
|
290 %} |
|
291 |
285 |
292 "Modified: / 23-09-1996 / 14:24:50 / stefan" |
286 "Modified: / 23-09-1996 / 14:24:50 / stefan" |
293 "Modified: / 10-01-1997 / 18:03:03 / cg" |
287 "Modified: / 10-01-1997 / 18:03:03 / cg" |
294 "Modified: / 19-09-2014 / 12:47:51 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
288 "Modified: / 19-09-2014 / 12:47:51 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
289 ! |
|
290 |
|
291 initializeVMMaxProcessId |
|
292 |
|
293 "/ for java locks, the VM may reserve some bits |
|
294 "/ and reduce the maximum processID to be able to |
|
295 "/ encode the id in an object's header field. |
|
296 %{ |
|
297 #ifndef __SCHTEAM__ |
|
298 |
|
299 # ifndef MAX_PROCESS_ID |
|
300 # define MAX_PROCESS_ID _MAX_INT |
|
301 # endif |
|
302 |
|
303 @global(ProcessorScheduler:MaxProcessId) = __MKSMALLINT(MAX_PROCESS_ID); |
|
304 RETURN (self); |
|
305 #endif /* not SCHTEAM */ |
|
306 %}. |
|
307 MaxProcessId := SmallInteger maxVal. |
295 ! ! |
308 ! ! |
296 |
309 |
297 !ProcessorScheduler class methodsFor:'instance creation'! |
310 !ProcessorScheduler class methodsFor:'instance creation'! |
298 |
311 |
299 new |
312 new |
349 "physical creation of a process. |
362 "physical creation of a process. |
350 (warning: low level entry, no administration done). |
363 (warning: low level entry, no administration done). |
351 This may raise an exception, if a VM process could not be created." |
364 This may raise an exception, if a VM process could not be created." |
352 |
365 |
353 MaxNumberOfProcesses notNil ifTrue:[ |
366 MaxNumberOfProcesses notNil ifTrue:[ |
354 KnownProcessIds size >= MaxNumberOfProcesses ifTrue:[ |
367 KnownProcessIds size >= MaxNumberOfProcesses ifTrue:[ |
355 (KnownProcessIds count:[:el | el notNil]) >= MaxNumberOfProcesses ifTrue:[ |
368 (KnownProcessIds count:[:el | el notNil]) >= MaxNumberOfProcesses ifTrue:[ |
356 " |
369 " |
357 the number of processes has reached the (soft) limit. |
370 the number of processes has reached the (soft) limit. |
358 This limit prevents runaway programs from creating too many |
371 This limit prevents runaway programs from creating too many |
359 processes. If you continue in the debugger, the process will be |
372 processes. If you continue in the debugger, the process will be |
360 created as usual. If you dont want this, abort or terminate. |
373 created as usual. If you dont want this, abort or terminate. |
361 " |
374 " |
362 self error:'too many processes'. |
375 self error:'too many processes'. |
363 ] |
376 ] |
364 ] |
377 ] |
365 ]. |
378 ]. |
366 |
379 |
367 %{ |
380 %{ |
368 int tid; |
381 int tid; |
369 extern int __threadCreate(); |
382 extern int __threadCreate(); |
370 |
383 |
371 tid = __threadCreate(aProcess, |
384 tid = __threadCreate(aProcess, |
372 0 /* stackSize: no longer needed */, |
385 0 /* stackSize: no longer needed */, |
373 __isSmallInteger(id) ? __intVal(id) /* assign id */ |
386 __isSmallInteger(id) ? __intVal(id) /* assign id */ |
374 : -1 /* let VM assign one */ ); |
387 : -1 /* let VM assign one */ ); |
375 if (tid) { |
388 if (tid) { |
376 RETURN ( __mkSmallInteger(tid)); |
389 RETURN ( __mkSmallInteger(tid)); |
377 } |
390 } |
378 %} |
391 %} |
379 . |
392 . |
380 " |
393 " |
381 arrive here, if creation of process in VM failed. |
394 arrive here, if creation of process in VM failed. |
672 sockets and pipes (sigh) |
685 sockets and pipes (sigh) |
673 " |
686 " |
674 any := false. |
687 any := false. |
675 nActions := readCheckArray size. |
688 nActions := readCheckArray size. |
676 1 to:nActions do:[:index | |
689 1 to:nActions do:[:index | |
677 checkBlock := readCheckArray at:index. |
690 checkBlock := readCheckArray at:index. |
678 (checkBlock notNil and:[checkBlock value]) ifTrue:[ |
691 (checkBlock notNil and:[checkBlock value]) ifTrue:[ |
679 sema := readSemaphoreArray at:index. |
692 sema := readSemaphoreArray at:index. |
680 sema notNil ifTrue:[ |
693 sema notNil ifTrue:[ |
681 sema signalOnce. |
694 sema signalOnce. |
682 ]. |
695 ]. |
683 any := true. |
696 any := true. |
684 ] |
697 ] |
685 ]. |
698 ]. |
686 nActions := writeCheckArray size. |
699 nActions := writeCheckArray size. |
687 1 to:nActions do:[:index | |
700 1 to:nActions do:[:index | |
688 checkBlock := writeCheckArray at:index. |
701 checkBlock := writeCheckArray at:index. |
689 (checkBlock notNil and:[checkBlock value]) ifTrue:[ |
702 (checkBlock notNil and:[checkBlock value]) ifTrue:[ |
690 sema := writeSemaphoreArray at:index. |
703 sema := writeSemaphoreArray at:index. |
691 sema notNil ifTrue:[ |
704 sema notNil ifTrue:[ |
692 sema signalOnce. |
705 sema signalOnce. |
693 ]. |
706 ]. |
694 any := true. |
707 any := true. |
695 ] |
708 ] |
696 ]. |
709 ]. |
697 |
710 |
698 "now, someone might be runnable ..." |
711 "now, someone might be runnable ..." |
699 |
712 |
700 p := self highestPriorityRunnableProcess. |
713 p := self highestPriorityRunnableProcess. |
701 p isNil ifTrue:[ |
714 p isNil ifTrue:[ |
702 "/ no one runnable, hard wait for event or timeout |
715 "/ no one runnable, hard wait for event or timeout |
703 "/ Trace ifTrue:['w' printCR.]. |
716 "/ Trace ifTrue:['w' printCR.]. |
704 self waitForEventOrTimeout. |
717 self waitForEventOrTimeout. |
705 |
718 |
706 "/ check for OS process termination |
719 "/ check for OS process termination |
707 gotChildSignalInterrupt ifTrue:[ |
720 gotChildSignalInterrupt ifTrue:[ |
708 gotChildSignalInterrupt := false. |
721 gotChildSignalInterrupt := false. |
709 self handleChildSignalInterrupt |
722 self handleChildSignalInterrupt |
710 ]. |
723 ]. |
711 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
724 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
712 ^ self |
725 ^ self |
713 ]. |
726 ]. |
714 |
727 |
715 pri := p priority. |
728 pri := p priority. |
716 |
729 |
717 " |
730 " |
757 or by installing a poll-interrupt after 50ms (if the OS does not). |
770 or by installing a poll-interrupt after 50ms (if the OS does not). |
758 " |
771 " |
759 pri < UserInterruptPriority ifTrue:[ |
772 pri < UserInterruptPriority ifTrue:[ |
760 |
773 |
761 "comment out this if above is uncommented" |
774 "comment out this if above is uncommented" |
762 anyTimeouts ifTrue:[ |
775 anyTimeouts ifTrue:[ |
763 millis := self timeToNextTimeout. |
776 millis := self timeToNextTimeout. |
764 millis == 0 ifTrue:[ |
777 millis == 0 ifTrue:[ |
765 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
778 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
766 ^ self |
779 ^ self |
767 ]. |
780 ]. |
768 ]. |
781 ]. |
769 "---" |
782 "---" |
770 |
783 |
771 useIOInterrupts ifTrue:[ |
784 useIOInterrupts ifTrue:[ |
772 "/ readFdArray do:[:fd | |
785 "/ readFdArray do:[:fd | |
773 "/ (fd notNil and:[fd >= 0]) ifTrue:[ |
786 "/ (fd notNil and:[fd >= 0]) ifTrue:[ |
774 "/ OperatingSystem enableIOInterruptsOn:fd |
787 "/ OperatingSystem enableIOInterruptsOn:fd |
775 "/ ]. |
788 "/ ]. |
776 "/ ]. |
789 "/ ]. |
777 ] ifFalse:[ |
790 ] ifFalse:[ |
778 millis notNil ifTrue:[ |
791 millis notNil ifTrue:[ |
779 millis := millis min:EventPollingInterval |
792 millis := millis min:EventPollingInterval |
780 ] ifFalse:[ |
793 ] ifFalse:[ |
781 millis := EventPollingInterval |
794 millis := EventPollingInterval |
782 ] |
795 ] |
783 ] |
796 ] |
784 ]. |
797 ]. |
785 |
798 |
786 millis notNil ifTrue:[ |
799 millis notNil ifTrue:[ |
787 "/ Trace ifTrue:['C' print. millis printCR.]. |
800 "/ Trace ifTrue:['C' print. millis printCR.]. |
788 "schedule a clock interrupt after millis milliseconds" |
801 "schedule a clock interrupt after millis milliseconds" |
789 OperatingSystem enableTimer:millis rounded. |
802 OperatingSystem enableTimer:millis rounded. |
790 ]. |
803 ]. |
791 |
804 |
792 scheduledProcesses notNil ifTrue:[ |
805 scheduledProcesses notNil ifTrue:[ |
793 scheduledProcesses add:p |
806 scheduledProcesses add:p |
794 ]. |
807 ]. |
795 |
808 |
796 " |
809 " |
797 now let the process run - will come back here by reschedule |
810 now let the process run - will come back here by reschedule |
798 from ioInterrupt, scheduler or timerInterrupt ... (running at max+1) |
811 from ioInterrupt, scheduler or timerInterrupt ... (running at max+1) |
850 "/ this safes a bit of memory allocation in the scheduler) |
863 "/ this safes a bit of memory allocation in the scheduler) |
851 |
864 |
852 dispatchAction := [ [dispatching] whileTrue:[ self dispatch ] ]. |
865 dispatchAction := [ [dispatching] whileTrue:[ self dispatch ] ]. |
853 |
866 |
854 handlerAction := [:ex | |
867 handlerAction := [:ex | |
855 (HaltInterrupt accepts:ex creator) ifTrue:[ |
868 (HaltInterrupt accepts:ex creator) ifTrue:[ |
856 "/ in a standalone application, we do not want those |
869 "/ in a standalone application, we do not want those |
857 Smalltalk isStandAloneApp ifTrue:[ |
870 Smalltalk isStandAloneApp ifTrue:[ |
858 Smalltalk isStandAloneDebug ifFalse:[ |
871 Smalltalk isStandAloneDebug ifFalse:[ |
859 ('Processor [info]: ignored (', ex creator printString, ')') infoPrintCR. |
872 ('Processor [info]: ignored (', ex creator printString, ')') infoPrintCR. |
860 ex proceed. |
873 ex proceed. |
861 ] |
874 ] |
862 ]. |
875 ]. |
863 ]. |
876 ]. |
864 |
877 |
865 ('Processor [info]: caught (and ignored) signal (', ex creator printString, ')') infoPrintCR. |
878 ('Processor [info]: caught (and ignored) signal (', ex creator printString, ')') infoPrintCR. |
866 ex return |
879 ex return |
867 ]. |
880 ]. |
868 |
881 |
869 ignoredSignals := SignalSet |
882 ignoredSignals := SignalSet |
870 with:HaltInterrupt |
883 with:HaltInterrupt |
871 with:TerminateProcessRequest |
884 with:TerminateProcessRequest |
872 with:RecursionError |
885 with:RecursionError |
873 with:AbortAllOperationRequest. |
886 with:AbortAllOperationRequest. |
874 |
887 |
875 "/ |
888 "/ |
876 "/ I made this an extra call to dispatch; this allows recompilation |
889 "/ I made this an extra call to dispatch; this allows recompilation |
877 "/ of the dispatch-handling code in the running system. |
890 "/ of the dispatch-handling code in the running system. |
878 "/ |
891 "/ |
879 [dispatching] whileTrue:[ |
892 [dispatching] whileTrue:[ |
880 ignoredSignals handle:handlerAction do:dispatchAction |
893 ignoredSignals handle:handlerAction do:dispatchAction |
881 ]. |
894 ]. |
882 |
895 |
883 "/ we arrive here in standalone Apps, |
896 "/ we arrive here in standalone Apps, |
884 "/ when the last process at or above UserSchedulingPriority process died. |
897 "/ when the last process at or above UserSchedulingPriority process died. |
885 "/ regular ST/X stays in above loop forever |
898 "/ regular ST/X stays in above loop forever |
1031 <context: #return> |
1044 <context: #return> |
1032 |
1045 |
1033 |index pri aProcess l| |
1046 |index pri aProcess l| |
1034 |
1047 |
1035 OperatingSystem interruptsBlocked ifFalse:[ |
1048 OperatingSystem interruptsBlocked ifFalse:[ |
1036 MiniDebugger |
1049 MiniDebugger |
1037 enterWithMessage:'vmResumeInterrupt with no interruptsBlocked' |
1050 enterWithMessage:'vmResumeInterrupt with no interruptsBlocked' |
1038 mayProceed:true. |
1051 mayProceed:true. |
1039 ]. |
1052 ]. |
1040 |
1053 |
1041 index := KnownProcessIds identityIndexOf:id. |
1054 index := KnownProcessIds identityIndexOf:id. |
1042 index ~~ 0 ifTrue:[ |
1055 index ~~ 0 ifTrue:[ |
1043 aProcess := KnownProcesses at:index. |
1056 aProcess := KnownProcesses at:index. |
1044 pri := aProcess priority. |
1057 pri := aProcess priority. |
1045 l := quiescentProcessLists at:pri. |
1058 l := quiescentProcessLists at:pri. |
1046 l notNil ifTrue:[ |
1059 l notNil ifTrue:[ |
1047 (l includesIdentical:aProcess) ifTrue:[ |
1060 (l includesIdentical:aProcess) ifTrue:[ |
1048 "/ aProcess is on a run queue. |
1061 "/ aProcess is on a run queue. |
1049 "/ CG: this situation may happen, if the wrapCall |
1062 "/ CG: this situation may happen, if the wrapCall |
1050 "/ finishes before the process was layed to sleep |
1063 "/ finishes before the process was layed to sleep |
1051 "/ (i.e. schedulerIRQ arrives before the threadSwitch was finished). |
1064 "/ (i.e. schedulerIRQ arrives before the threadSwitch was finished). |
1052 "/ In that case, simply resume it and everything is OK. |
1065 "/ In that case, simply resume it and everything is OK. |
1053 "/ If the process is state running, ignore. |
1066 "/ If the process is state running, ignore. |
1054 |
1067 |
1055 |state| |
1068 |state| |
1056 |
1069 |
1057 state := aProcess state. |
1070 state := aProcess state. |
1058 (state == #wrapWait or:[state == #osWait] or:[state == #stopped]) ifTrue:[ |
1071 (state == #wrapWait or:[state == #osWait] or:[state == #stopped]) ifTrue:[ |
1059 aProcess state:#run. |
1072 aProcess state:#run. |
1060 ]. |
1073 ]. |
1061 'ProcSched [info]: resumeIRQ ignored for process: ' infoPrint. |
1074 'ProcSched [info]: resumeIRQ ignored for process: ' infoPrint. |
1062 aProcess id infoPrint. ' in state: ' infoPrint. state infoPrintCR. |
1075 aProcess id infoPrint. ' in state: ' infoPrint. state infoPrintCR. |
1063 ^ self |
1076 ^ self |
1064 ] |
1077 ] |
1065 ] ifFalse:[ |
1078 ] ifFalse:[ |
1066 l := LinkedList new. |
1079 l := LinkedList new. |
1067 quiescentProcessLists at:pri put:l. |
1080 quiescentProcessLists at:pri put:l. |
1068 ]. |
1081 ]. |
1069 l addLast:aProcess. |
1082 l addLast:aProcess. |
1070 aProcess state:#run. |
1083 aProcess state:#run. |
1071 ] ifFalse:[ |
1084 ] ifFalse:[ |
1072 'ProcSched [info]: resumeIRQ for unknown process: ' infoPrint. |
1085 'ProcSched [info]: resumeIRQ for unknown process: ' infoPrint. |
1073 id infoPrintCR. |
1086 id infoPrintCR. |
1074 ] |
1087 ] |
1075 |
1088 |
1076 "Modified: / 28.9.1998 / 11:36:53 / cg" |
1089 "Modified: / 28.9.1998 / 11:36:53 / cg" |
1077 ! |
1090 ! |
1078 |
1091 |
1142 blocking := OperatingSystem blockingChildProcessWait. |
1155 blocking := OperatingSystem blockingChildProcessWait. |
1143 |
1156 |
1144 "/ no interrupt processing, to avoid races with monitorPid |
1157 "/ no interrupt processing, to avoid races with monitorPid |
1145 wasBlocked := OperatingSystem blockInterrupts. |
1158 wasBlocked := OperatingSystem blockInterrupts. |
1146 [ |
1159 [ |
1147 [ |
1160 [ |
1148 osProcessStatus := OperatingSystem childProcessWait:blocking pid:nil. |
1161 osProcessStatus := OperatingSystem childProcessWait:blocking pid:nil. |
1149 osProcessStatus notNil ifTrue:[ |
1162 osProcessStatus notNil ifTrue:[ |
1150 |pid action| |
1163 |pid action| |
1151 |
1164 |
1152 pid := osProcessStatus pid. |
1165 pid := osProcessStatus pid. |
1153 osProcessStatus stillAlive ifTrue:[ |
1166 osProcessStatus stillAlive ifTrue:[ |
1154 action := osChildExitActions at:pid ifAbsent:nil. |
1167 action := osChildExitActions at:pid ifAbsent:nil. |
1155 ] ifFalse:[ |
1168 ] ifFalse:[ |
1156 action := osChildExitActions removeKey:pid ifAbsent:nil. |
1169 action := osChildExitActions removeKey:pid ifAbsent:nil. |
1157 ]. |
1170 ]. |
1158 action notNil ifTrue:[ |
1171 action notNil ifTrue:[ |
1159 action value:osProcessStatus |
1172 action value:osProcessStatus |
1160 ]. |
1173 ]. |
1161 ]. |
1174 ]. |
1162 |
1175 |
1163 "/ if pollChildProcesses does block, poll only one status change. |
1176 "/ if pollChildProcesses does block, poll only one status change. |
1164 "/ we will get another SIGCHLD for other status changes. |
1177 "/ we will get another SIGCHLD for other status changes. |
1165 |
1178 |
1166 osProcessStatus notNil and:[blocking not] |
1179 osProcessStatus notNil and:[blocking not] |
1167 ] whileTrue. |
1180 ] whileTrue. |
1168 |
1181 |
1169 "/ if there are no more waiters, disable SIGCHILD handler. |
1182 "/ if there are no more waiters, disable SIGCHILD handler. |
1170 "/ this helps us with synchronous waiters (e.g. pclose), |
1183 "/ this helps us with synchronous waiters (e.g. pclose), |
1171 "/ But they should block SIGCHLD anyway. |
1184 "/ But they should block SIGCHLD anyway. |
1172 |
1185 |
1173 osChildExitActions isEmpty ifTrue:[ |
1186 osChildExitActions isEmpty ifTrue:[ |
1174 OperatingSystem disableChildSignalInterrupts. |
1187 OperatingSystem disableChildSignalInterrupts. |
1175 ]. |
1188 ]. |
1176 ] ensure:[ |
1189 ] ensure:[ |
1177 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1190 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1178 ] |
1191 ] |
1179 |
1192 |
1180 "Modified: 5.1.1996 / 16:56:11 / stefan" |
1193 "Modified: 5.1.1996 / 16:56:11 / stefan" |
1181 "Modified: 28.2.1996 / 21:36:31 / cg" |
1194 "Modified: 28.2.1996 / 21:36:31 / cg" |
1182 "Created: 12.4.1996 / 10:08:21 / stefan" |
1195 "Created: 12.4.1996 / 10:08:21 / stefan" |
1299 activeProcess := oldProcess. |
1312 activeProcess := oldProcess. |
1300 activeProcessId := oldId. |
1313 activeProcessId := oldId. |
1301 currentPriority := oldProcess priority. |
1314 currentPriority := oldProcess priority. |
1302 |
1315 |
1303 ok == true ifFalse:[ |
1316 ok == true ifFalse:[ |
1304 " |
1317 " |
1305 switch failed for some reason - |
1318 switch failed for some reason - |
1306 destroy (hard-terminate) the bad process. |
1319 destroy (hard-terminate) the bad process. |
1307 This happens when: |
1320 This happens when: |
1308 - the stack went above the absolute limit |
1321 - the stack went above the absolute limit |
1309 (VM switches back to scheduler) |
1322 (VM switches back to scheduler) |
1310 - a halted process cannot execute its interrupt |
1323 - a halted process cannot execute its interrupt |
1311 actions (win32 only) |
1324 actions (win32 only) |
1312 " |
1325 " |
1313 (id := p id) ~~ 0 ifTrue:[ |
1326 (id := p id) ~~ 0 ifTrue:[ |
1314 id notNil ifTrue:[ |
1327 id notNil ifTrue:[ |
1315 'Processor [warning]: problem with process ' errorPrint. |
1328 'Processor [warning]: problem with process ' errorPrint. |
1316 id errorPrint. |
1329 id errorPrint. |
1317 (nm := p name) notNil ifTrue:[ |
1330 (nm := p name) notNil ifTrue:[ |
1318 ' (' errorPrint. nm errorPrint. ')' errorPrint. |
1331 ' (' errorPrint. nm errorPrint. ')' errorPrint. |
1319 ]. |
1332 ]. |
1320 |
1333 |
1321 ok == #halted ifTrue:[ |
1334 ok == #halted ifTrue:[ |
1322 "/ that process was halted (win32 only) |
1335 "/ that process was halted (win32 only) |
1323 p state:#halted. |
1336 p state:#halted. |
1324 '; stopped it.' errorPrintCR. |
1337 '; stopped it.' errorPrintCR. |
1325 self suspend:p. |
1338 self suspend:p. |
1326 ] ifFalse:[ |
1339 ] ifFalse:[ |
1327 '; hard-terminate it.' errorPrintCR. |
1340 '; hard-terminate it.' errorPrintCR. |
1328 'Processor [info]: cleanup may take a while if stack is huge' infoPrintCR. |
1341 'Processor [info]: cleanup may take a while if stack is huge' infoPrintCR. |
1329 p state:#cleanup. |
1342 p state:#cleanup. |
1330 self terminateNoSignal:p. |
1343 self terminateNoSignal:p. |
1331 ] |
1344 ] |
1332 ] |
1345 ] |
1333 ] |
1346 ] |
1334 ]. |
1347 ]. |
1335 zombie notNil ifTrue:[ |
1348 zombie notNil ifTrue:[ |
1336 self class threadDestroy:zombie. |
1349 self class threadDestroy:zombie. |
1337 zombie := nil |
1350 zombie := nil |
1338 ]. |
1351 ]. |
1339 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1352 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1340 |
1353 |
1341 "Modified: / 23-07-2010 / 10:32:11 / cg" |
1354 "Modified: / 23-07-2010 / 10:32:11 / cg" |
1342 ! ! |
1355 ! ! |
1446 |
1459 |
1447 wasBlocked := OperatingSystem blockInterrupts. |
1460 wasBlocked := OperatingSystem blockInterrupts. |
1448 index := 1. |
1461 index := 1. |
1449 sz := KnownProcessIds size. |
1462 sz := KnownProcessIds size. |
1450 [index <= sz] whileTrue:[ |
1463 [index <= sz] whileTrue:[ |
1451 (KnownProcesses at:index) isNil ifTrue:[ |
1464 (KnownProcesses at:index) isNil ifTrue:[ |
1452 oldId := KnownProcessIds at:index. |
1465 oldId := KnownProcessIds at:index. |
1453 oldId notNil ifTrue:[ |
1466 oldId notNil ifTrue:[ |
1454 self class threadDestroy:oldId. |
1467 self class threadDestroy:oldId. |
1455 ]. |
1468 ]. |
1456 KnownProcesses at:index put:aProcess. |
1469 KnownProcesses at:index put:aProcess. |
1457 KnownProcessIds at:index put:aProcess id. |
1470 KnownProcessIds at:index put:aProcess id. |
1458 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1471 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1459 ^ self |
1472 ^ self |
1460 ]. |
1473 ]. |
1461 index := index + 1 |
1474 index := index + 1 |
1462 ]. |
1475 ]. |
1463 |
1476 |
1464 KnownProcessIds grow:index. |
1477 KnownProcessIds grow:index. |
1465 KnownProcessIds at:index put:aProcess id. |
1478 KnownProcessIds at:index put:aProcess id. |
1466 |
1479 |
1467 oldSize := KnownProcesses size. |
1480 oldSize := KnownProcesses size. |
1468 (index > oldSize) ifTrue:[ |
1481 (index > oldSize) ifTrue:[ |
1469 newShadow := WeakArray new:(oldSize * 2). |
1482 newShadow := WeakArray new:(oldSize * 2). |
1470 newShadow addDependent:self class. |
1483 newShadow addDependent:self class. |
1471 newShadow replaceFrom:1 with:KnownProcesses. |
1484 newShadow replaceFrom:1 with:KnownProcesses. |
1472 KnownProcesses := newShadow |
1485 KnownProcesses := newShadow |
1473 ]. |
1486 ]. |
1474 KnownProcesses at:index put:aProcess. |
1487 KnownProcesses at:index put:aProcess. |
1475 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1488 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1476 |
1489 |
1477 "Modified: 7.1.1997 / 16:48:39 / stefan" |
1490 "Modified: 7.1.1997 / 16:48:39 / stefan" |
1688 " |
1701 " |
1689 check for valid argument |
1702 check for valid argument |
1690 " |
1703 " |
1691 newPrio := prio. |
1704 newPrio := prio. |
1692 newPrio < 1 ifTrue:[ |
1705 newPrio < 1 ifTrue:[ |
1693 newPrio := 1. |
1706 newPrio := 1. |
1694 ] ifFalse:[ |
1707 ] ifFalse:[ |
1695 newPrio > HighestPriority ifTrue:[ |
1708 newPrio > HighestPriority ifTrue:[ |
1696 newPrio := HighestPriority |
1709 newPrio := HighestPriority |
1697 ] |
1710 ] |
1698 ]. |
1711 ]. |
1699 |
1712 |
1700 [ |
1713 [ |
1701 wasBlocked := OperatingSystem blockInterrupts. |
1714 wasBlocked := OperatingSystem blockInterrupts. |
1702 |
1715 |
1703 aProcess setPriority:newPrio. |
1716 aProcess setPriority:newPrio. |
1704 |
1717 |
1705 oldList := quiescentProcessLists at:oldPrio. |
1718 oldList := quiescentProcessLists at:oldPrio. |
1706 oldList notNil ifTrue:[ |
1719 oldList notNil ifTrue:[ |
1707 (oldList removeIdentical:aProcess ifAbsent:nil) notNil ifTrue:[ |
1720 (oldList removeIdentical:aProcess ifAbsent:nil) notNil ifTrue:[ |
1708 newList := quiescentProcessLists at:newPrio. |
1721 newList := quiescentProcessLists at:newPrio. |
1709 newList isNil ifTrue:[ |
1722 newList isNil ifTrue:[ |
1710 quiescentProcessLists at:newPrio put:(newList := LinkedList new). |
1723 quiescentProcessLists at:newPrio put:(newList := LinkedList new). |
1711 ]. |
1724 ]. |
1712 newList addLast:aProcess. |
1725 newList addLast:aProcess. |
1713 |
1726 |
1714 "if its the current process lowering its prio |
1727 "if its the current process lowering its prio |
1715 or another one raising, we have to reschedule" |
1728 or another one raising, we have to reschedule" |
1716 |
1729 |
1717 aProcess == activeProcess ifTrue:[ |
1730 aProcess == activeProcess ifTrue:[ |
1718 currentPriority := newPrio. |
1731 currentPriority := newPrio. |
1719 newPrio < oldPrio ifTrue:[ |
1732 newPrio < oldPrio ifTrue:[ |
1720 self threadSwitch:scheduler. |
1733 self threadSwitch:scheduler. |
1721 ] |
1734 ] |
1722 ] ifFalse:[ |
1735 ] ifFalse:[ |
1723 newPrio > currentPriority ifTrue:[ |
1736 newPrio > currentPriority ifTrue:[ |
1724 self threadSwitch:aProcess. |
1737 self threadSwitch:aProcess. |
1725 ] |
1738 ] |
1726 ]. |
1739 ]. |
1727 timeSliceNeededSemaphore notNil ifTrue:[ |
1740 timeSliceNeededSemaphore notNil ifTrue:[ |
1728 "/ tell timeslicer, that some work might be needed... |
1741 "/ tell timeslicer, that some work might be needed... |
1729 timeSliceNeededSemaphore signalIf. |
1742 timeSliceNeededSemaphore signalIf. |
1730 ] |
1743 ] |
1731 ] |
1744 ] |
1732 ] |
1745 ] |
1733 ] ensure:[ |
1746 ] ensure:[ |
1734 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1747 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1735 ] |
1748 ] |
1736 |
1749 |
1737 "Modified: / 4.8.1998 / 00:08:54 / cg" |
1750 "Modified: / 4.8.1998 / 00:08:54 / cg" |
1738 ! |
1751 ! |
1739 |
1752 |
1779 "ignore, if process is already dead" |
1792 "ignore, if process is already dead" |
1780 (aProcess isNil or:[aProcess isDead]) ifTrue:[^ false]. |
1793 (aProcess isNil or:[aProcess isDead]) ifTrue:[^ false]. |
1781 |
1794 |
1782 s := aProcess state. |
1795 s := aProcess state. |
1783 s == #osWait ifTrue:[ |
1796 s == #osWait ifTrue:[ |
1784 'Processor [warning]: bad resume: #osWait' errorPrintCR. |
1797 'Processor [warning]: bad resume: #osWait' errorPrintCR. |
1785 "/ MiniDebugger enterWithMessage:'bad resume: state osWait'. |
1798 "/ MiniDebugger enterWithMessage:'bad resume: state osWait'. |
1786 ^ false. |
1799 ^ false. |
1787 ]. |
1800 ]. |
1788 s == #stopped ifTrue:[ |
1801 s == #stopped ifTrue:[ |
1789 "by definition, stopped processes cannot be resumed" |
1802 "by definition, stopped processes cannot be resumed" |
1790 ^ false. |
1803 ^ false. |
1791 ]. |
1804 ]. |
1792 |
1805 |
1793 aProcess == activeProcess ifTrue:[ |
1806 aProcess == activeProcess ifTrue:[ |
1794 "special handling for waiting schedulers" |
1807 "special handling for waiting schedulers" |
1795 aProcess == scheduler ifTrue:[ |
1808 aProcess == scheduler ifTrue:[ |
1796 suspendScheduler := false. |
1809 suspendScheduler := false. |
1797 ]. |
1810 ]. |
1798 ^ false |
1811 ^ false |
1799 ]. |
1812 ]. |
1800 |
1813 |
1801 wasBlocked := OperatingSystem blockInterrupts. |
1814 wasBlocked := OperatingSystem blockInterrupts. |
1802 |
1815 |
1803 pri := aProcess priority. |
1816 pri := aProcess priority. |
1804 |
1817 |
1805 l := quiescentProcessLists at:pri. |
1818 l := quiescentProcessLists at:pri. |
1806 "if already running, ignore" |
1819 "if already running, ignore" |
1807 l notNil ifTrue:[ |
1820 l notNil ifTrue:[ |
1808 (l identityIndexOf:aProcess) ~~ 0 ifTrue:[ |
1821 (l identityIndexOf:aProcess) ~~ 0 ifTrue:[ |
1809 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1822 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1810 ^ false |
1823 ^ false |
1811 ] |
1824 ] |
1812 ] ifFalse:[ |
1825 ] ifFalse:[ |
1813 l := LinkedList new. |
1826 l := LinkedList new. |
1814 quiescentProcessLists at:pri put:l. |
1827 quiescentProcessLists at:pri put:l. |
1815 ]. |
1828 ]. |
1816 l addLast:aProcess. |
1829 l addLast:aProcess. |
1817 aProcess state:#run. |
1830 aProcess state:#run. |
1818 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1831 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1819 |
1832 |
1820 pri > currentPriority ifTrue:[ |
1833 pri > currentPriority ifTrue:[ |
1821 "must reschedule" |
1834 "must reschedule" |
1822 ^ true. |
1835 ^ true. |
1823 ]. |
1836 ]. |
1824 |
1837 |
1825 timeSliceNeededSemaphore notNil ifTrue:[ |
1838 timeSliceNeededSemaphore notNil ifTrue:[ |
1826 "/ tell timeslicer, that some work might be needed... |
1839 "/ tell timeslicer, that some work might be needed... |
1827 timeSliceNeededSemaphore signalIf. |
1840 timeSliceNeededSemaphore signalIf. |
1828 ]. |
1841 ]. |
1829 ^ false. |
1842 ^ false. |
1830 |
1843 |
1831 "Modified: / 29.7.1996 / 12:07:37 / cg" |
1844 "Modified: / 29.7.1996 / 12:07:37 / cg" |
1832 "Created: / 4.2.1998 / 20:58:28 / cg" |
1845 "Created: / 4.2.1998 / 20:58:28 / cg" |
1875 suspend:aProcess |
1888 suspend:aProcess |
1876 "remove the argument, aProcess from the list of runnable processes. |
1889 "remove the argument, aProcess from the list of runnable processes. |
1877 If the process is the current one, reschedule. |
1890 If the process is the current one, reschedule. |
1878 |
1891 |
1879 Notice: |
1892 Notice: |
1880 This method should only be called by Process>>suspend or |
1893 This method should only be called by Process>>suspend or |
1881 Process>>suspendWithState:" |
1894 Process>>suspendWithState:" |
1882 |
1895 |
1883 |pri l p wasBlocked| |
1896 |pri l p wasBlocked| |
1884 |
1897 |
1885 " |
1898 " |
1886 some debugging stuff |
1899 some debugging stuff |
1887 " |
1900 " |
1888 aProcess isNil ifTrue:[ |
1901 aProcess isNil ifTrue:[ |
1889 InvalidProcessSignal raiseRequestWith:aProcess errorString:'nil suspend'. |
1902 InvalidProcessSignal raiseRequestWith:aProcess errorString:'nil suspend'. |
1890 ^ self |
1903 ^ self |
1891 ]. |
1904 ]. |
1892 aProcess isDead ifTrue:[ |
1905 aProcess isDead ifTrue:[ |
1893 InvalidProcessSignal raiseRequestWith:aProcess errorString:'bad suspend: already dead'. |
1906 InvalidProcessSignal raiseRequestWith:aProcess errorString:'bad suspend: already dead'. |
1894 self threadSwitch:scheduler. |
1907 self threadSwitch:scheduler. |
1895 ^ self |
1908 ^ self |
1896 ]. |
1909 ]. |
1897 aProcess == scheduler ifTrue:[ |
1910 aProcess == scheduler ifTrue:[ |
1898 "only the scheduler may suspend itself" |
1911 "only the scheduler may suspend itself" |
1899 activeProcess == scheduler ifTrue:[ |
1912 activeProcess == scheduler ifTrue:[ |
1900 suspendScheduler := true. |
1913 suspendScheduler := true. |
1901 [suspendScheduler] whileTrue:[ |
1914 [suspendScheduler] whileTrue:[ |
1902 self dispatch. |
1915 self dispatch. |
1903 ]. |
1916 ]. |
1904 ^ self |
1917 ^ self |
1905 ]. |
1918 ]. |
1906 |
1919 |
1907 InvalidProcessSignal raiseRequestWith:aProcess errorString:'attempt to suspend scheduler'. |
1920 InvalidProcessSignal raiseRequestWith:aProcess errorString:'attempt to suspend scheduler'. |
1908 ^ self |
1921 ^ self |
1909 ]. |
1922 ]. |
1910 |
1923 |
1911 aProcess hasInterruptActions ifTrue:[ |
1924 aProcess hasInterruptActions ifTrue:[ |
1912 aProcess interrupt. |
1925 aProcess interrupt. |
1913 ]. |
1926 ]. |
1914 |
1927 |
1915 wasBlocked := OperatingSystem blockInterrupts. |
1928 wasBlocked := OperatingSystem blockInterrupts. |
1916 |
1929 |
1917 pri := aProcess priority. |
1930 pri := aProcess priority. |
1982 |
1995 |
1983 |pri id l wasBlocked| |
1996 |pri id l wasBlocked| |
1984 |
1997 |
1985 aProcess isNil ifTrue:[^ self]. |
1998 aProcess isNil ifTrue:[^ self]. |
1986 aProcess == scheduler ifTrue:[ |
1999 aProcess == scheduler ifTrue:[ |
1987 InvalidProcessSignal raiseWith:aProcess errorString:'attempt to terminate scheduler'. |
2000 InvalidProcessSignal raiseWith:aProcess errorString:'attempt to terminate scheduler'. |
1988 ^ self |
2001 ^ self |
1989 ]. |
2002 ]. |
1990 |
2003 |
1991 wasBlocked := OperatingSystem blockInterrupts. |
2004 wasBlocked := OperatingSystem blockInterrupts. |
1992 |
2005 |
1993 id := aProcess id. |
2006 id := aProcess id. |
1994 id isNil ifTrue:[ "already dead" |
2007 id isNil ifTrue:[ "already dead" |
1995 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
2008 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
1996 ^ self |
2009 ^ self |
1997 ]. |
2010 ]. |
1998 |
2011 |
1999 aProcess setId:nil state:#dead. |
2012 aProcess setId:nil state:#dead. |
2000 |
2013 |
2001 "remove the process from the runnable list" |
2014 "remove the process from the runnable list" |
2002 |
2015 |
2003 pri := aProcess priority. |
2016 pri := aProcess priority. |
2004 l := quiescentProcessLists at:pri. |
2017 l := quiescentProcessLists at:pri. |
2005 l notNil ifTrue:[ |
2018 l notNil ifTrue:[ |
2006 (l removeIdentical:aProcess ifAbsent:nil) "notNil ifTrue:[ |
2019 (l removeIdentical:aProcess ifAbsent:nil) "notNil ifTrue:[ |
2007 l isEmpty ifTrue:[ |
2020 l isEmpty ifTrue:[ |
2008 quiescentProcessLists at:pri put:nil |
2021 quiescentProcessLists at:pri put:nil |
2009 ] |
2022 ] |
2010 ]." |
2023 ]." |
2011 ]. |
2024 ]. |
2012 |
2025 |
2013 aProcess == activeProcess ifTrue:[ |
2026 aProcess == activeProcess ifTrue:[ |
2014 " |
2027 " |
2015 hard case - it's the currently running process |
2028 hard case - it's the currently running process |
2016 we must have the next active process destroy this one |
2029 we must have the next active process destroy this one |
2017 (we cannot destroy the chair we are sitting on ... :-) |
2030 (we cannot destroy the chair we are sitting on ... :-) |
2018 " |
2031 " |
2019 zombie notNil ifTrue:[ |
2032 zombie notNil ifTrue:[ |
2020 self error:'active process is zombie' mayProceed:true. |
2033 self error:'active process is zombie' mayProceed:true. |
2021 self class threadDestroy:zombie. |
2034 self class threadDestroy:zombie. |
2022 ]. |
2035 ]. |
2023 |
2036 |
2024 self unRemember:aProcess. |
2037 self unRemember:aProcess. |
2025 zombie := id. |
2038 zombie := id. |
2026 |
2039 |
2027 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
2040 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
2028 self threadSwitch:scheduler. |
2041 self threadSwitch:scheduler. |
2029 "not reached" |
2042 "not reached" |
2030 ^ self |
2043 ^ self |
2031 ]. |
2044 ]. |
2032 |
2045 |
2033 self unRemember:aProcess. |
2046 self unRemember:aProcess. |
2034 self class threadDestroy:id. |
2047 self class threadDestroy:id. |
2035 |
2048 |
2100 "recompute dynamic priorities." |
2113 "recompute dynamic priorities." |
2101 |
2114 |
2102 |processesToDecrease processesToIncrease| |
2115 |processesToDecrease processesToIncrease| |
2103 |
2116 |
2104 scheduledProcesses notNil ifTrue:[ |
2117 scheduledProcesses notNil ifTrue:[ |
2105 "/ this is written a bit cryptic - to avoid creation |
2118 "/ this is written a bit cryptic - to avoid creation |
2106 "/ of garbage objects (Id'sets) if possible. |
2119 "/ of garbage objects (Id'sets) if possible. |
2107 "/ since this runs 50 times a second and most of the |
2120 "/ since this runs 50 times a second and most of the |
2108 "/ time, no rescheduling is req'd |
2121 "/ time, no rescheduling is req'd |
2109 |
2122 |
2110 scheduledProcesses do:[:aProcess | |
2123 scheduledProcesses do:[:aProcess | |
2111 |range| |
2124 |range| |
2112 |
2125 |
2113 "/ decrease priority of processes that did run |
2126 "/ decrease priority of processes that did run |
2114 (range := aProcess priorityRange) notNil ifTrue:[ |
2127 (range := aProcess priorityRange) notNil ifTrue:[ |
2115 aProcess priority > range start ifTrue:[ |
2128 aProcess priority > range start ifTrue:[ |
2116 processesToDecrease isNil ifTrue:[ |
2129 processesToDecrease isNil ifTrue:[ |
2117 processesToDecrease := IdentitySet new. |
2130 processesToDecrease := IdentitySet new. |
2118 ]. |
2131 ]. |
2119 processesToDecrease add:aProcess. |
2132 processesToDecrease add:aProcess. |
2120 ] |
2133 ] |
2121 ] |
2134 ] |
2122 ]. |
2135 ]. |
2123 |
2136 |
2124 processesToDecrease notNil ifTrue:[ |
2137 processesToDecrease notNil ifTrue:[ |
2125 processesToDecrease do:[:aProcess | |
2138 processesToDecrease do:[:aProcess | |
2126 |newPri| |
2139 |newPri| |
2127 |
2140 |
2128 "/ newPri := aProcess priority - 1. |
2141 "/ newPri := aProcess priority - 1. |
2129 newPri := aProcess priorityRange start. |
2142 newPri := aProcess priorityRange start. |
2130 self changePriority:newPri for:aProcess. |
2143 self changePriority:newPri for:aProcess. |
2131 ]. |
2144 ]. |
2132 ]. |
2145 ]. |
2133 |
2146 |
2134 "/ and increase all prios of those that did not run, but are runnable |
2147 "/ and increase all prios of those that did not run, but are runnable |
2135 |
2148 |
2136 TimeSlicingPriorityLimit to:1 by:-1 do:[:i | |
2149 TimeSlicingPriorityLimit to:1 by:-1 do:[:i | |
2137 |list| |
2150 |list| |
2138 |
2151 |
2139 (list := quiescentProcessLists at:i) size > 0 ifTrue:[ |
2152 (list := quiescentProcessLists at:i) size > 0 ifTrue:[ |
2140 list linksDo:[:aProcess | |
2153 list linksDo:[:aProcess | |
2141 |range prio| |
2154 |range prio| |
2142 |
2155 |
2143 (range := aProcess priorityRange) notNil ifTrue:[ |
2156 (range := aProcess priorityRange) notNil ifTrue:[ |
2144 (processesToDecrease isNil |
2157 (processesToDecrease isNil |
2145 or:[(processesToDecrease includes:aProcess) not]) ifTrue:[ |
2158 or:[(processesToDecrease includes:aProcess) not]) ifTrue:[ |
2146 aProcess priority < range stop ifTrue:[ |
2159 aProcess priority < range stop ifTrue:[ |
2147 processesToIncrease isNil ifTrue:[ |
2160 processesToIncrease isNil ifTrue:[ |
2148 processesToIncrease := OrderedCollection new. |
2161 processesToIncrease := OrderedCollection new. |
2149 ]. |
2162 ]. |
2150 processesToIncrease add:aProcess |
2163 processesToIncrease add:aProcess |
2151 ] |
2164 ] |
2152 ] |
2165 ] |
2153 ] |
2166 ] |
2154 ] |
2167 ] |
2155 ] |
2168 ] |
2156 ]. |
2169 ]. |
2157 processesToIncrease notNil ifTrue:[ |
2170 processesToIncrease notNil ifTrue:[ |
2158 processesToIncrease do:[:aProcess | |
2171 processesToIncrease do:[:aProcess | |
2159 self changePriority:(aProcess priority + 1) for:aProcess. |
2172 self changePriority:(aProcess priority + 1) for:aProcess. |
2160 ]. |
2173 ]. |
2161 ]. |
2174 ]. |
2162 ]. |
2175 ]. |
2163 |
2176 |
2164 "Modified: / 30-07-2013 / 19:33:14 / cg" |
2177 "Modified: / 30-07-2013 / 19:33:14 / cg" |
2165 ! |
2178 ! |
2166 |
2179 |
2310 wasBlocked fd| |
2323 wasBlocked fd| |
2311 |
2324 |
2312 wasBlocked := OperatingSystem blockInterrupts. |
2325 wasBlocked := OperatingSystem blockInterrupts. |
2313 idx := readSemaphoreArray identityIndexOf:aSemaphore startingAt:1. |
2326 idx := readSemaphoreArray identityIndexOf:aSemaphore startingAt:1. |
2314 [idx ~~ 0] whileTrue:[ |
2327 [idx ~~ 0] whileTrue:[ |
2315 useIOInterrupts ifTrue:[ |
2328 useIOInterrupts ifTrue:[ |
2316 fd := readFdArray at:idx. |
2329 fd := readFdArray at:idx. |
2317 fd notNil ifTrue:[ |
2330 fd notNil ifTrue:[ |
2318 OperatingSystem disableIOInterruptsOn:fd |
2331 OperatingSystem disableIOInterruptsOn:fd |
2319 ]. |
2332 ]. |
2320 ]. |
2333 ]. |
2321 readFdArray at:idx put:nil. |
2334 readFdArray at:idx put:nil. |
2322 readSemaphoreArray at:idx put:nil. |
2335 readSemaphoreArray at:idx put:nil. |
2323 readCheckArray at:idx put:nil. |
2336 readCheckArray at:idx put:nil. |
2324 idx := readSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1. |
2337 idx := readSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1. |
2325 ]. |
2338 ]. |
2326 idx := writeSemaphoreArray identityIndexOf:aSemaphore startingAt:1. |
2339 idx := writeSemaphoreArray identityIndexOf:aSemaphore startingAt:1. |
2327 [idx ~~ 0] whileTrue:[ |
2340 [idx ~~ 0] whileTrue:[ |
2328 useIOInterrupts ifTrue:[ |
2341 useIOInterrupts ifTrue:[ |
2329 fd := writeFdArray at:idx. |
2342 fd := writeFdArray at:idx. |
2330 fd notNil ifTrue:[ |
2343 fd notNil ifTrue:[ |
2331 OperatingSystem disableIOInterruptsOn:fd |
2344 OperatingSystem disableIOInterruptsOn:fd |
2332 ]. |
2345 ]. |
2333 ]. |
2346 ]. |
2334 writeFdArray at:idx put:nil. |
2347 writeFdArray at:idx put:nil. |
2335 writeSemaphoreArray at:idx put:nil. |
2348 writeSemaphoreArray at:idx put:nil. |
2336 writeCheckArray at:idx put:nil. |
2349 writeCheckArray at:idx put:nil. |
2337 idx := writeSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1. |
2350 idx := writeSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1. |
2338 ]. |
2351 ]. |
2339 idx := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:1. |
2352 idx := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:1. |
2340 [idx ~~ 0] whileTrue:[ |
2353 [idx ~~ 0] whileTrue:[ |
2341 timeoutArray at:idx put:nil. |
2354 timeoutArray at:idx put:nil. |
2342 timeoutSemaphoreArray at:idx put:nil. |
2355 timeoutSemaphoreArray at:idx put:nil. |
2343 timeoutActionArray at:idx put:nil. |
2356 timeoutActionArray at:idx put:nil. |
2344 timeoutProcessArray at:idx put:nil. |
2357 timeoutProcessArray at:idx put:nil. |
2345 idx := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1. |
2358 idx := timeoutSemaphoreArray identityIndexOf:aSemaphore startingAt:idx+1. |
2346 ]. |
2359 ]. |
2347 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
2360 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
2348 |
2361 |
2349 "Modified: 4.8.1997 / 15:19:33 / cg" |
2362 "Modified: 4.8.1997 / 15:19:33 / cg" |
2350 ! |
2363 ! |
2446 |
2459 |
2447 "Here we assume, that for every triple (aSemaphore, aFileDescriptor, aBlock) |
2460 "Here we assume, that for every triple (aSemaphore, aFileDescriptor, aBlock) |
2448 aSemphore is never nil, but one of aFileDescriptor, aBlock may be nil" |
2461 aSemphore is never nil, but one of aFileDescriptor, aBlock may be nil" |
2449 |
2462 |
2450 aFileDescriptor isNil ifTrue:[ |
2463 aFileDescriptor isNil ifTrue:[ |
2451 idx := readSemaphoreArray identityIndexOf:aSemaphore or:nil. |
2464 idx := readSemaphoreArray identityIndexOf:aSemaphore or:nil. |
2452 idx == 0 ifTrue:[ |
2465 idx == 0 ifTrue:[ |
2453 "aSemaphore is not registered yet, have to create a new slot" |
2466 "aSemaphore is not registered yet, have to create a new slot" |
2454 readFdArray := readFdArray copyWith:nil. |
2467 readFdArray := readFdArray copyWith:nil. |
2455 readSemaphoreArray := readSemaphoreArray copyWith:aSemaphore. |
2468 readSemaphoreArray := readSemaphoreArray copyWith:aSemaphore. |
2456 readCheckArray := readCheckArray copyWith:aBlock. |
2469 readCheckArray := readCheckArray copyWith:aBlock. |
2457 ] ifFalse:[ |
2470 ] ifFalse:[ |
2458 slot := readSemaphoreArray at:idx. |
2471 slot := readSemaphoreArray at:idx. |
2459 slot isNil ifTrue:[ |
2472 slot isNil ifTrue:[ |
2460 readSemaphoreArray at:idx put:aSemaphore. |
2473 readSemaphoreArray at:idx put:aSemaphore. |
2461 readCheckArray at:idx put:aBlock |
2474 readCheckArray at:idx put:aBlock |
2462 ] ifFalse:[ |
2475 ] ifFalse:[ |
2463 "/ someone has already registered aSemaphore. |
2476 "/ someone has already registered aSemaphore. |
2464 "/ Check if it is the block changes... |
2477 "/ Check if it is the block changes... |
2465 (readCheckArray at:idx) notNil ifTrue:[ |
2478 (readCheckArray at:idx) notNil ifTrue:[ |
2466 (readCheckArray at:idx) ~~ aBlock ifTrue:[ |
2479 (readCheckArray at:idx) ~~ aBlock ifTrue:[ |
2467 'Processor [info]: checkblock changed for read-check' infoPrintCR. |
2480 'Processor [info]: checkblock changed for read-check' infoPrintCR. |
2468 readCheckArray at:idx put:aBlock. |
2481 readCheckArray at:idx put:aBlock. |
2469 ]. |
2482 ]. |
2470 ]. |
2483 ]. |
2471 ]. |
2484 ]. |
2472 ] |
2485 ] |
2473 ] ifFalse:[ |
2486 ] ifFalse:[ |
2474 idx := readFdArray identityIndexOf:aFileDescriptor or:nil. |
2487 idx := readFdArray identityIndexOf:aFileDescriptor or:nil. |
2475 idx == 0 ifTrue:[ |
2488 idx == 0 ifTrue:[ |
2476 "aFileDescriptor is not registered yet, have to create a new slot" |
2489 "aFileDescriptor is not registered yet, have to create a new slot" |
2477 readFdArray := readFdArray copyWith:aFileDescriptor. |
2490 readFdArray := readFdArray copyWith:aFileDescriptor. |
2478 readSemaphoreArray := readSemaphoreArray copyWith:aSemaphore. |
2491 readSemaphoreArray := readSemaphoreArray copyWith:aSemaphore. |
2479 readCheckArray := readCheckArray copyWith:aBlock. |
2492 readCheckArray := readCheckArray copyWith:aBlock. |
2480 ] ifFalse:[ |
2493 ] ifFalse:[ |
2481 slot := readFdArray at:idx. |
2494 slot := readFdArray at:idx. |
2482 slot isNil ifTrue:[ |
2495 slot isNil ifTrue:[ |
2483 readFdArray at:idx put:aFileDescriptor. |
2496 readFdArray at:idx put:aFileDescriptor. |
2484 readSemaphoreArray at:idx put:aSemaphore. |
2497 readSemaphoreArray at:idx put:aSemaphore. |
2485 readCheckArray at:idx put:aBlock |
2498 readCheckArray at:idx put:aBlock |
2486 ] ifFalse:[ |
2499 ] ifFalse:[ |
2487 "/ someone has already registered aFileDescriptor. |
2500 "/ someone has already registered aFileDescriptor. |
2488 "/ Check if it is the semaphore or block changes... |
2501 "/ Check if it is the semaphore or block changes... |
2489 (readSemaphoreArray at:idx) ~~ aSemaphore ifTrue:[ |
2502 (readSemaphoreArray at:idx) ~~ aSemaphore ifTrue:[ |
2490 'Processor [info]: sema changed for read-check' infoPrintCR. |
2503 'Processor [info]: sema changed for read-check' infoPrintCR. |
2491 readSemaphoreArray at:idx put:aSemaphore. |
2504 readSemaphoreArray at:idx put:aSemaphore. |
2492 ]. |
2505 ]. |
2493 (readCheckArray at:idx) ~~ aBlock ifTrue:[ |
2506 (readCheckArray at:idx) ~~ aBlock ifTrue:[ |
2494 'Processor [info]: checkblock changed for read-check' infoPrintCR. |
2507 'Processor [info]: checkblock changed for read-check' infoPrintCR. |
2495 readCheckArray at:idx put:aBlock. |
2508 readCheckArray at:idx put:aBlock. |
2496 ]. |
2509 ]. |
2497 ]. |
2510 ]. |
2498 ]. |
2511 ]. |
2499 (useIOInterrupts and:[slot isNil]) ifTrue:[ |
2512 (useIOInterrupts and:[slot isNil]) ifTrue:[ |
2500 OperatingSystem enableIOInterruptsOn:aFileDescriptor |
2513 OperatingSystem enableIOInterruptsOn:aFileDescriptor |
2501 ]. |
2514 ]. |
2502 ]. |
2515 ]. |
2503 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
2516 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
2504 |
2517 |
2505 "Modified: 4.8.1997 / 15:20:45 / cg" |
2518 "Modified: 4.8.1997 / 15:20:45 / cg" |
2506 ! |
2519 ! |
2547 |
2560 |
2548 "Here we assume, that for every triple (aSemaphore, aFileDescriptor, aBlock) |
2561 "Here we assume, that for every triple (aSemaphore, aFileDescriptor, aBlock) |
2549 aSemphore is never nil, but one of aFileDescriptor, aBlock may be nil" |
2562 aSemphore is never nil, but one of aFileDescriptor, aBlock may be nil" |
2550 |
2563 |
2551 aFileDescriptor isNil ifTrue:[ |
2564 aFileDescriptor isNil ifTrue:[ |
2552 idx := writeSemaphoreArray identityIndexOf:aSemaphore or:nil. |
2565 idx := writeSemaphoreArray identityIndexOf:aSemaphore or:nil. |
2553 idx == 0 ifTrue:[ |
2566 idx == 0 ifTrue:[ |
2554 "aSemaphore is not registered yet, have to create a new slot" |
2567 "aSemaphore is not registered yet, have to create a new slot" |
2555 writeFdArray := writeFdArray copyWith:nil. |
2568 writeFdArray := writeFdArray copyWith:nil. |
2556 writeSemaphoreArray := writeSemaphoreArray copyWith:aSemaphore. |
2569 writeSemaphoreArray := writeSemaphoreArray copyWith:aSemaphore. |
2557 writeCheckArray := writeCheckArray copyWith:aBlock. |
2570 writeCheckArray := writeCheckArray copyWith:aBlock. |
2558 ] ifFalse:[ |
2571 ] ifFalse:[ |
2559 slot := writeSemaphoreArray at:idx. |
2572 slot := writeSemaphoreArray at:idx. |
2560 slot isNil ifTrue:[ |
2573 slot isNil ifTrue:[ |
2561 writeSemaphoreArray at:idx put:aSemaphore. |
2574 writeSemaphoreArray at:idx put:aSemaphore. |
2562 writeCheckArray at:idx put:aBlock |
2575 writeCheckArray at:idx put:aBlock |
2563 ] ifFalse:[ |
2576 ] ifFalse:[ |
2564 "/ someone has already registered aSemaphore. |
2577 "/ someone has already registered aSemaphore. |
2565 "/ Check if it is the block changes... |
2578 "/ Check if it is the block changes... |
2566 (writeCheckArray at:idx) notNil ifTrue:[ |
2579 (writeCheckArray at:idx) notNil ifTrue:[ |
2567 (writeCheckArray at:idx) ~~ aBlock ifTrue:[ |
2580 (writeCheckArray at:idx) ~~ aBlock ifTrue:[ |
2568 'Processor [info]: checkblock changed for write-check' infoPrintCR. |
2581 'Processor [info]: checkblock changed for write-check' infoPrintCR. |
2569 writeCheckArray at:idx put:aBlock. |
2582 writeCheckArray at:idx put:aBlock. |
2570 ]. |
2583 ]. |
2571 ]. |
2584 ]. |
2572 ]. |
2585 ]. |
2573 ] |
2586 ] |
2574 ] ifFalse:[ |
2587 ] ifFalse:[ |
2575 idx := writeFdArray identityIndexOf:aFileDescriptor or:nil. |
2588 idx := writeFdArray identityIndexOf:aFileDescriptor or:nil. |
2576 idx == 0 ifTrue:[ |
2589 idx == 0 ifTrue:[ |
2577 "aFileDescriptor is not registered yet, have to create a new slot" |
2590 "aFileDescriptor is not registered yet, have to create a new slot" |
2578 writeFdArray := writeFdArray copyWith:aFileDescriptor. |
2591 writeFdArray := writeFdArray copyWith:aFileDescriptor. |
2579 writeSemaphoreArray := writeSemaphoreArray copyWith:aSemaphore. |
2592 writeSemaphoreArray := writeSemaphoreArray copyWith:aSemaphore. |
2580 writeCheckArray := writeCheckArray copyWith:aBlock. |
2593 writeCheckArray := writeCheckArray copyWith:aBlock. |
2581 ] ifFalse:[ |
2594 ] ifFalse:[ |
2582 slot := writeFdArray at:idx. |
2595 slot := writeFdArray at:idx. |
2583 slot isNil ifTrue:[ |
2596 slot isNil ifTrue:[ |
2584 writeFdArray at:idx put:aFileDescriptor. |
2597 writeFdArray at:idx put:aFileDescriptor. |
2585 writeSemaphoreArray at:idx put:aSemaphore. |
2598 writeSemaphoreArray at:idx put:aSemaphore. |
2586 writeCheckArray at:idx put:aBlock |
2599 writeCheckArray at:idx put:aBlock |
2587 ] ifFalse:[ |
2600 ] ifFalse:[ |
2588 "/ someone has already registered aFileDescriptor. |
2601 "/ someone has already registered aFileDescriptor. |
2589 "/ Check if it is the semaphore or block changes... |
2602 "/ Check if it is the semaphore or block changes... |
2590 (writeSemaphoreArray at:idx) ~~ aSemaphore ifTrue:[ |
2603 (writeSemaphoreArray at:idx) ~~ aSemaphore ifTrue:[ |
2591 'Processor [info]: sema changed for write-check' infoPrintCR. |
2604 'Processor [info]: sema changed for write-check' infoPrintCR. |
2592 writeSemaphoreArray at:idx put:aSemaphore. |
2605 writeSemaphoreArray at:idx put:aSemaphore. |
2593 ]. |
2606 ]. |
2594 (writeCheckArray at:idx) ~~ aBlock ifTrue:[ |
2607 (writeCheckArray at:idx) ~~ aBlock ifTrue:[ |
2595 'Processor [info]: checkblock changed for write-check' infoPrintCR. |
2608 'Processor [info]: checkblock changed for write-check' infoPrintCR. |
2596 writeCheckArray at:idx put:aBlock. |
2609 writeCheckArray at:idx put:aBlock. |
2597 ]. |
2610 ]. |
2598 ]. |
2611 ]. |
2599 ]. |
2612 ]. |
2600 (useIOInterrupts and:[slot isNil]) ifTrue:[ |
2613 (useIOInterrupts and:[slot isNil]) ifTrue:[ |
2601 OperatingSystem enableIOInterruptsOn:aFileDescriptor |
2614 OperatingSystem enableIOInterruptsOn:aFileDescriptor |
2602 ]. |
2615 ]. |
2603 ]. |
2616 ]. |
2604 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
2617 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
2605 |
2618 |
2606 "Modified: 4.8.1997 / 15:21:49 / cg" |
2619 "Modified: 4.8.1997 / 15:21:49 / cg" |
2607 ! |
2620 ! |
2857 |
2870 |
2858 |action| |
2871 |action| |
2859 |
2872 |
2860 action := [anExternalFunction callWith:argument]. |
2873 action := [anExternalFunction callWith:argument]. |
2861 ^ self |
2874 ^ self |
2862 addTimedBlock:action |
2875 addTimedBlock:action |
2863 for:aProcess |
2876 for:aProcess |
2864 atMilliseconds:milliTime. |
2877 atMilliseconds:milliTime. |
2865 |
2878 |
2866 "Created: 23.9.1996 / 14:29:30 / cg" |
2879 "Created: 23.9.1996 / 14:29:30 / cg" |
2867 "Modified: 23.9.1996 / 14:34:57 / cg" |
2880 "Modified: 23.9.1996 / 14:34:57 / cg" |
2868 ! |
2881 ! |
2869 |
2882 |
2870 evaluateTimeouts |
2883 evaluateTimeouts |
2871 "walk through timeouts and evaluate blocks or signal semas that need to be .." |
2884 "walk through timeouts and evaluate blocks or signal semas that need to be .." |
2872 |
2885 |
2873 |sema now aTime block blocksAndProcessesToEvaluate |
2886 |sema now aTime block blocksAndProcessesToEvaluate |
2874 firstBlockToEvaluate firstProcess |
2887 firstBlockToEvaluate firstProcess |
2875 n "{ Class: SmallInteger }" |
2888 n "{ Class: SmallInteger }" |
2876 indexOfLastTimeout "{ Class: SmallInteger }" |
2889 indexOfLastTimeout "{ Class: SmallInteger }" |
2877 halfSize "{ Class: SmallInteger }" |
2890 halfSize "{ Class: SmallInteger }" |
2878 wasBlocked p| |
2891 wasBlocked p| |
2879 |
2892 |
2880 |
2893 |
2881 anyTimeouts ifFalse:[ ^ self]. |
2894 anyTimeouts ifFalse:[ ^ self]. |
2882 anyTimeouts := false. |
2895 anyTimeouts := false. |
2883 |
2896 |
2884 "have to collect the blocks first, then evaluate them. |
2897 "have to collect the blocks first, then evaluate them. |
2885 This avoids problems due to newly inserted blocks." |
2898 This avoids problems due to newly inserted blocks." |
2886 |
2899 |
2887 "/ notice: the code looks uglier than seems to be required; |
2900 "/ notice: the code looks uglier than seems to be required; |
2888 "/ the observation is that in almost all cases, only a single block (or no block at all) |
2901 "/ the observation is that in almost all cases, only a single block (or no block at all) |
2889 "/ is found in the loops below. |
2902 "/ is found in the loops below. |
2893 "/ looks ugly, but as this is called very often, reduces idle allocation by a lot. |
2906 "/ looks ugly, but as this is called very often, reduces idle allocation by a lot. |
2894 |
2907 |
2895 now := OperatingSystem getMillisecondTime. |
2908 now := OperatingSystem getMillisecondTime. |
2896 n := timeoutArray size. |
2909 n := timeoutArray size. |
2897 1 to:n do:[:index | |
2910 1 to:n do:[:index | |
2898 aTime := timeoutArray at:index. |
2911 aTime := timeoutArray at:index. |
2899 aTime notNil ifTrue:[ |
2912 aTime notNil ifTrue:[ |
2900 (OperatingSystem millisecondTime:now isAfter:aTime) ifTrue:[ |
2913 (OperatingSystem millisecondTime:now isAfter:aTime) ifTrue:[ |
2901 "this one should be triggered" |
2914 "this one should be triggered" |
2902 |
2915 |
2903 sema := timeoutSemaphoreArray at:index. |
2916 sema := timeoutSemaphoreArray at:index. |
2904 sema notNil ifTrue:[ |
2917 sema notNil ifTrue:[ |
2905 timeoutSemaphoreArray at:index put:nil. |
2918 timeoutSemaphoreArray at:index put:nil. |
2906 sema signalOnce. |
2919 sema signalOnce. |
2907 ] ifFalse:[ |
2920 ] ifFalse:[ |
2908 "to support pure-events" |
2921 "to support pure-events" |
2909 block := timeoutActionArray at:index. |
2922 block := timeoutActionArray at:index. |
2910 block notNil ifTrue:[ |
2923 block notNil ifTrue:[ |
2911 firstBlockToEvaluate isNil ifTrue:[ |
2924 firstBlockToEvaluate isNil ifTrue:[ |
2912 firstBlockToEvaluate := block. |
2925 firstBlockToEvaluate := block. |
2913 firstProcess := timeoutProcessArray at:index. |
2926 firstProcess := timeoutProcessArray at:index. |
2914 ] ifFalse:[ |
2927 ] ifFalse:[ |
2915 blocksAndProcessesToEvaluate isNil ifTrue:[ |
2928 blocksAndProcessesToEvaluate isNil ifTrue:[ |
2916 blocksAndProcessesToEvaluate := OrderedCollection |
2929 blocksAndProcessesToEvaluate := OrderedCollection |
2917 with:firstBlockToEvaluate |
2930 with:firstBlockToEvaluate |
2918 with:firstProcess. |
2931 with:firstProcess. |
2919 ]. |
2932 ]. |
2920 blocksAndProcessesToEvaluate add:block. |
2933 blocksAndProcessesToEvaluate add:block. |
2921 blocksAndProcessesToEvaluate add:(timeoutProcessArray at:index). |
2934 blocksAndProcessesToEvaluate add:(timeoutProcessArray at:index). |
2922 ]. |
2935 ]. |
2923 timeoutActionArray at:index put:nil. |
2936 timeoutActionArray at:index put:nil. |
2924 timeoutProcessArray at:index put:nil. |
2937 timeoutProcessArray at:index put:nil. |
2925 ] |
2938 ] |
2926 ]. |
2939 ]. |
2927 timeoutArray at:index put:nil. |
2940 timeoutArray at:index put:nil. |
2928 ] ifFalse:[ |
2941 ] ifFalse:[ |
2929 "there are still pending timeouts" |
2942 "there are still pending timeouts" |
2930 anyTimeouts := true. |
2943 anyTimeouts := true. |
2931 indexOfLastTimeout := index. |
2944 indexOfLastTimeout := index. |
2932 ] |
2945 ] |
2933 ] |
2946 ] |
2934 ]. |
2947 ]. |
2935 |
2948 |
2936 "shrink the arrays, if they are 50% free" |
2949 "shrink the arrays, if they are 50% free" |
2937 n > 20 ifTrue:[ |
2950 n > 20 ifTrue:[ |
2938 halfSize := n // 2. |
2951 halfSize := n // 2. |
2939 indexOfLastTimeout < halfSize ifTrue:[ |
2952 indexOfLastTimeout < halfSize ifTrue:[ |
2940 wasBlocked := OperatingSystem blockInterrupts. |
2953 wasBlocked := OperatingSystem blockInterrupts. |
2941 (timeoutArray at:indexOfLastTimeout+1) isNil ifTrue:[ "/ no new timeouts arrived |
2954 (timeoutArray at:indexOfLastTimeout+1) isNil ifTrue:[ "/ no new timeouts arrived |
2942 timeoutArray := timeoutArray copyTo:halfSize. |
2955 timeoutArray := timeoutArray copyTo:halfSize. |
2943 timeoutSemaphoreArray := timeoutSemaphoreArray copyTo:halfSize. |
2956 timeoutSemaphoreArray := timeoutSemaphoreArray copyTo:halfSize. |
2944 timeoutActionArray := timeoutActionArray copyTo:halfSize. |
2957 timeoutActionArray := timeoutActionArray copyTo:halfSize. |
2945 timeoutProcessArray := timeoutProcessArray copyTo:halfSize. |
2958 timeoutProcessArray := timeoutProcessArray copyTo:halfSize. |
2946 ]. |
2959 ]. |
2947 wasBlocked ifFalse:[ OperatingSystem unblockInterrupts ]. |
2960 wasBlocked ifFalse:[ OperatingSystem unblockInterrupts ]. |
2948 ]. |
2961 ]. |
2949 ]. |
2962 ]. |
2950 |
2963 |
2951 blocksAndProcessesToEvaluate isNil ifTrue:[ |
2964 blocksAndProcessesToEvaluate isNil ifTrue:[ |
2952 firstBlockToEvaluate notNil ifTrue:[ |
2965 firstBlockToEvaluate notNil ifTrue:[ |
2953 (firstProcess isNil or:[firstProcess == scheduler or:[PureEventDriven]]) ifTrue:[ |
2966 (firstProcess isNil or:[firstProcess == scheduler or:[PureEventDriven]]) ifTrue:[ |
2954 firstBlockToEvaluate value |
2967 firstBlockToEvaluate value |
2955 ] ifFalse:[ |
2968 ] ifFalse:[ |
2956 firstProcess isDead ifTrue:[ |
2969 firstProcess isDead ifTrue:[ |
2957 "/ a timedBlock for a process which has already terminated |
2970 "/ a timedBlock for a process which has already terminated |
2958 "/ issue a warning and do not execute it. |
2971 "/ issue a warning and do not execute it. |
2959 "/ (exeuting here may be dangerous, since it would run at scheduler priority here, |
2972 "/ (exeuting here may be dangerous, since it would run at scheduler priority here, |
2960 "/ and thereby could block the whole smalltalk system. |
2973 "/ and thereby could block the whole smalltalk system. |
2961 "/ For this reason is it IGNORED here.) |
2974 "/ For this reason is it IGNORED here.) |
2962 "/ Could handle it in timeoutProcess, but we don't, |
2975 "/ Could handle it in timeoutProcess, but we don't, |
2963 "/ because otherwise timeouts might be reissued forever... |
2976 "/ because otherwise timeouts might be reissued forever... |
2964 "/ (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[ |
2977 "/ (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[ |
2965 "/ timeoutHandlerProcess interruptWith:block. |
2978 "/ timeoutHandlerProcess interruptWith:block. |
2966 "/ ] ifFalse:[ |
2979 "/ ] ifFalse:[ |
2967 ('ProcessorScheduler [warning]: cannot evaluate timedBlock for dead process: ''' , firstProcess name , '''') infoPrintCR. |
2980 ('ProcessorScheduler [warning]: cannot evaluate timedBlock for dead process: ''' , firstProcess name , '''') infoPrintCR. |
2968 ('ProcessorScheduler [warning]: the timedBlock is: ' , firstBlockToEvaluate displayString) infoPrintCR. |
2981 ('ProcessorScheduler [warning]: the timedBlock is: ' , firstBlockToEvaluate displayString) infoPrintCR. |
2969 "/ ]. |
2982 "/ ]. |
2970 ] ifFalse:[ |
2983 ] ifFalse:[ |
2971 firstProcess interruptWith:firstBlockToEvaluate |
2984 firstProcess interruptWith:firstBlockToEvaluate |
2972 ] |
2985 ] |
2973 ] |
2986 ] |
2974 ]. |
2987 ]. |
2975 ] ifFalse:[ |
2988 ] ifFalse:[ |
2976 n := blocksAndProcessesToEvaluate size. |
2989 n := blocksAndProcessesToEvaluate size. |
2977 1 to:n by:2 do:[:index | |
2990 1 to:n by:2 do:[:index | |
2978 block := blocksAndProcessesToEvaluate at:index. |
2991 block := blocksAndProcessesToEvaluate at:index. |
2979 p := blocksAndProcessesToEvaluate at:index+1. |
2992 p := blocksAndProcessesToEvaluate at:index+1. |
2980 (p isNil or:[p == scheduler or:[PureEventDriven]]) ifTrue:[ |
2993 (p isNil or:[p == scheduler or:[PureEventDriven]]) ifTrue:[ |
2981 block value |
2994 block value |
2982 ] ifFalse:[ |
2995 ] ifFalse:[ |
2983 p isDead ifTrue:[ |
2996 p isDead ifTrue:[ |
2984 "/ a timedBlock for a process which has already terminated |
2997 "/ a timedBlock for a process which has already terminated |
2985 "/ issue a warning and do not execute it. |
2998 "/ issue a warning and do not execute it. |
2986 "/ (exeuting here may be dangerous, since it would run at scheduler priority here, |
2999 "/ (exeuting here may be dangerous, since it would run at scheduler priority here, |
2987 "/ and thereby could block the whole smalltalk system. |
3000 "/ and thereby could block the whole smalltalk system. |
2988 "/ For this reason is it IGNORED here.) |
3001 "/ For this reason is it IGNORED here.) |
2989 "/ Could handle it in timeoutProcess, but we don't, |
3002 "/ Could handle it in timeoutProcess, but we don't, |
2990 "/ because otherwise timeouts might be reissued forever... |
3003 "/ because otherwise timeouts might be reissued forever... |
2991 "/ (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[ |
3004 "/ (timeoutHandlerProcess notNil and:[timeoutHandlerProcess isDead not]) ifTrue:[ |
2992 "/ timeoutHandlerProcess interruptWith:block. |
3005 "/ timeoutHandlerProcess interruptWith:block. |
2993 "/ ] ifFalse:[ |
3006 "/ ] ifFalse:[ |
2994 ('ProcessorScheduler [warning]: cannot evaluate timedBlock for dead process: ''' , p name , '''') infoPrintCR. |
3007 ('ProcessorScheduler [warning]: cannot evaluate timedBlock for dead process: ''' , p name , '''') infoPrintCR. |
2995 ('ProcessorScheduler [warning]: the timedBlock is: ' , block displayString) infoPrintCR. |
3008 ('ProcessorScheduler [warning]: the timedBlock is: ' , block displayString) infoPrintCR. |
2996 "/ ]. |
3009 "/ ]. |
2997 ] ifFalse:[ |
3010 ] ifFalse:[ |
2998 p interruptWith:block |
3011 p interruptWith:block |
2999 ] |
3012 ] |
3000 ] |
3013 ] |
3001 ] |
3014 ] |
3002 ]. |
3015 ]. |
3003 |
3016 |
3004 "Modified: / 30-07-2013 / 19:33:24 / cg" |
3017 "Modified: / 30-07-2013 / 19:33:24 / cg" |
3005 ! |
3018 ! |
3006 |
3019 |
3030 |index "{ Class: SmallInteger }" |
3043 |index "{ Class: SmallInteger }" |
3031 wasBlocked| |
3044 wasBlocked| |
3032 |
3045 |
3033 index := anID. |
3046 index := anID. |
3034 (index > 0) ifTrue:[ |
3047 (index > 0) ifTrue:[ |
3035 wasBlocked := OperatingSystem blockInterrupts. |
3048 wasBlocked := OperatingSystem blockInterrupts. |
3036 |
3049 |
3037 timeoutArray at:index put:nil. |
3050 timeoutArray at:index put:nil. |
3038 timeoutActionArray at:index put:nil. |
3051 timeoutActionArray at:index put:nil. |
3039 timeoutSemaphoreArray at:index put:nil. |
3052 timeoutSemaphoreArray at:index put:nil. |
3040 timeoutProcessArray at:index put:nil. |
3053 timeoutProcessArray at:index put:nil. |
3041 |
3054 |
3042 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
3055 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
3043 ] |
3056 ] |
3044 |
3057 |
3045 "Created: 23.9.1996 / 14:32:33 / cg" |
3058 "Created: 23.9.1996 / 14:32:33 / cg" |
3046 "Modified: 23.9.1996 / 14:35:09 / cg" |
3059 "Modified: 23.9.1996 / 14:35:09 / cg" |
3047 ! |
3060 ! |
3048 |
3061 |
3049 timeoutHandlerProcess |
3062 timeoutHandlerProcess |
3050 (timeoutHandlerProcess isNil or:[timeoutHandlerProcess isDead]) ifTrue:[ |
3063 (timeoutHandlerProcess isNil or:[timeoutHandlerProcess isDead]) ifTrue:[ |
3051 timeoutHandlerProcess := |
3064 timeoutHandlerProcess := |
3052 [ |
3065 [ |
3053 [ |
3066 [ |
3054 self timeoutHandlerProcessLoop. |
3067 self timeoutHandlerProcessLoop. |
3055 ] ensure:[ |
3068 ] ensure:[ |
3056 timeoutHandlerProcess := nil |
3069 timeoutHandlerProcess := nil |
3057 ]. |
3070 ]. |
3058 ] newProcess. |
3071 ] newProcess. |
3059 |
3072 |
3060 timeoutHandlerProcess |
3073 timeoutHandlerProcess |
3061 priority:TimingPriority; |
3074 priority:TimingPriority; |
3062 name:'timeout handler'; |
3075 name:'timeout handler'; |
3063 beSystemProcess; |
3076 beSystemProcess; |
3064 resume. |
3077 resume. |
3065 ]. |
3078 ]. |
3066 ^ timeoutHandlerProcess. |
3079 ^ timeoutHandlerProcess. |
3067 |
3080 |
3068 "Modified: / 20-07-2006 / 09:52:27 / cg" |
3081 "Modified: / 20-07-2006 / 09:52:27 / cg" |
3069 ! |
3082 ! |
3131 |
3144 |
3132 wasBlocked := OperatingSystem unblockInterrupts. |
3145 wasBlocked := OperatingSystem unblockInterrupts. |
3133 |
3146 |
3134 newProcessMaybeReady := false. |
3147 newProcessMaybeReady := false. |
3135 readableResultFdArray size < readFdArray size ifTrue:[ |
3148 readableResultFdArray size < readFdArray size ifTrue:[ |
3136 readableResultFdArray := Array new:(40 max:readFdArray size). |
3149 readableResultFdArray := Array new:(40 max:readFdArray size). |
3137 ]. |
3150 ]. |
3138 writableResultFdArray size < writeFdArray size ifTrue:[ |
3151 writableResultFdArray size < writeFdArray size ifTrue:[ |
3139 writableResultFdArray := Array new:(40 max:writeFdArray size). |
3152 writableResultFdArray := Array new:(40 max:writeFdArray size). |
3140 ]. |
3153 ]. |
3141 |
3154 |
3142 OperatingSystem isMSWINDOWSlike ifTrue:[ |
3155 OperatingSystem isMSWINDOWSlike ifTrue:[ |
3143 "/ |
3156 "/ |
3144 "/ win32 does a WaitForMultipleObjects in select... |
3157 "/ win32 does a WaitForMultipleObjects in select... |
3145 "/ unix waits for SIGCHLD |
3158 "/ unix waits for SIGCHLD |
3146 "/ |
3159 "/ |
3147 osChildExitActions keysDo:[:eachPid| |
3160 osChildExitActions keysDo:[:eachPid| |
3148 eachPid address = 0 ifTrue:[ |
3161 eachPid address = 0 ifTrue:[ |
3149 'Processor: remove 0 handle pid: ' infoPrint. eachPid infoPrintCR. |
3162 'Processor: remove 0 handle pid: ' infoPrint. eachPid infoPrintCR. |
3150 osChildExitActions safeRemoveKey:eachPid. |
3163 osChildExitActions safeRemoveKey:eachPid. |
3151 ] ifFalse:[ |
3164 ] ifFalse:[ |
3152 pidsFinished isNil ifTrue:[ |
3165 pidsFinished isNil ifTrue:[ |
3153 exceptArray := osChildExitActions keyArray. |
3166 exceptArray := osChildExitActions keyArray. |
3154 pidsFinished := Array new:osChildExitActions size. |
3167 pidsFinished := Array new:osChildExitActions size. |
3155 ]. |
3168 ]. |
3156 ]. |
3169 ]. |
3157 ]. |
3170 ]. |
3158 ]. |
3171 ]. |
3159 |
3172 |
3160 nReady := OperatingSystem |
3173 nReady := OperatingSystem |
3161 selectOnAnyReadable:readFdArray |
3174 selectOnAnyReadable:readFdArray |
3162 writable:writeFdArray |
3175 writable:writeFdArray |
3163 exception:exceptArray |
3176 exception:exceptArray |
3164 readableInto:readableResultFdArray |
3177 readableInto:readableResultFdArray |
3165 writableInto:writableResultFdArray |
3178 writableInto:writableResultFdArray |
3166 exceptionInto:pidsFinished |
3179 exceptionInto:pidsFinished |
3167 withTimeOut:millis. |
3180 withTimeOut:millis. |
3168 |
3181 |
3169 wasBlocked ifTrue:[ |
3182 wasBlocked ifTrue:[ |
3170 OperatingSystem blockInterrupts. |
3183 OperatingSystem blockInterrupts. |
3171 ]. |
3184 ]. |
3172 |
3185 |
3173 nReady <= 0 ifTrue:[ |
3186 nReady <= 0 ifTrue:[ |
3174 "/ either still nothing to do, |
3187 "/ either still nothing to do, |
3175 "/ or error (which should not happen) |
3188 "/ or error (which should not happen) |
3176 |
3189 |
3177 (nReady < 0 and:[(err := OperatingSystem lastErrorSymbol) notNil]) ifTrue:[ |
3190 (nReady < 0 and:[(err := OperatingSystem lastErrorSymbol) notNil]) ifTrue:[ |
3178 err == #EBADF ifTrue:[ |
3191 err == #EBADF ifTrue:[ |
3179 "/ mhmh - one of the fd's given to me is corrupt. |
3192 "/ mhmh - one of the fd's given to me is corrupt. |
3180 "/ find out which one .... and remove it |
3193 "/ find out which one .... and remove it |
3181 self removeCorruptedFds |
3194 self removeCorruptedFds |
3182 ] ifFalse:[ |
3195 ] ifFalse:[ |
3183 err == #ENOENT ifTrue:[ |
3196 err == #ENOENT ifTrue:[ |
3184 'Processor [warning]: ENOENT in select; rd=' infoPrint. |
3197 'Processor [warning]: ENOENT in select; rd=' infoPrint. |
3185 readFdArray infoPrint. |
3198 readFdArray infoPrint. |
3186 ' wr=' infoPrint. |
3199 ' wr=' infoPrint. |
3187 writeFdArray infoPrintCR. |
3200 writeFdArray infoPrintCR. |
3188 ] ifFalse:[ |
3201 ] ifFalse:[ |
3189 'Processor [warning]: error in select: ' infoPrint. err infoPrintCR. |
3202 'Processor [warning]: error in select: ' infoPrint. err infoPrintCR. |
3190 ] |
3203 ] |
3191 ]. |
3204 ]. |
3192 ] |
3205 ] |
3193 ] ifFalse:[ |
3206 ] ifFalse:[ |
3194 readyIndex := 1. |
3207 readyIndex := 1. |
3195 [nReady > 0 |
3208 [nReady > 0 |
3196 and:[ readyIndex <= readableResultFdArray size |
3209 and:[ readyIndex <= readableResultFdArray size |
3197 and:[ (fd := readableResultFdArray at:readyIndex) notNil ]]] |
3210 and:[ (fd := readableResultFdArray at:readyIndex) notNil ]]] |
3198 whileTrue:[ |
3211 whileTrue:[ |
3199 index := readFdArray identityIndexOf:fd. |
3212 index := readFdArray identityIndexOf:fd. |
3200 index ~~ 0 ifTrue:[ |
3213 index ~~ 0 ifTrue:[ |
3201 action := readCheckArray at:index. |
3214 action := readCheckArray at:index. |
3202 sema := readSemaphoreArray at:index. |
3215 sema := readSemaphoreArray at:index. |
3203 sema notNil ifTrue:[ |
3216 sema notNil ifTrue:[ |
3204 sema signalOnce. |
3217 sema signalOnce. |
3205 newProcessMaybeReady := true. |
3218 newProcessMaybeReady := true. |
3206 action isNil ifTrue:[ |
3219 action isNil ifTrue:[ |
3207 "before May 2014 we disabled the sema in the caller after wakeup. |
3220 "before May 2014 we disabled the sema in the caller after wakeup. |
3208 This caused ST/X to consume 100% cpu, when the caller didn't read |
3221 This caused ST/X to consume 100% cpu, when the caller didn't read |
3209 the data (e.g. because his process was stopped)." |
3222 the data (e.g. because his process was stopped)." |
3210 useIOInterrupts ifTrue:[ |
3223 useIOInterrupts ifTrue:[ |
3211 OperatingSystem disableIOInterruptsOn:fd |
3224 OperatingSystem disableIOInterruptsOn:fd |
3212 ]. |
3225 ]. |
3213 readFdArray at:index put:nil. |
3226 readFdArray at:index put:nil. |
3214 readSemaphoreArray at:index put:nil. |
3227 readSemaphoreArray at:index put:nil. |
3215 "disable possible write side and timeouts as well" |
3228 "disable possible write side and timeouts as well" |
3216 self disableSemaphore:sema. |
3229 self disableSemaphore:sema. |
3217 ]. |
3230 ]. |
3218 ]. |
3231 ]. |
3219 action notNil ifTrue:[ |
3232 action notNil ifTrue:[ |
3220 action value. |
3233 action value. |
3221 newProcessMaybeReady := true |
3234 newProcessMaybeReady := true |
3222 ]. |
3235 ]. |
3223 ]. |
3236 ]. |
3224 nReady := nReady - 1. |
3237 nReady := nReady - 1. |
3225 readyIndex := readyIndex + 1. |
3238 readyIndex := readyIndex + 1. |
3226 ]. |
3239 ]. |
3227 |
3240 |
3228 readyIndex := 1. |
3241 readyIndex := 1. |
3229 [nReady > 0 |
3242 [nReady > 0 |
3230 and:[ readyIndex <= writableResultFdArray size |
3243 and:[ readyIndex <= writableResultFdArray size |
3231 and:[ (fd := writableResultFdArray at:readyIndex) notNil ]]] |
3244 and:[ (fd := writableResultFdArray at:readyIndex) notNil ]]] |
3232 whileTrue:[ |
3245 whileTrue:[ |
3233 index := writeFdArray identityIndexOf:fd. |
3246 index := writeFdArray identityIndexOf:fd. |
3234 index ~~ 0 ifTrue:[ |
3247 index ~~ 0 ifTrue:[ |
3235 action := writeCheckArray at:index. |
3248 action := writeCheckArray at:index. |
3236 sema := writeSemaphoreArray at:index. |
3249 sema := writeSemaphoreArray at:index. |
3237 sema notNil ifTrue:[ |
3250 sema notNil ifTrue:[ |
3238 sema signalOnce. |
3251 sema signalOnce. |
3239 newProcessMaybeReady := true. |
3252 newProcessMaybeReady := true. |
3240 action isNil ifTrue:[ |
3253 action isNil ifTrue:[ |
3241 "now this is a one shot operation - see the input above" |
3254 "now this is a one shot operation - see the input above" |
3242 useIOInterrupts ifTrue:[ |
3255 useIOInterrupts ifTrue:[ |
3243 OperatingSystem disableIOInterruptsOn:fd |
3256 OperatingSystem disableIOInterruptsOn:fd |
3244 ]. |
3257 ]. |
3245 writeFdArray at:index put:nil. |
3258 writeFdArray at:index put:nil. |
3246 writeSemaphoreArray at:index put:nil. |
3259 writeSemaphoreArray at:index put:nil. |
3247 "disable possible read side and timeouts as well" |
3260 "disable possible read side and timeouts as well" |
3248 self disableSemaphore:sema. |
3261 self disableSemaphore:sema. |
3249 ]. |
3262 ]. |
3250 ]. |
3263 ]. |
3251 action notNil ifTrue:[ |
3264 action notNil ifTrue:[ |
3252 action value. |
3265 action value. |
3253 newProcessMaybeReady := true |
3266 newProcessMaybeReady := true |
3254 ] |
3267 ] |
3255 ]. |
3268 ]. |
3256 nReady := nReady - 1. |
3269 nReady := nReady - 1. |
3257 readyIndex := readyIndex + 1. |
3270 readyIndex := readyIndex + 1. |
3258 ]. |
3271 ]. |
3259 |
3272 |
3260 exceptArray notNil ifTrue:[ |
3273 exceptArray notNil ifTrue:[ |
3261 "/ only for win32 |
3274 "/ only for win32 |
3262 readyIndex := 1. |
3275 readyIndex := 1. |
3263 [nReady > 0 |
3276 [nReady > 0 |
3264 and:[ readyIndex <= pidsFinished size |
3277 and:[ readyIndex <= pidsFinished size |
3265 and:[ (pid := pidsFinished at:readyIndex) notNil ]]] |
3278 and:[ (pid := pidsFinished at:readyIndex) notNil ]]] |
3266 whileTrue:[ |
3279 whileTrue:[ |
3267 |osProcessStatus actionBlock| |
3280 |osProcessStatus actionBlock| |
3268 "/'pid signaled: ' infoPrint. pid infoPrintCR. |
3281 "/'pid signaled: ' infoPrint. pid infoPrintCR. |
3269 actionBlock := osChildExitActions removeKey:pid ifAbsent:nil. |
3282 actionBlock := osChildExitActions removeKey:pid ifAbsent:nil. |
3270 osProcessStatus := OperatingSystem childProcessWait:false pid:pid. |
3283 osProcessStatus := OperatingSystem childProcessWait:false pid:pid. |
3271 osProcessStatus notNil ifTrue:[ |
3284 osProcessStatus notNil ifTrue:[ |
3272 (osProcessStatus pid = pid) ifTrue:[ |
3285 (osProcessStatus pid = pid) ifTrue:[ |
3273 actionBlock notNil ifTrue:[ |
3286 actionBlock notNil ifTrue:[ |
3274 actionBlock value:osProcessStatus. |
3287 actionBlock value:osProcessStatus. |
3275 newProcessMaybeReady := true |
3288 newProcessMaybeReady := true |
3276 ]. |
3289 ]. |
3277 ]. |
3290 ]. |
3278 ]. |
3291 ]. |
3279 nReady := nReady - 1. |
3292 nReady := nReady - 1. |
3280 readyIndex := readyIndex + 1. |
3293 readyIndex := readyIndex + 1. |
3281 ]. |
3294 ]. |
3282 ]. |
3295 ]. |
3283 ]. |
3296 ]. |
3284 ^ newProcessMaybeReady |
3297 ^ newProcessMaybeReady |
3285 |
3298 |
3286 "Modified: / 12-04-1996 / 09:31:22 / stefan" |
3299 "Modified: / 12-04-1996 / 09:31:22 / stefan" |
3287 "Modified: / 07-12-2006 / 19:48:17 / cg" |
3300 "Modified: / 07-12-2006 / 19:48:17 / cg" |
3315 an #EBADF error, leading to high-frequency polling and a locked up system. |
3328 an #EBADF error, leading to high-frequency polling and a locked up system. |
3316 (you could still fix things by interrupting on the console and fixing the |
3329 (you could still fix things by interrupting on the console and fixing the |
3317 readFdArray/writeFdArray in the debugger)" |
3330 readFdArray/writeFdArray in the debugger)" |
3318 |
3331 |
3319 readFdArray keysAndValuesDo:[:idx :fd | |
3332 readFdArray keysAndValuesDo:[:idx :fd | |
3320 |result sema| |
3333 |result sema| |
3321 |
3334 |
3322 fd notNil ifTrue:[ |
3335 fd notNil ifTrue:[ |
3323 result := OperatingSystem |
3336 result := OperatingSystem |
3324 selectOnAnyReadable:(Array with:fd) writable:nil exception:nil |
3337 selectOnAnyReadable:(Array with:fd) writable:nil exception:nil |
3325 readableInto:nil writableInto:nil exceptionInto:nil |
3338 readableInto:nil writableInto:nil exceptionInto:nil |
3326 withTimeOut:0. |
3339 withTimeOut:0. |
3327 |
3340 |
3328 result < 0 ifTrue:[ |
3341 result < 0 ifTrue:[ |
3329 ('Processor [info]: removing invalid read-select fileDescriptor: ' , fd printString) infoPrintCR. |
3342 ('Processor [info]: removing invalid read-select fileDescriptor: ' , fd printString) infoPrintCR. |
3330 readFdArray at:idx put:nil. |
3343 readFdArray at:idx put:nil. |
3331 readCheckArray at:idx put:nil. |
3344 readCheckArray at:idx put:nil. |
3332 (sema := readSemaphoreArray at:idx) notNil ifTrue:[ |
3345 (sema := readSemaphoreArray at:idx) notNil ifTrue:[ |
3333 readSemaphoreArray at:idx put:nil. |
3346 readSemaphoreArray at:idx put:nil. |
3334 sema signalOnce. |
3347 sema signalOnce. |
3335 ]. |
3348 ]. |
3336 ] |
3349 ] |
3337 ]. |
3350 ]. |
3338 ]. |
3351 ]. |
3339 |
3352 |
3340 writeFdArray keysAndValuesDo:[:idx :fd | |
3353 writeFdArray keysAndValuesDo:[:idx :fd | |
3341 |result sema| |
3354 |result sema| |
3342 |
3355 |
3343 fd notNil ifTrue:[ |
3356 fd notNil ifTrue:[ |
3344 result := OperatingSystem |
3357 result := OperatingSystem |
3345 selectOnAnyReadable:(Array with:fd) writable:nil exception:nil |
3358 selectOnAnyReadable:(Array with:fd) writable:nil exception:nil |
3346 readableInto:nil writableInto:nil exceptionInto:nil |
3359 readableInto:nil writableInto:nil exceptionInto:nil |
3347 withTimeOut:0. |
3360 withTimeOut:0. |
3348 |
3361 |
3349 result < 0 ifTrue:[ |
3362 result < 0 ifTrue:[ |
3350 ('Processor [info]: removing invalid write-select fileDescriptor: ' , fd printString) infoPrintCR. |
3363 ('Processor [info]: removing invalid write-select fileDescriptor: ' , fd printString) infoPrintCR. |
3351 writeFdArray at:idx put:nil. |
3364 writeFdArray at:idx put:nil. |
3352 writeCheckArray at:idx put:nil. |
3365 writeCheckArray at:idx put:nil. |
3353 (sema := writeSemaphoreArray at:idx) notNil ifTrue:[ |
3366 (sema := writeSemaphoreArray at:idx) notNil ifTrue:[ |
3354 writeSemaphoreArray at:idx put:nil. |
3367 writeSemaphoreArray at:idx put:nil. |
3355 sema signalOnce. |
3368 sema signalOnce. |
3356 ]. |
3369 ]. |
3357 ] |
3370 ] |
3358 ] |
3371 ] |
3359 ]. |
3372 ]. |
3360 |
3373 |
3361 OperatingSystem isMSWINDOWSlike ifTrue:[ |
3374 OperatingSystem isMSWINDOWSlike ifTrue:[ |
3362 "/ |
3375 "/ |
3363 "/ win32 does a WaitForMultipleObjects in select... |
3376 "/ win32 does a WaitForMultipleObjects in select... |
3364 "/ unix waits for SIGCHLD |
3377 "/ unix waits for SIGCHLD |
3365 "/ |
3378 "/ |
3366 osChildExitActions keysDo:[:eachPid | |
3379 osChildExitActions keysDo:[:eachPid | |
3367 |result sema| |
3380 |result sema| |
3368 |
3381 |
3369 eachPid notNil ifTrue:[ |
3382 eachPid notNil ifTrue:[ |
3370 result := OperatingSystem |
3383 result := OperatingSystem |
3371 selectOnAnyReadable:nil writable:nil exception:(Array with:eachPid) |
3384 selectOnAnyReadable:nil writable:nil exception:(Array with:eachPid) |
3372 readableInto:nil writableInto:nil exceptionInto:nil |
3385 readableInto:nil writableInto:nil exceptionInto:nil |
3373 withTimeOut:0. |
3386 withTimeOut:0. |
3374 |
3387 |
3375 result < 0 ifTrue:[ |
3388 result < 0 ifTrue:[ |
3376 ('Processor [info]: removing invalid except-select pid: ' , eachPid printString) infoPrintCR. |
3389 ('Processor [info]: removing invalid except-select pid: ' , eachPid printString) infoPrintCR. |
3377 osChildExitActions safeRemoveKey:eachPid. |
3390 osChildExitActions safeRemoveKey:eachPid. |
3378 ] |
3391 ] |
3379 ] |
3392 ] |
3380 ]. |
3393 ]. |
3381 ]. |
3394 ]. |
3382 |
3395 |
3383 "Modified: 12.4.1996 / 09:32:58 / stefan" |
3396 "Modified: 12.4.1996 / 09:32:58 / stefan" |
3384 "Modified: 27.1.1997 / 20:09:27 / cg" |
3397 "Modified: 27.1.1997 / 20:09:27 / cg" |
3385 ! |
3398 ! |
3456 |
3469 |
3457 |millis doingGC anySema dT| |
3470 |millis doingGC anySema dT| |
3458 |
3471 |
3459 doingGC := true. |
3472 doingGC := true. |
3460 [doingGC] whileTrue:[ |
3473 [doingGC] whileTrue:[ |
3461 anyTimeouts ifTrue:[ |
3474 anyTimeouts ifTrue:[ |
3462 millis := self timeToNextTimeout. |
3475 millis := self timeToNextTimeout. |
3463 (millis notNil and:[millis <= 0]) ifTrue:[ |
3476 (millis notNil and:[millis <= 0]) ifTrue:[ |
3464 ^ self "oops - hurry up checking" |
3477 ^ self "oops - hurry up checking" |
3465 ]. |
3478 ]. |
3466 ]. |
3479 ]. |
3467 |
3480 |
3468 " |
3481 " |
3469 if its worth doing, collect a bit of garbage; |
3482 if its worth doing, collect a bit of garbage; |
3470 but not, if a backgroundCollector is active |
3483 but not, if a backgroundCollector is active |
3471 " |
3484 " |
3472 ObjectMemory backgroundCollectorRunning ifTrue:[ |
3485 ObjectMemory backgroundCollectorRunning ifTrue:[ |
3473 doingGC := false |
3486 doingGC := false |
3474 ] ifFalse:[ |
3487 ] ifFalse:[ |
3475 doingGC := ObjectMemory gcStepIfUseful. |
3488 doingGC := ObjectMemory gcStepIfUseful. |
3476 ]. |
3489 ]. |
3477 |
3490 |
3478 "then do idle actions" |
3491 "then do idle actions" |
3479 (idleActions notNil and:[idleActions size ~~ 0]) ifTrue:[ |
3492 (idleActions notNil and:[idleActions size ~~ 0]) ifTrue:[ |
3480 idleActions do:[:aBlock | |
3493 idleActions do:[:aBlock | |
3481 aBlock value. |
3494 aBlock value. |
3482 ]. |
3495 ]. |
3483 ^ self "go back checking" |
3496 ^ self "go back checking" |
3484 ]. |
3497 ]. |
3485 |
3498 |
3486 doingGC ifTrue:[ |
3499 doingGC ifTrue:[ |
3487 (self checkForIOWithTimeout:0) ifTrue:[ |
3500 (self checkForIOWithTimeout:0) ifTrue:[ |
3488 ^ self "go back checking" |
3501 ^ self "go back checking" |
3489 ] |
3502 ] |
3490 ] |
3503 ] |
3491 ]. |
3504 ]. |
3492 |
3505 |
3493 exitWhenNoMoreUserProcesses ifTrue:[ |
3506 exitWhenNoMoreUserProcesses ifTrue:[ |
3494 "/ check if there are any processes at all |
3507 "/ check if there are any processes at all |
3495 "/ stop dispatching if there is none |
3508 "/ stop dispatching if there is none |
3496 "/ (and anyTimeouts is false, which means that no timeout blocks are present) |
3509 "/ (and anyTimeouts is false, which means that no timeout blocks are present) |
3497 "/ and no readSemaphores are present (which means that noone is waiting for input) |
3510 "/ and no readSemaphores are present (which means that noone is waiting for input) |
3498 "/ and no writeSemaphores are present |
3511 "/ and no writeSemaphores are present |
3499 |
3512 |
3500 anyTimeouts ifFalse:[ |
3513 anyTimeouts ifFalse:[ |
3501 anySema := (readSemaphoreArray findFirst:[:sema | sema notNil]) ~~ 0. |
3514 anySema := (readSemaphoreArray findFirst:[:sema | sema notNil]) ~~ 0. |
3502 anySema ifFalse:[ |
3515 anySema ifFalse:[ |
3503 anySema := (writeSemaphoreArray findFirst:[:sema | sema notNil]) ~~ 0. |
3516 anySema := (writeSemaphoreArray findFirst:[:sema | sema notNil]) ~~ 0. |
3504 anySema ifFalse:[ |
3517 anySema ifFalse:[ |
3505 self anyUserProcessAtAll ifFalse:[ |
3518 self anyUserProcessAtAll ifFalse:[ |
3506 dispatching := false. |
3519 dispatching := false. |
3507 ^ self |
3520 ^ self |
3508 ] |
3521 ] |
3509 ]. |
3522 ]. |
3510 ]. |
3523 ]. |
3511 ]. |
3524 ]. |
3512 ]. |
3525 ]. |
3513 |
3526 |
3514 preWaitActions notNil ifTrue:[ |
3527 preWaitActions notNil ifTrue:[ |
3515 preWaitActions do:[:action | action value]. |
3528 preWaitActions do:[:action | action value]. |
3516 ]. |
3529 ]. |
3517 |
3530 |
3518 "/ |
3531 "/ |
3519 "/ absolutely nothing to do - simply wait |
3532 "/ absolutely nothing to do - simply wait |
3520 "/ |
3533 "/ |
3521 OperatingSystem supportsSelect ifFalse:[ |
3534 OperatingSystem supportsSelect ifFalse:[ |
3522 "SCO instant ShitStation has a bug here, |
3535 "SCO instant ShitStation has a bug here, |
3523 waiting always 1 sec in the select - therefore we delay a bit and |
3536 waiting always 1 sec in the select - therefore we delay a bit and |
3524 return - effectively polling in 50ms cycles |
3537 return - effectively polling in 50ms cycles |
3525 " |
3538 " |
3526 (self checkForIOWithTimeout:0) ifTrue:[ |
3539 (self checkForIOWithTimeout:0) ifTrue:[ |
3527 ^ self "go back checking" |
3540 ^ self "go back checking" |
3528 ]. |
3541 ]. |
3529 OperatingSystem millisecondDelay:EventPollingInterval. |
3542 OperatingSystem millisecondDelay:EventPollingInterval. |
3530 ^ self |
3543 ^ self |
3531 ]. |
3544 ]. |
3532 |
3545 |
3533 useIOInterrupts ifTrue:[ |
3546 useIOInterrupts ifTrue:[ |
3534 dT := 999999 |
3547 dT := 999999 |
3535 ] ifFalse:[ |
3548 ] ifFalse:[ |
3536 dT := EventPollingInterval |
3549 dT := EventPollingInterval |
3537 ]. |
3550 ]. |
3538 |
3551 |
3539 millis isNil ifTrue:[ |
3552 millis isNil ifTrue:[ |
3540 millis := dT. |
3553 millis := dT. |
3541 ] ifFalse:[ |
3554 ] ifFalse:[ |
3542 millis := millis rounded min:dT. |
3555 millis := millis rounded min:dT. |
3543 ]. |
3556 ]. |
3544 |
3557 |
3545 self checkForIOWithTimeout:millis |
3558 self checkForIOWithTimeout:millis |
3546 |
3559 |
3547 "Modified: 14.12.1995 / 13:37:46 / stefan" |
3560 "Modified: 14.12.1995 / 13:37:46 / stefan" |