8 be provided or otherwise made available to, or used by, any |
8 be provided or otherwise made available to, or used by, any |
9 other person. No title to or ownership of the software is |
9 other person. No title to or ownership of the software is |
10 hereby transferred. |
10 hereby transferred. |
11 " |
11 " |
12 |
12 |
|
13 'From Smalltalk/X, Version:2.10.8 on 21-dec-1995 at 16:28:28' ! |
|
14 |
13 Object subclass:#ProcessorScheduler |
15 Object subclass:#ProcessorScheduler |
14 instanceVariableNames:'quiescentProcessLists scheduler zombie activeProcess |
16 instanceVariableNames:'quiescentProcessLists scheduler zombie activeProcess |
15 currentPriority readFdArray readSemaphoreArray readCheckArray |
17 currentPriority readFdArray readSemaphoreArray readCheckArray |
16 writeFdArray writeSemaphoreArray timeoutArray timeoutActionArray |
18 writeFdArray writeSemaphoreArray timeoutArray timeoutActionArray |
17 timeoutProcessArray timeoutSemaphoreArray idleActions anyTimeouts |
19 timeoutProcessArray timeoutSemaphoreArray idleActions anyTimeouts |
18 dispatching interruptedProcess useIOInterrupts' |
20 dispatching interruptedProcess useIOInterrupts gotIOInterrupt' |
19 classVariableNames:'KnownProcesses KnownProcessIds PureEventDriven |
21 classVariableNames:'KnownProcesses KnownProcessIds PureEventDriven |
20 UserSchedulingPriority UserInterruptPriority TimingPriority |
22 UserSchedulingPriority UserInterruptPriority TimingPriority |
21 HighestPriority SchedulingPriority MaxNumberOfProcesses' |
23 HighestPriority SchedulingPriority MaxNumberOfProcesses' |
22 poolDictionaries:'' |
24 poolDictionaries:'' |
23 category:'Kernel-Processes' |
25 category:'Kernel-Processes' |
498 |
500 |
499 " |
501 " |
500 handle all timeout actions |
502 handle all timeout actions |
501 " |
503 " |
502 anyTimeouts ifTrue:[ |
504 anyTimeouts ifTrue:[ |
503 self evaluateTimeouts |
505 self evaluateTimeouts |
504 ]. |
506 ]. |
505 |
507 |
506 "first do a quick check for semaphores using checkActions - this is needed for |
508 "first do a quick check for semaphores using checkActions - this is needed for |
507 devices like the X-connection, where some events might be in the event |
509 devices like the X-connection, where some events might be in the event |
508 queue. Without these checks, a select might block even though there is work to do |
510 queue. Without these checks, a select might block even though there is work to do |
509 " |
511 " |
510 any := false. |
512 any := false. |
511 nActions := readCheckArray size. |
513 nActions := readCheckArray size. |
512 1 to:nActions do:[:index | |
514 1 to:nActions do:[:index | |
513 |checkBlock sema| |
515 |checkBlock sema| |
514 |
516 |
515 checkBlock := readCheckArray at:index. |
517 checkBlock := readCheckArray at:index. |
516 (checkBlock notNil and:[checkBlock value]) ifTrue:[ |
518 (checkBlock notNil and:[checkBlock value]) ifTrue:[ |
517 sema := readSemaphoreArray at:index. |
519 sema := readSemaphoreArray at:index. |
518 sema notNil ifTrue:[ |
520 sema notNil ifTrue:[ |
519 sema signalOnce. |
521 sema signalOnce. |
520 ]. |
522 ]. |
521 any := true. |
523 any := true. |
522 ] |
524 ] |
523 ]. |
525 ]. |
524 |
526 |
525 "now, someone might be runnable ..." |
527 "now, someone might be runnable ..." |
526 |
528 |
527 p := self highestPriorityRunnableProcess. |
529 p := self highestPriorityRunnableProcess. |
528 p isNil ifTrue:[ |
530 p isNil ifTrue:[ |
529 "no one runnable, hard wait for event or timeout" |
531 "no one runnable, hard wait for event or timeout" |
530 |
532 |
531 self waitForEventOrTimeout. |
533 self waitForEventOrTimeout. |
532 ^ self |
534 ^ self |
533 ]. |
535 ]. |
534 |
536 |
535 pri := p priority. |
537 pri := p priority. |
536 |
538 |
537 " |
539 " |
558 (a future version will have a process running to handle a timeout queue) |
560 (a future version will have a process running to handle a timeout queue) |
559 " |
561 " |
560 |
562 |
561 " |
563 " |
562 pri < TimingPriority ifTrue:[ |
564 pri < TimingPriority ifTrue:[ |
563 anyTimeouts ifTrue:[ |
565 anyTimeouts ifTrue:[ |
564 millis := self timeToNextTimeout. |
566 millis := self timeToNextTimeout. |
565 millis == 0 ifTrue:[^ self]. |
567 millis == 0 ifTrue:[^ self]. |
566 ] |
568 ] |
567 ]. |
569 ]. |
568 " |
570 " |
569 |
571 |
570 " |
572 " |
571 if the process to run has a lower than UserInterruptPriority, |
573 if the process to run has a lower than UserInterruptPriority, |
574 or by installing a poll-interrupt after 50ms (if the OS does not). |
576 or by installing a poll-interrupt after 50ms (if the OS does not). |
575 " |
577 " |
576 pri < UserInterruptPriority ifTrue:[ |
578 pri < UserInterruptPriority ifTrue:[ |
577 |
579 |
578 "comment out this if above is uncommented" |
580 "comment out this if above is uncommented" |
579 anyTimeouts ifTrue:[ |
581 anyTimeouts ifTrue:[ |
580 millis := self timeToNextTimeout. |
582 millis := self timeToNextTimeout. |
581 millis == 0 ifTrue:[^ self]. |
583 millis == 0 ifTrue:[^ self]. |
582 ]. |
584 ]. |
583 "---" |
585 "---" |
584 |
586 |
585 useIOInterrupts ifTrue:[ |
587 useIOInterrupts ifTrue:[ |
586 readFdArray do:[:fd | |
588 readFdArray do:[:fd | |
587 fd notNil ifTrue:[ |
589 fd notNil ifTrue:[ |
588 OperatingSystem enableIOInterruptsOn:fd |
590 OperatingSystem enableIOInterruptsOn:fd |
589 ]. |
591 ]. |
590 ]. |
592 ]. |
591 ] ifFalse:[ |
593 ] ifFalse:[ |
592 millis notNil ifTrue:[ |
594 millis notNil ifTrue:[ |
593 millis := millis min:50 |
595 millis := millis min:50 |
594 ] ifFalse:[ |
596 ] ifFalse:[ |
595 millis := 50 |
597 millis := 50 |
596 ] |
598 ] |
597 ] |
599 ] |
598 ]. |
600 ]. |
599 |
601 |
600 millis notNil ifTrue:[ |
602 millis notNil ifTrue:[ |
601 "schedule a clock interrupt after millis milliseconds" |
603 "schedule a clock interrupt after millis milliseconds" |
602 OperatingSystem enableTimer:millis rounded. |
604 OperatingSystem enableTimer:millis rounded. |
603 ]. |
605 ]. |
604 |
606 |
605 " |
607 " |
606 now let the process run - will come back here by reschedule |
608 now let the process run - will come back here by reschedule |
607 from ioInterrupt or timerInterrupt ... (running at max+1) |
609 from ioInterrupt or timerInterrupt ... (running at max+1) |
608 " |
610 " |
609 self threadSwitch:p. |
611 self threadSwitch:p. |
610 |
612 |
611 "... when we arrive here, we are back on stage" |
613 "... when we arrive here, we are back on stage. |
|
614 Either by an ALARM or IO signal, or by a suspend of another process |
|
615 " |
612 |
616 |
613 millis notNil ifTrue:[ |
617 millis notNil ifTrue:[ |
614 OperatingSystem disableTimer. |
618 OperatingSystem disableTimer. |
615 useIOInterrupts ifFalse:[ |
619 ]. |
616 self checkForInputWithTimeout:0. |
620 |
617 ] |
621 "/ check for new input |
|
622 |
|
623 (gotIOInterrupt or:[useIOInterrupts not]) ifTrue:[ |
|
624 gotIOInterrupt := false. |
|
625 self checkForInputWithTimeout:0. |
618 ] |
626 ] |
619 |
627 |
620 "Modified: 14.12.1995 / 14:45:13 / stefan" |
628 "Modified: 21.12.1995 / 16:21:54 / stefan" |
621 ! |
629 ! |
622 |
630 |
623 dispatchLoop |
631 dispatchLoop |
624 "central dispatch loop; the scheduler process is always staying in |
632 "central dispatch loop; the scheduler process is always staying in |
625 this method, looping forever." |
633 this method, looping forever." |
794 |
802 |
795 |nPrios "{ Class: SmallInteger }" |
803 |nPrios "{ Class: SmallInteger }" |
796 l p| |
804 l p| |
797 |
805 |
798 KnownProcesses isNil ifTrue:[ |
806 KnownProcesses isNil ifTrue:[ |
799 KnownProcesses := WeakArray new:10. |
807 KnownProcesses := WeakArray new:10. |
800 KnownProcesses watcher:self class. |
808 KnownProcesses watcher:self class. |
801 KnownProcessIds := OrderedCollection new. |
809 KnownProcessIds := OrderedCollection new. |
802 ]. |
810 ]. |
803 |
811 |
804 " |
812 " |
805 create a collection with process lists; accessed using the priority as key |
813 create a collection with process lists; accessed using the priority as key |
806 " |
814 " |
807 nPrios := SchedulingPriority. |
815 nPrios := SchedulingPriority. |
808 quiescentProcessLists := Array new:nPrios. |
816 quiescentProcessLists := Array new:nPrios. |
809 1 to:nPrios do:[:pri | |
817 1 to:nPrios do:[:pri | |
810 quiescentProcessLists at:pri put:(LinkedList new) |
818 quiescentProcessLists at:pri put:(LinkedList new) |
811 ]. |
819 ]. |
812 |
820 |
813 readFdArray := Array with:nil. |
821 readFdArray := Array with:nil. |
814 readCheckArray := Array with:nil. |
822 readCheckArray := Array with:nil. |
815 readSemaphoreArray := Array with:nil. |
823 readSemaphoreArray := Array with:nil. |
820 timeoutActionArray := Array with:nil. |
828 timeoutActionArray := Array with:nil. |
821 timeoutProcessArray := Array with:nil. |
829 timeoutProcessArray := Array with:nil. |
822 anyTimeouts := false. |
830 anyTimeouts := false. |
823 dispatching := false. |
831 dispatching := false. |
824 useIOInterrupts := OperatingSystem supportsIOInterrupts. |
832 useIOInterrupts := OperatingSystem supportsIOInterrupts. |
|
833 gotIOInterrupt := false. |
825 |
834 |
826 " |
835 " |
827 handcraft the first (dispatcher-) process - this one will never |
836 handcraft the first (dispatcher-) process - this one will never |
828 block, but go into a select if there is nothing to do. |
837 block, but go into a select if there is nothing to do. |
829 Also, it has a prio of max+1 - thus, it comes first when looking |
838 Also, it has a prio of max+1 - thus, it comes first when looking |
842 " |
851 " |
843 let me handle IO and timer interrupts |
852 let me handle IO and timer interrupts |
844 " |
853 " |
845 ObjectMemory ioInterruptHandler:self. |
854 ObjectMemory ioInterruptHandler:self. |
846 ObjectMemory timerInterruptHandler:self. |
855 ObjectMemory timerInterruptHandler:self. |
|
856 |
|
857 "Modified: 21.12.1995 / 16:18:36 / stefan" |
847 ! |
858 ! |
848 |
859 |
849 reinitialize |
860 reinitialize |
850 "all previous processes (except those marked as restartable) are made dead |
861 "all previous processes (except those marked as restartable) are made dead |
851 - each object should reinstall its process(s) upon restart; |
862 - each object should reinstall its process(s) upon restart; |