1 (* Executive.mod provides a simple multitasking executive.
3 Copyright (C) 2002-2022 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6 This file is part of GNU Modula-2.
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 Under Section 7 of GPL version 3, you are granted additional
19 permissions described in the GCC Runtime Library Exception, version
20 3.1, as published by the Free Software Foundation.
22 You should have received a copy of the GNU General Public License and
23 a copy of the GCC Runtime Library Exception along with this program;
24 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
25 <http://www.gnu.org/licenses/>. *)
27 IMPLEMENTATION MODULE Executive[MAX(PROTECTION)] ;
29 FROM SYSTEM IMPORT ADDRESS, PROCESS, LISTEN, ADR,
30 NEWPROCESS, TRANSFER, IOTRANSFER, ListenLoop,
33 FROM COROUTINES IMPORT PROTECTION ;
34 FROM SysStorage IMPORT ALLOCATE, DEALLOCATE ;
35 FROM StrLib IMPORT StrCopy ;
36 FROM StrLib IMPORT StrLen ;
37 FROM NumberIO IMPORT CardToStr ;
38 FROM Debug IMPORT DebugString, Halt ;
46 IdleStackSize = 16 * 1024 * 1024 ;
49 SEMAPHORE = POINTER TO Semaphore ; (* defines dijkstra's semaphores *)
51 Value : CARDINAL ; (* semaphore value *)
52 SemName: EntityName ; (* semaphore name for debugging *)
53 Who : DESCRIPTOR ; (* queue of waiting processes *)
54 ExistsQ: SemQueue ; (* list of existing semaphores *)
57 DESCRIPTOR= POINTER TO Descriptor ; (* handle onto a process *)
59 Volatiles : PROCESS ; (* process volatile environment *)
60 ReadyQ : DesQueue ; (* queue of ready processes *)
61 ExistsQ : DesQueue ; (* queue of existing processes *)
62 SemaphoreQ : DesQueue ; (* queue of waiting processes *)
63 Which : SEMAPHORE ; (* which semaphore are we waiting*)
64 RunName : EntityName ; (* process name for debugging *)
65 Status : State ; (* state of process *)
66 RunPriority: Priority ; (* runtime priority of process *)
67 Size : CARDINAL ; (* Maximum stack size *)
68 Start : ADDRESS ; (* Stack start *)
69 Debugged : BOOLEAN ; (* Does user want to debug a *)
70 (* deadlocked process? *)
83 EntityName= ARRAY [0..MaxCharsInName] OF CHAR ;
85 Priority = (idle, lo, hi) ; (* process run priority *)
87 State = (Runnable, Suspended, WaitOnSem, WaitOnInt) ;
90 ExistsQueue : DESCRIPTOR ; (* List of existing processes *)
91 RunQueue : ARRAY Priority OF DESCRIPTOR ;
92 (* List of runnable processes *)
93 CurrentProcess: DESCRIPTOR ;
94 AllSemaphores : SEMAPHORE ; (* List of all semaphores *)
95 GarbageItem : DESCRIPTOR ; (* Descriptor destined to free *)
102 PROCEDURE Assert (c: BOOLEAN; file: ARRAY OF CHAR; line: CARDINAL;
103 function: ARRAY OF CHAR) ;
108 Halt(file, line, function, 'assert failed')
114 InitProcess - initializes a process which is held in the suspended
115 state. When the process is resumed it will start executing
116 procedure, p. The process has a maximum stack size of,
117 StackSize, bytes and its textual name is, Name.
118 The StackSize should be at least 5000 bytes.
121 PROCEDURE InitProcess (p: PROC;
123 Name: ARRAY OF CHAR) : DESCRIPTOR ;
126 ToOldState: PROTECTION ;
127 db : ARRAY [0..80] OF CHAR ;
129 (* ToOldState := TurnInterrupts(MAX(PROTECTION)) ; (* disable interrupts *) *)
133 (* allocate space for this processes stack *)
134 ALLOCATE(Start, StackSize) ;
135 NEWPROCESS(p, Start, StackSize, Volatiles) ; (* create volatiles *)
136 InitQueue(ReadyQ) ; (* not on the ready queue as suspended *)
137 AddToExists(d) ; (* add process to the exists queue *)
138 InitQueue(SemaphoreQ) ; (* not on a semaphore queue yet *)
139 Which := NIL ; (* not on a semaphore queue yet *)
140 StrCopy(Name, RunName) ; (* copy name into descriptor for debugging *)
141 Status := Suspended ; (* this process will be suspended *)
142 RunPriority := lo ; (* all processes start off at lo priority *)
143 Debugged := FALSE ; (* no need to debug deadlock yet! *)
145 (* ToOldState := TurnInterrupts(ToOldState) ; (* restore interrupts *) *)
146 RETURN( d ) (* and return a descriptor to the caller *)
151 KillProcess - kills the current process. Notice that if InitProcess
152 is called again, it might reuse the DESCRIPTOR of the
153 killed process. It is the responsibility of the caller
154 to ensure all other processes understand this process
158 PROCEDURE KillProcess ;
160 ToOldState: PROTECTION ;
162 (* ToOldState := TurnInterrupts(MAX(PROTECTION)) ; (* disable interrupts *) *)
163 SubFromReady(CurrentProcess) ;
164 SubFromExists(ExistsQueue, CurrentProcess) ;
165 GarbageItem := CurrentProcess ;
167 (* ToOldState := TurnInterrupts(ToOldState) (* restore interrupts *) *)
172 Resume - resumes a suspended process. If all is successful then the process, p,
173 is returned. If it fails then NIL is returned.
176 PROCEDURE Resume (d: DESCRIPTOR) : DESCRIPTOR ;
178 ToOldState: PROTECTION ;
180 (* ToOldState := TurnInterrupts(MAX(PROTECTION)) ; (* disable interrupts *) *)
182 (* your code needs to go here *)
183 WITH d^ DO (* remove for student *)
184 IF Status=Suspended (* remove for student *)
185 THEN (* remove for student *)
186 (* legal state transition *) (* remove for student *)
187 Status := Runnable ; (* change status *) (* remove for student *)
188 AddToReady(d) ; (* add to run queue *) (* remove for student *)
189 RunQueue[RunPriority] := d ; (* make d at top of q *) (* remove for student *)
190 Reschedule (* check whether this process has a higher run priority *) (* remove for student *)
191 ELSE (* remove for student *)
192 (* we are trying to Resume a process which is *) (* remove for student *)
193 Halt(__FILE__, __LINE__, __FUNCTION__, (* remove for student *)
194 'trying to resume a process which is not suspended') ; (* remove for student *)
195 RETURN( NIL ) (* not held in a Suspended state - error *) (* remove for student *)
196 END (* remove for student *)
197 END ; (* remove for student *)
198 (* ToOldState := TurnInterrupts(ToOldState) ; (* restore interrupts *) *)
204 Suspend - suspend the calling process.
205 The process can only continue running if another process
211 ToOldState: PROTECTION ;
213 (* ToOldState := TurnInterrupts(MAX(PROTECTION)) ; (* disable interrupts *) *)
214 WITH CurrentProcess^ DO
217 SubFromReady(CurrentProcess) ;
219 (* ToOldState := TurnInterrupts(ToOldState) (* restore interrupts *) *)
224 InitSemaphore - creates a semaphore whose initial value is, v, and
228 PROCEDURE InitSemaphore (v: CARDINAL; Name: ARRAY OF CHAR) : SEMAPHORE ;
231 ToOldState: PROTECTION ;
233 (* ToOldState := TurnInterrupts(MAX(PROTECTION)) ; (* disable interrupts *) *)
236 Value := v ; (* initial value of semaphore *)
237 StrCopy(Name, SemName) ; (* save the name for future debugging *)
238 Who := NIL ; (* no one waiting on this semaphore yet *)
239 AddToSemaphoreExists(s) ; (* add semaphore to exists list *)
241 (* ToOldState := TurnInterrupts(ToOldState) ; (* restore interrupts *) *)
247 Wait - performs dijkstra's P operation on a semaphore.
248 A process which calls this procedure will
249 wait until the value of the semaphore is > 0
250 and then it will decrement this value.
253 PROCEDURE Wait (s: SEMAPHORE) ;
255 ToOldState: PROTECTION ;
257 (* ToOldState := TurnInterrupts(MAX(PROTECTION)) ; (* disable interrupts *) *)
259 (* your code needs to go here *)
260 WITH s^ DO (* remove for student *)
261 IF Value>0 (* remove for student *)
262 THEN (* remove for student *)
263 DEC( Value ) (* remove for student *)
264 ELSE (* remove for student *)
265 SubFromReady(CurrentProcess) ; (* remove from run q *) (* remove for student *)
266 IF Who=CurrentProcess
269 Halt(__FILE__, __LINE__, __FUNCTION__, 'we are already on sem')
271 AddToSemaphore(Who, CurrentProcess) ; (* add to semaphore q *) (* remove for student *)
272 CurrentProcess^.Status := WaitOnSem ; (* set new status *) (* remove for student *)
273 CurrentProcess^.Which := s ; (* debugging aid *) (* remove for student *)
274 Reschedule (* find next process *) (* remove for student *)
275 END (* remove for student *)
276 END ; (* remove for student *)
277 (* ToOldState := TurnInterrupts(ToOldState) (* restore interrupts *) *)
282 Signal - performs dijkstra's V operation on a semaphore.
283 A process which calls the procedure will increment
284 the semaphores value.
287 PROCEDURE Signal (s: SEMAPHORE) ;
289 ToOldState: PROTECTION ;
292 (* ToOldState := TurnInterrupts(MAX(PROTECTION)) ; (* disable interrupts *) *)
296 INC( Value ) (* no process waiting *)
298 d := SubFromSemaphoreTop(Who) ; (* remove process from semaphore q *)
299 d^.Which := NIL ; (* no longer waiting on semaphore *)
300 d^.Status := Runnable ; (* set new status *)
301 AddToReady(d) ; (* add process to the run queue *)
302 Reschedule (* find out whether there is a *)
303 (* higher priority to run. *)
306 (* ToOldState := TurnInterrupts(ToOldState) (* restore interrupts *) *)
311 WaitForIO - waits for an interrupt to occur on vector, VectorNo.
314 PROCEDURE WaitForIO (VectorNo: CARDINAL) ;
316 Calling : DESCRIPTOR ;
318 ToOldState: PROTECTION ;
321 (* ToOldState := TurnInterrupts(MAX(PROTECTION)) ; *)
323 DebugString('inside WaitForIO ') ;
324 DebugString(CurrentProcess^.RunName) ;
327 Assert(CurrentProcess^.Status=Runnable,
328 __FILE__, __LINE__, __FUNCTION__) ;
329 SubFromReady(CurrentProcess) ; (* remove process from run queue *)
331 alter run priority to hi as all processes waiting for an interrupt
332 are scheduled to run at the highest priority.
334 WITH CurrentProcess^ DO
335 Status := WaitOnInt ; (* it will be blocked waiting for an interrupt. *)
336 RunPriority := hi ; (* this (hopefully) allows it to run as soon as *)
337 (* the interrupt occurs. *)
339 Calling := CurrentProcess ; (* process which called WaitForIO *)
340 CurrentProcess := NextReady() ; (* find next process to run while we wait *)
341 Next := CurrentProcess^.Volatiles ;
343 This is quite complicated. We transfer control to the next process saving
344 our volatile environment into the Calling process descriptor volatiles.
345 When an interrupt occurs the calling process will be resumed and the
346 interrupted process volatiles will be placed into Next.
348 IOTRANSFER(Calling^.Volatiles, Next, VectorNo) ;
351 At this point the interrupt has just occurred and the volatiles of
352 the interrupted process are in Next. Next is the current process
353 and so we must save them before picking up the Calling descriptor.
356 CurrentProcess^.Volatiles := Next ; (* carefully stored away *)
357 CurrentProcess := Calling ; (* update CurrentProcess *)
359 DebugString(CurrentProcess^.RunName) ;
361 CurrentProcess^.Status := Runnable ; (* add to run queue *)
362 AddToReady(CurrentProcess) ;
364 DebugString(' finishing WaitForIO\n') ;
367 (* ToOldState := TurnInterrupts(ToOldState) (* restore interrupts *) *)
372 Ps - displays a process list together with relevant their status.
377 ToOldState: PROTECTION ;
380 a : ARRAY [0..5] OF CHAR ;
382 (* ToOldState := TurnInterrupts(MAX(PROTECTION)) ; (* disable interrupts *) *)
388 p := p^.ExistsQ.Right
396 DebugString(SemName) ;
397 WriteNSpaces(MaxCharsInName-StrLen(SemName)) ;
398 CardToStr(Value, 0, a) ;
402 s := s^.ExistsQ.Right
403 UNTIL s=AllSemaphores
405 (* ToOldState := TurnInterrupts(ToOldState) (* restore interrupts *) *)
410 DisplayProcess - displays the process, p, together with its status.
413 PROCEDURE DisplayProcess (p: DESCRIPTOR) ;
415 a: ARRAY [0..4] OF CHAR ;
418 DebugString(RunName) ; WriteNSpaces(MaxCharsInName-StrLen(RunName)) ;
421 idle: DebugString(' idle ') |
422 lo : DebugString(' lo ') |
423 hi : DebugString(' hi ')
428 Runnable : DebugString('runnable ') |
429 Suspended: DebugString('suspended') |
430 WaitOnSem: DebugString('waitonsem (') ;
431 DebugString(Which^.SemName) ;
433 WaitOnInt: DebugString('waitonint')
442 WriteNSpaces - writes, n, spaces.
445 PROCEDURE WriteNSpaces (n: CARDINAL) ;
455 GetCurrentProcess - returns the descriptor of the current running
459 PROCEDURE GetCurrentProcess () : DESCRIPTOR ;
461 ToOldState: PROTECTION ;
464 (* ToOldState := TurnInterrupts(MAX(PROTECTION)) ; (* disable interrupts *) *)
465 p := CurrentProcess ;
466 (* ToOldState := TurnInterrupts(ToOldState) ; (* restore interrupts *) *)
468 END GetCurrentProcess ;
472 RotateRunQueue - rotates the process run queue.
475 PROCEDURE RotateRunQueue ;
477 ToOldState: PROTECTION ;
479 (* ToOldState := TurnInterrupts(MAX(PROTECTION)) ; (* disable interrupts *) *)
480 (* we only need to rotate the lo priority processes as:
481 idle - should only have one process (the idle process)
482 hi - are the device drivers which most of the time are performing
487 RunQueue[lo] := RunQueue[lo]^.ReadyQ.Right
489 (* ToOldState := TurnInterrupts(ToOldState) (* restore interrupts *) *)
494 ProcessName - displays the name of process, d, through
498 PROCEDURE ProcessName (d: DESCRIPTOR) ;
500 DebugString(d^.RunName)
508 PROCEDURE DebugProcess (d: DESCRIPTOR) ;
510 ToOldState: PROTECTION ;
512 (* ToOldState := TurnInterrupts(MAX(PROTECTION)) ; *)
516 DebugString('debugging process (') ;
517 DebugString(RunName) ;
518 DebugString(') was waiting on semaphore (') ;
519 DebugString(Which^.SemName) ;
521 SubFromSemaphore(Which^.Who, d) ;
527 DebugString('can only debug deadlocked processes (') ;
528 DebugString(RunName) ;
529 DebugString(') which are waiting on a semaphore\n')
532 (* ToOldState := TurnInterrupts(ToOldState) *)
537 CheckDebugged - checks to see whether the debugged flag has
538 been set by the debugger.
539 TRUE is returned if the process was debugged.
540 FALSE is returned if the process was not debugged.
543 PROCEDURE CheckDebugged () : BOOLEAN ;
545 WITH CurrentProcess^ DO
549 You will see this comment after you have enabled a
550 deadlocked process to continue via the gdb command:
552 print Executive_DebugProcess(d)
554 debugger caused deadlocked process to continue
556 (* gdb.breakpoint ; *)
558 SubFromReady(CurrentProcess) ;
559 AddToSemaphore(Which^.Who, CurrentProcess) ;
560 (* add it back to the queue sem *)
561 Status := WaitOnSem ;
571 Reschedule - reschedules to the highest runnable process.
574 PROCEDURE Reschedule ;
577 the repeat loop allows us to debug a process even when it is
578 technically waiting on a semaphore. We run the process into
579 a breakpoint and then back into this schedule routine.
580 This is really useful when trying to find out why processes have
585 UNTIL NOT CheckDebugged()
590 ScheduleProcess - finds the highest priority Runnable process and
591 then transfers control to it.
594 PROCEDURE ScheduleProcess ;
597 Highest: DESCRIPTOR ;
599 Highest := NextReady() ;
601 (* rotate ready Q to ensure fairness *)
602 RunQueue[Highest^.RunPriority] := Highest^.ReadyQ.Right ;
604 (* no need to transfer if Highest=CurrentProcess *)
605 IF Highest#CurrentProcess
607 From := CurrentProcess ;
609 DebugString('context switching from ') ; DebugString(From^.RunName) ;
611 (* alter CurrentProcess before we TRANSFER *)
612 CurrentProcess := Highest ;
614 DebugString(' to ') ; DebugString(CurrentProcess^.RunName) ;
617 TRANSFER(From^.Volatiles, Highest^.Volatiles) ;
619 ; DebugString(' (') ; DebugString(CurrentProcess^.RunName) ;
624 END ScheduleProcess ;
628 NextReady - returns the highest priority Runnable process.
631 PROCEDURE NextReady () : DESCRIPTOR ;
633 Highest: DESCRIPTOR ;
637 FOR Pri := idle TO hi DO
640 Highest := RunQueue[Pri]
643 Assert(Highest#NIL, __FILE__, __LINE__, __FUNCTION__) ;
649 CheckGarbageCollect - checks to see whether GarbageItem is set
650 and if so it deallocates storage associated
651 with this descriptor.
654 PROCEDURE CheckGarbageCollect ;
659 DEALLOCATE(Start, Size)
661 DISPOSE(GarbageItem) ;
664 END CheckGarbageCollect ;
668 AddToExists - adds item, Item, to the exists queue.
671 PROCEDURE AddToExists (Item: DESCRIPTOR) ;
675 ExistsQueue := Item ; (* Head is empty therefore make *)
676 Item^.ExistsQ.Left := Item ; (* Item the only entry on this *)
677 Item^.ExistsQ.Right := Item (* queue. *)
679 Item^.ExistsQ.Right := ExistsQueue ; (* Add Item to the end of queue *)
680 Item^.ExistsQ.Left := ExistsQueue^.ExistsQ.Left ;
681 ExistsQueue^.ExistsQ.Left^.ExistsQ.Right := Item ;
682 ExistsQueue^.ExistsQ.Left := Item
688 SubFromExists - removes a process, Item, from the exists queue, Head.
691 PROCEDURE SubFromExists (VAR Head: DESCRIPTOR; Item: DESCRIPTOR) ;
693 IF (Item^.ExistsQ.Right=Head) AND (Item=Head)
699 Head := Head^.ExistsQ.Right
701 Item^.ExistsQ.Left^.ExistsQ.Right := Item^.ExistsQ.Right ;
702 Item^.ExistsQ.Right^.ExistsQ.Left := Item^.ExistsQ.Left
708 AddToSemaphore - adds item, Item, to the semaphore queue defined by Head.
711 PROCEDURE AddToSemaphore (VAR Head: DESCRIPTOR; Item: DESCRIPTOR) ;
715 Head := Item ; (* Head is empty therefore make *)
716 Item^.SemaphoreQ.Left := Item ; (* Item the only entry on this *)
717 Item^.SemaphoreQ.Right := Item (* queue. *)
719 Item^.SemaphoreQ.Right := Head ; (* Add Item to the end of queue *)
720 Item^.SemaphoreQ.Left := Head^.SemaphoreQ.Left ;
721 Head^.SemaphoreQ.Left^.SemaphoreQ.Right := Item ;
722 Head^.SemaphoreQ.Left := Item
728 AddToSemaphoreExists - adds item, Item, to the semaphore exists queue.
731 PROCEDURE AddToSemaphoreExists (Item: SEMAPHORE) ;
735 AllSemaphores := Item ; (* Head is empty therefore make *)
736 Item^.ExistsQ.Left := Item ; (* Item the only entry on this *)
737 Item^.ExistsQ.Right := Item (* queue. *)
739 Item^.ExistsQ.Right := AllSemaphores ;
740 (* Add Item to the end of queue *)
741 Item^.ExistsQ.Left := AllSemaphores^.ExistsQ.Left ;
742 AllSemaphores^.ExistsQ.Left^.ExistsQ.Right := Item ;
743 AllSemaphores^.ExistsQ.Left := Item
745 END AddToSemaphoreExists ;
749 AddToReady - adds item, Item, to the ready queue.
752 PROCEDURE AddToReady (Item: DESCRIPTOR) ;
754 AddToReadyQ(RunQueue[Item^.RunPriority], Item)
759 AddToReadyQ - adds item, Item, to the ready queue defined by Head.
762 PROCEDURE AddToReadyQ (VAR Head: DESCRIPTOR; Item: DESCRIPTOR) ;
766 Head := Item ; (* Head is empty therefore make *)
767 Item^.ReadyQ.Left := Item ; (* Item the only entry on this *)
768 Item^.ReadyQ.Right := Item (* queue. *)
770 Item^.ReadyQ.Right := Head ; (* Add Item to the end of queue *)
771 Item^.ReadyQ.Left := Head^.ReadyQ.Left ;
772 Head^.ReadyQ.Left^.ReadyQ.Right := Item ;
773 Head^.ReadyQ.Left := Item
779 SubFromReady - subtract process descriptor, Item, from the Ready queue.
782 PROCEDURE SubFromReady (Item: DESCRIPTOR) ;
784 SubFromReadyQ(RunQueue[Item^.RunPriority], Item)
789 SubFromReadyQ - removes a process, Item, from a queue, Head.
792 PROCEDURE SubFromReadyQ (VAR Head: DESCRIPTOR; Item: DESCRIPTOR) ;
794 IF (Item^.ReadyQ.Right=Head) AND (Item=Head)
800 Head := Head^.ReadyQ.Right
802 Item^.ReadyQ.Left^.ReadyQ.Right := Item^.ReadyQ.Right ;
803 Item^.ReadyQ.Right^.ReadyQ.Left := Item^.ReadyQ.Left
809 SubFromSemaphoreTop - returns the first descriptor in the
813 PROCEDURE SubFromSemaphoreTop (VAR Head: DESCRIPTOR) : DESCRIPTOR ;
818 SubFromSemaphore(Head, Top) ;
820 END SubFromSemaphoreTop ;
824 SubFromSemaphore - removes a process, Item, from a queue, Head.
827 PROCEDURE SubFromSemaphore (VAR Head: DESCRIPTOR; Item: DESCRIPTOR) ;
829 IF (Item^.SemaphoreQ.Right=Head) AND (Item=Head)
835 Head := Head^.SemaphoreQ.Right
837 Item^.SemaphoreQ.Left^.SemaphoreQ.Right := Item^.SemaphoreQ.Right ;
838 Item^.SemaphoreQ.Right^.SemaphoreQ.Left := Item^.SemaphoreQ.Left
840 END SubFromSemaphore ;
844 Idle - this process is only run whenever there is no other Runnable
845 process. It should never be removed from the run queue.
850 ToOldState: PROTECTION ;
852 ToOldState := TurnInterrupts(MIN(PROTECTION)) ; (* enable interrupts *)
855 Listen for interrupts.
856 We could solve chess endgames here or calculate PI etc.
857 We forever wait for an interrupt since there is nothing else
862 (* we must NEVER exit from the above loop *)
867 InitIdleProcess - creates an idle process descriptor which
868 is run whenever no other process is Runnable.
869 The Idle process should be the only process which
870 has the priority idle.
874 IdleProcess: DESCRIPTOR ; (* Idle process always runnable *)
876 PROCEDURE InitIdleProcess ;
878 db : ARRAY [0..80] OF CHAR ;
882 ALLOCATE(Start, IdleStackSize) ;
883 Size := IdleStackSize ;
884 NEWPROCESS(Idle, Start, IdleStackSize, Volatiles) ;
885 InitQueue(SemaphoreQ) ; (* not on a semaphore queue *)
886 Which := NIL ; (* at all. *)
887 StrCopy('Idle', RunName) ; (* idle process's name *)
888 Status := Runnable ; (* should always be idle *)
889 RunPriority := idle ; (* lowest priority possible *)
890 Debugged := FALSE ; (* should never be debugging *)
892 AddToReady(IdleProcess) ; (* should be the only *)
893 (* process at this run priority *)
894 AddToExists(IdleProcess) (* process now exists.. *)
895 END InitIdleProcess ;
899 InitInitProcess - creates a descriptor for this running environment
900 so it too can be manipulated by Reschedule.
902 This concept is important to understand.
903 InitInitProcess is called by the startup code to this
904 module. It ensures that the current stack and processor
905 volatiles can be "housed" in a process descriptor and
906 therefore it can be manipulated just like any other
910 PROCEDURE InitInitProcess ;
912 NEW(CurrentProcess) ;
913 WITH CurrentProcess^ DO
914 Size := 0 ; (* we dont know the size of main stack *)
915 Start := NIL ; (* we don't need to know where it is. *)
916 InitQueue(ReadyQ) ; (* assign queues to NIL *)
918 InitQueue(SemaphoreQ) ; (* not waiting on a semaphore queue yet *)
919 Which := NIL ; (* at all. *)
920 StrCopy('Init', RunName) ; (* name for debugging purposes *)
921 Status := Runnable ; (* currently running *)
922 RunPriority := lo ; (* default status *)
923 Debugged := FALSE ; (* not deadlock debugging yet *)
925 AddToExists(CurrentProcess) ;
926 AddToReady(CurrentProcess)
927 END InitInitProcess ;
931 InitQueue - initializes a queue, q, to empty.
934 PROCEDURE InitQueue (VAR q: DesQueue) ;
944 Init - initializes all the global variables.
950 RunQueue[lo] := NIL ;
951 RunQueue[hi] := NIL ;
952 RunQueue[idle] := NIL ;
953 AllSemaphores := NIL ;