* added compilers lcc and bcc (linux86)
[mascara-docs.git] / i86 / mtx / docs / 06-multi-tasking.txt
blob9e115a9e1bb17c7521eafd04d1dc15a1dba3d3d1
1 460 Notes #3
4                CS460 NOTES on Multitasking
6 1. An Example Program:
8 ============== main.c file ======================
9 typedef struct proc{
10         struct proc *next;
11                int  ksp;
12 }PROC;
14 PROC mainProc, *running;
15 int  procSize = sizeof(PROC);
17 prints(s) char *s;
18 { YOUR prints() function }
20 main()
22   running = &mainProc;
23   prints("call tswitch()\n\r");
24      tswitch();
25   prints("back to main()\n\r");
28 int scheduler()
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.
41 begdata:
42 .bss
43 begbss:
44 .text
46 start:
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
50         mov     es,ax
51         mov     sp,#0                   ! SP = 64KB
53         call _main                      ! call main[] in C
55 dead:   jmp dead
57 _getc:
58         xorb   ah,ah
59         int    0x16
60         ret
62 _putc:
63         push   bp
64         mov    bp,sp
65         movb   al,4[bp]
66         movb   ah,#14
67         mov    bx,#0x000B
68         int    0x10
69         pop    bp
70         ret
73 _tswitch:
74 SAVE:   push ax
75         push bx
76         push cx
77         push dx
78         push bp
79         push si
80         push di
81         pushf
82         mov   bx, _running
83         mov   2[bx], sp
85 FIND:   call _scheduler
87 RESUME: mov   bx, _running
88         mov   sp, 2[bx]
89         popf
90         pop  di
91         pop  si
92         pop  bp
93         pop  dx
94         pop  cx
95         pop  bx
96         pop  ax
97         ret
98 =============================================
99           UNDER Linux:
100    as86 -o s.o s.s
101    bcc  -c main.c
102    ld86 -d s.o main.o /usr/lib/bcc/libc.a
103    mount /dev/fd0 /fd0
104    cp a.out /fd0/boot/mtx
105    umount /fd0
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.
160 begdata:
161 .bss
162 begbss:
163 .text
165 start:
166         mov     ax,cs                   ! establish segments
167         mov     ds,ax                   ! Let DS,SS,ES = CS=0x1000.
168         mov     ss,ax
169         mov     es,ax
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
179 _tswitch:
180 SAVE:   push ax
181         push bx
182         push cx
183         push dx
184         push bp
185         push si
186         push di
187         pushf
188         mov   bx, _running
189         mov   2[bx], sp
191 FIND:   call _scheduler
193 RESUME: mov   bx, _running
194         mov   sp, 2[bx]
195         popf
196         pop  di
197         pop  si
198         pop  bp
199         pop  dx
200         pop  cx
201         pop  bx
202         pop  ax
203         ret
206 _getc:
207         xorb   ah,ah
208         int    0x16
209         ret
211 _putc:
212         push   bp
213         mov    bp,sp
214         movb   al,4[bp]
215         movb   ah,#14
216         mov    bx,#0x000B   ! CYAN color
217         int    0x10
218         pop    bp
219         ret
220 !----------------- end of s.s file ---------------------------
223 /************ t.c file **********************************/
224 #define NPROC     9
225 #define SSIZE  1024                /* kstack int size */
227 #define DEAD      0                /* proc status     */
228 #define READY     1
230 typedef struct proc{
231     struct proc *next;
232            int  ksp;               /* saved sp; offset = 2 */
233            int  pid;
234            int  status;            /* READY|DEAD, etc */
235            int  kstack[SSIZE];     // kmode stack of task
236 }PROC;
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] -->
252           ^                                         |
253           |<---------------------------------------<-
255         Each proc's kstack contains:
256         retPC, ax, bx, cx, dx, bp, si, di, flag;  all 2 bytes
257 *****************************************************************/
259 int body();
261 int initialize()
263   int i, j;
264   PROC *p;
266   for (i=0; i < NPROC; i++){
267     p = &proc[i];
268     p->next = &proc[i+1];
269     p->pid = i;
270     p->status = READY;
272     if (i){     // initialize kstack[ ] of proc[1] to proc[N-1]
273       for (j=1; j<10; j++)
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
277     }
278   }
279   running = &proc[0];
280   proc[NPROC-1].next = &proc[1];
281   printf("initialization complete\n");
284 char *gasp[NPROC]={
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",
291 int grave(){
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 */
300 int ps()
302   PROC *p;
304   printf("running = %d\n", running->pid);
306   p = running;
307   p = p->next;
308   printf("readyProcs = ");
309   while(p != running && p->status==READY){
310     printf("%d -> ", p->pid);
311     p = p->next;
312   }
313   printf("\n");
316 int body()
317 {  char c;
318    while(1){
319       ps();
320       printf("I am Proc %d in body()\n", running->pid);
321       printf("Input a char : [s|q] ");
322        c=getc();
323        switch(c){
324             case 's': tswitch(); break;
325             case 'q': grave();   break;
326             default :            break;
327        }
328    }
332 main()
334  printf("\nWelcome to the 460 Multitasking System\n");
335    initialize();
336    printf("P0 switch to P1\n");
337    tswitch();
338  printf("P0 resumes: all dead, happy ending\n");
342 int scheduler()
344     PROC *p;
345     p = running->next;
347     while (p->status != READY && p != running)
348       p = p->next;
350     if (p == running)
351        running = &proc[0];
352     else
353        running = p;
355     printf("\n-----------------------------\n");
356     printf("next running proc = %d\n", running->pid);
357     printf("-----------------------------\n");
360 //=======================================================================
361 # mk file
363    as86 -o s.o s.s
364    bcc  -c t.c
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
370    umount /fd0
372 #   Use YOUR MTX booter of LAB#1 to boot up MTX