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