* added compilers lcc and bcc (linux86)
[mascara-docs.git] / i86 / mtx / mtx / notes3.html
blobd783b9eb27eea560321ed2b340236dc85fbf132c
1 <Title>460 Notes</Title> <Body bgcolor="#00cccc" text="#000000"><H1>460 Notes #3</H1><Pre>
3 CS460 NOTES on Multitasking
5 1. An Example Program:
7 ============== main.c file ======================
8 typedef struct proc{
9 struct proc *next;
10 int ksp;
11 }PROC;
13 PROC mainProc, *running;
14 int procSize = sizeof(PROC);
16 prints(s) char *s;
17 { YOUR prints() function }
19 main()
21 running = &mainProc;
22 prints("call tswitch()\n\r");
23 tswitch();
24 prints("back to main()\n\r");
27 int scheduler()
29 prints("in scheduler\n\r");
32 ================= s.s file ==================
33 .globl begtext, begdata, begbss ! needed by linker
34 .globl _main, _getc, _putc
35 .globl _tswitch, _running, _scheduler
37 .text ! these tell as:
38 begtext: ! text,data,bss segments
39 .data ! are all the same.
40 begdata:
41 .bss
42 begbss:
43 .text
45 start:
46 mov ax,cs ! establish segments
47 mov ds,ax ! we know ES,CS=0x1000. Let DS=CS
48 mov ss,ax ! SS = CS ===> all point to 0x1000
49 mov es,ax
50 mov sp,#0 ! SP = 64KB
52 call _main ! call main[] in C
54 dead: jmp dead
56 _getc:
57 xorb ah,ah
58 int 0x16
59 ret
61 _putc:
62 push bp
63 mov bp,sp
64 movb al,4[bp]
65 movb ah,#14
66 mov bx,#0x000B
67 int 0x10
68 pop bp
69 ret
72 _tswitch:
73 SAVE: push ax
74 push bx
75 push cx
76 push dx
77 push bp
78 push si
79 push di
80 pushf
81 mov bx, _running
82 mov 2[bx], sp
84 FIND: call _scheduler
86 RESUME: mov bx, _running
87 mov sp, 2[bx]
88 popf
89 pop di
90 pop si
91 pop bp
92 pop dx
93 pop cx
94 pop bx
95 pop ax
96 ret
97 =============================================
98 UNDER Linux:
99 as86 -o s.o s.s
100 bcc -c main.c
101 ld86 -d s.o main.o /usr/lib/bcc/libc.a
102 mount /dev/fd0 /fd0
103 cp a.out /fd0/boot/mtx
104 umount /fd0
106 Use YOUR MTX booter of LAB#1 (OR mtx_booter from the samples/LAB3/)
108 dd if=mtx_booter of=/dev/fd0
110 Boot mtx from FD to run the program.
111 It does practically NOTHING.
113 However, it is the basis of all multitasking systems. Note that in
114 scheduler() we may let running -> a different PROC structure.
115 Then tswitch() would "resume" that PROC's saved context.
117 -------------------------------------------------------------------------
118 To see this, let's define a newPORC structure, together with a new stack
119 area, int newStack[1024].
121 Although newProc never existed before, we may PRETEND that it was running
122 before and it gave up CPU by calling tswitch().
124 When calling tswitch(), it saved returnPC on its stack in newStack[1023].
125 Then, it executed SAVE, whcih saved CPU registers ax to flag
126 retPC ax, bx, cx, dx, bp, si, di, flag;
127 in newStack[]: -1 -2 -3 -4 -5 -6 -7 -8 -9
129 and newProc.savedSp -> newStack[1024-9].
130 Then, it called secheduler(), in which it gave up CPU (to our mainProc).
132 What should be the retPC? It can be the entry address of any executable
133 code. For example, a function body(){ ........}
134 What should be the values of the "saved" registers? They can be anything,
135 except for flag, which must be 0. So, we may set all of them to 0.
136 -------------------------------------------------------------------------
138 Now, in scheduler(), if we let running point to newProc, then the RESUME
139 part of tswitch() will "resume" newProc, causing it to "return" to body().
141 Changing CPU's execution environment (i.e. CPU register contents, hence
142 stack area and "point of execution") from one "activity" to that of another
143 is called CONTEXT SWITCHING.
145 2. A Simple Multi-tasking System
147 (s.s, t.c and mk are in ~samples/LAB2/; Download and test run)
150 !----------------- s.s file -----------------------------------------------
151 .globl begtext, begdata, begbss ! needed by linker
153 .globl _tswitch,_getc,_putc ! EXPORT these
154 .globl _main,_running,_scheduler,_proc,_procSize ! IMPORT these
156 .text ! these tell as:
157 begtext: ! text,data,bss segments
158 .data ! are all the same.
159 begdata:
160 .bss
161 begbss:
162 .text
164 start:
165 mov ax,cs ! establish segments
166 mov ds,ax ! Let DS,SS,ES = CS=0x1000.
167 mov ss,ax
168 mov es,ax
170 mov sp,#_proc ! sp -> proc[0]
171 add sp,_procSize ! sp -> proc[0]'s HIGH END
173 call _main ! call main() in C
175 dead: jmp dead ! loop if main() ever returns
178 _tswitch:
179 SAVE: push ax
180 push bx
181 push cx
182 push dx
183 push bp
184 push si
185 push di
186 pushf
187 mov bx, _running
188 mov 2[bx], sp
190 FIND: call _scheduler
192 RESUME: mov bx, _running
193 mov sp, 2[bx]
194 popf
195 pop di
196 pop si
197 pop bp
198 pop dx
199 pop cx
200 pop bx
201 pop ax
205 _getc:
206 xorb ah,ah
207 int 0x16
208 ret
210 _putc:
211 push bp
212 mov bp,sp
213 movb al,4[bp]
214 movb ah,#14
215 mov bx,#0x000B ! CYAN color
216 int 0x10
217 pop bp
219 !----------------- end of s.s file ---------------------------
222 /************ t.c file **********************************/
223 #define NPROC 9
224 #define SSIZE 1024 /* kstack int size */
226 #define DEAD 0 /* proc status */
227 #define READY 1
229 typedef struct proc{
230 struct proc *next;
231 int ksp; /* saved sp; offset = 2 */
232 int pid;
233 int status; /* READY|DEAD, etc */
234 int kstack[SSIZE]; // kmode stack of task
235 }PROC;
238 #include "io.c" /**** USE YOUR OWN io.c with printf() here *****/
240 PROC proc[NPROC], *running;
242 int procSize = sizeof(PROC);
244 /****************************************************************
245 Initialize the proc's as shown:
246 running ---> proc[0] -> proc[1];
248 proc[1] to proc[N-1] form a circular list:
250 proc[1] --> proc[2] ... --> proc[NPROC-1] -->
252 |<---------------------------------------<-
254 Each proc's kstack contains:
255 retPC, ax, bx, cx, dx, bp, si, di, flag; all 2 bytes
256 *****************************************************************/
258 int body();
260 int initialize()
262 int i, j;
263 PROC *p;
265 for (i=0; i < NPROC; i++){
266 p = &proc[i];
267 p->next = &proc[i+1];
268 p->pid = i;
269 p->status = READY;
271 if (i){ // initialize kstack[ ] of proc[1] to proc[N-1]
272 for (j=1; j<10; j++)
273 p->kstack[SSIZE - j] = 0; // all saved registers = 0
274 p->kstack[SSIZE-1]=(int)body; // called tswitch() from body
275 p->ksp = &(p->kstack[SSIZE-9]); // ksp -> kstack top
278 running = &proc[0];
279 proc[NPROC-1].next = &proc[1];
280 printf("initialization complete\n");
283 char *gasp[NPROC]={
284 "Oh! You are killing me .......\n",
285 "Oh! I am dying ...............\n",
286 "Oh! I am a goner .............\n",
287 "Bye! Bye! World...............\n",
290 int grave(){
291 printf("\n*****************************************\n");
292 printf("Task %d %s\n", running->pid,gasp[(running->pid) % 4]);
293 printf("*****************************************\n");
294 running->status = DEAD;
296 tswitch(); /* journey of no return */
299 int ps()
301 PROC *p;
303 printf("running = %d\n", running->pid);
305 p = running;
306 p = p->next;
307 printf("readyProcs = ");
308 while(p != running && p->status==READY){
309 printf("%d -> ", p->pid);
310 p = p->next;
312 printf("\n");
315 int body()
316 { char c;
317 while(1){
318 ps();
319 printf("I am Proc %d in body()\n", running->pid);
320 printf("Input a char : [s|q] ");
321 c=getc();
322 switch(c){
323 case 's': tswitch(); break;
324 case 'q': grave(); break;
325 default : break;
331 main()
333 printf("\nWelcome to the 460 Multitasking System\n");
334 initialize();
335 printf("P0 switch to P1\n");
336 tswitch();
337 printf("P0 resumes: all dead, happy ending\n");
341 int scheduler()
343 PROC *p;
344 p = running->next;
346 while (p->status != READY && p != running)
347 p = p->next;
349 if (p == running)
350 running = &proc[0];
351 else
352 running = p;
354 printf("\n-----------------------------\n");
355 printf("next running proc = %d\n", running->pid);
356 printf("-----------------------------\n");
359 //=======================================================================
360 # mk file
362 as86 -o s.o s.s
363 bcc -c t.c
364 ld86 -d s.o t.o /usr/lib/bcc/libc.a
366 # mount /dev/fd0 /fd0
367 mount -o loop /root/dosemu/mtximage /fd0
368 cp a.out /fd0/boot/mtx
369 umount /fd0
371 # Use YOUR MTX booter of LAB#1 to boot up MTX