4 CS460 NOTES on Multitasking
8 ============== main.c file ======================
14 PROC mainProc, *running;
15 int procSize = sizeof(PROC);
18 { YOUR prints() function }
23 prints("call tswitch()\n\r");
25 prints("back to main()\n\r");
30 prints("in scheduler\n\r");
33 ================= s.s file ==================
34 .globl begtext, begdata, begbss ! needed by linker
35 .globl _main, _getc, _putc
36 .globl _tswitch, _running, _scheduler
38 .text ! these tell as:
39 begtext: ! text,data,bss segments
40 .data ! are all the same.
47 mov ax,cs ! establish segments
48 mov ds,ax ! we know ES,CS=0x1000. Let DS=CS
49 mov ss,ax ! SS = CS ===> all point to 0x1000
53 call _main ! call main[] in C
87 RESUME: mov bx, _running
98 =============================================
102 ld86 -d s.o main.o /usr/lib/bcc/libc.a
104 cp a.out /fd0/boot/mtx
107 Use YOUR MTX booter of LAB#1 (OR mtx_booter from the samples/LAB3/)
109 dd if=mtx_booter of=/dev/fd0
111 Boot mtx from FD to run the program.
112 It does practically NOTHING.
114 However, it is the basis of all multitasking systems. Note that in
115 scheduler() we may let running -> a different PROC structure.
116 Then tswitch() would "resume" that PROC's saved context.
118 -------------------------------------------------------------------------
119 To see this, let's define a newPORC structure, together with a new stack
120 area, int newStack[1024].
122 Although newProc never existed before, we may PRETEND that it was running
123 before and it gave up CPU by calling tswitch().
125 When calling tswitch(), it saved returnPC on its stack in newStack[1023].
126 Then, it executed SAVE, whcih saved CPU registers ax to flag
127 retPC ax, bx, cx, dx, bp, si, di, flag;
128 in newStack[]: -1 -2 -3 -4 -5 -6 -7 -8 -9
130 and newProc.savedSp -> newStack[1024-9].
131 Then, it called secheduler(), in which it gave up CPU (to our mainProc).
133 What should be the retPC? It can be the entry address of any executable
134 code. For example, a function body(){ ........}
135 What should be the values of the "saved" registers? They can be anything,
136 except for flag, which must be 0. So, we may set all of them to 0.
137 -------------------------------------------------------------------------
139 Now, in scheduler(), if we let running point to newProc, then the RESUME
140 part of tswitch() will "resume" newProc, causing it to "return" to body().
142 Changing CPU's execution environment (i.e. CPU register contents, hence
143 stack area and "point of execution") from one "activity" to that of another
144 is called CONTEXT SWITCHING.
146 2. A Simple Multi-tasking System
148 (s.s, t.c and mk are in ~samples/LAB2/; Download and test run)
151 !----------------- s.s file -----------------------------------------------
152 .globl begtext, begdata, begbss ! needed by linker
154 .globl _tswitch,_getc,_putc ! EXPORT these
155 .globl _main,_running,_scheduler,_proc,_procSize ! IMPORT these
157 .text ! these tell as:
158 begtext: ! text,data,bss segments
159 .data ! are all the same.
166 mov ax,cs ! establish segments
167 mov ds,ax ! Let DS,SS,ES = CS=0x1000.
171 mov sp,#_proc ! sp -> proc[0]
172 add sp,_procSize ! sp -> proc[0]'s HIGH END
174 call _main ! call main() in C
176 dead: jmp dead ! loop if main() ever returns
191 FIND: call _scheduler
193 RESUME: mov bx, _running
216 mov bx,#0x000B ! CYAN color
220 !----------------- end of s.s file ---------------------------
223 /************ t.c file **********************************/
225 #define SSIZE 1024 /* kstack int size */
227 #define DEAD 0 /* proc status */
232 int ksp; /* saved sp; offset = 2 */
234 int status; /* READY|DEAD, etc */
235 int kstack[SSIZE]; // kmode stack of task
239 #include "io.c" /**** USE YOUR OWN io.c with printf() here *****/
241 PROC proc[NPROC], *running;
243 int procSize = sizeof(PROC);
245 /****************************************************************
246 Initialize the proc's as shown:
247 running ---> proc[0] -> proc[1];
249 proc[1] to proc[N-1] form a circular list:
251 proc[1] --> proc[2] ... --> proc[NPROC-1] -->
253 |<---------------------------------------<-
255 Each proc's kstack contains:
256 retPC, ax, bx, cx, dx, bp, si, di, flag; all 2 bytes
257 *****************************************************************/
266 for (i=0; i < NPROC; i++){
268 p->next = &proc[i+1];
272 if (i){ // initialize kstack[ ] of proc[1] to proc[N-1]
274 p->kstack[SSIZE - j] = 0; // all saved registers = 0
275 p->kstack[SSIZE-1]=(int)body; // called tswitch() from body
276 p->ksp = &(p->kstack[SSIZE-9]); // ksp -> kstack top
280 proc[NPROC-1].next = &proc[1];
281 printf("initialization complete\n");
285 "Oh! You are killing me .......\n",
286 "Oh! I am dying ...............\n",
287 "Oh! I am a goner .............\n",
288 "Bye! Bye! World...............\n",
292 printf("\n*****************************************\n");
293 printf("Task %d %s\n", running->pid,gasp[(running->pid) % 4]);
294 printf("*****************************************\n");
295 running->status = DEAD;
297 tswitch(); /* journey of no return */
304 printf("running = %d\n", running->pid);
308 printf("readyProcs = ");
309 while(p != running && p->status==READY){
310 printf("%d -> ", p->pid);
320 printf("I am Proc %d in body()\n", running->pid);
321 printf("Input a char : [s|q] ");
324 case 's': tswitch(); break;
325 case 'q': grave(); break;
334 printf("\nWelcome to the 460 Multitasking System\n");
336 printf("P0 switch to P1\n");
338 printf("P0 resumes: all dead, happy ending\n");
347 while (p->status != READY && p != running)
355 printf("\n-----------------------------\n");
356 printf("next running proc = %d\n", running->pid);
357 printf("-----------------------------\n");
360 //=======================================================================
365 ld86 -d s.o t.o /usr/lib/bcc/libc.a
367 # mount /dev/fd0 /fd0
368 mount -o loop /root/dosemu/mtximage /fd0
369 cp a.out /fd0/boot/mtx
372 # Use YOUR MTX booter of LAB#1 to boot up MTX