home *** CD-ROM | disk | FTP | other *** search
- /********************************************************/
- /* MT.C */
- /* Multitasking in Turbo-C */
- /* (C) 1990 by J.Peter & toolbox */
- /* */
- /* Compiler: Turbo-C Borland (Version 2.0 !) */
- /* für die Speicher-Modelle : Small & Huge */
- /* Compilieren mit: tcc -B demo_mt */
- /* einbinden in die Library mit: */
- /* tlib lib\cs.lib +mt */
- /* bzw. */
- /* tlib lib\ch.lib +mt */
- /********************************************************/
-
- #include <math.h>
- #include <string.h>
- #include <dos.h>
- #include <conio.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <stddef.h>
-
- #define _max 10 /* Höchstgrenze für die Anzahl der
- parallenen Prozesse */
-
- #define small 8
- #define huge 10
- #define distance small /* nötig zum Zugriff auf die
- Prozessadressen auf dem Stack */
-
-
- /*************** SYSTEM PARAMETER **************/
-
- unsigned def_w[_max][4];/* Speicher für Fenstergröße der
- einzelnen Prozesse */
-
-
- int cur_pos[_max][2]; /* Speicher für Cursorposition */
-
- #define _stack_size 2000 /* Größe des für jeden Prozeß zu
- reservierenden Stacks */
-
-
- int _p_time[_max]; /* Verbrauchte Prozessorzeit */
- int _stoped[_max]; /* Wird auf 255 gesetzt, falls
- Prozess nicht mehr aktiviert
- werden soll */
-
- int _s_ss,_s_sp; /* Sichern von SS & SP, bevor SS
- auf das Datensegment gesetzt
- wird */
- int _count; /* Anzahl der parallel
- laufenden Prozesse */
-
- int _stack[_max][_stack_size]; /* Stack Segment der
- parallelen Prozesse */
- int _save_sp[_max][2]; /* Zum Sichern der
- Stapelzeiger SS:SP
- für jeden Task */
-
- unsigned char _aktiv; /* Enthält Nummer (0,1,..) des
- gerade aktiven Prozesses */
- unsigned char _beendet; /* Anzahl der beendeten Prozesse */
- unsigned char _ctrl_break; /* wird auf 255 gesetzt,
- falls ein <Ctrl>+<C>
- aufgetreten ist */
- unsigned char _using_windows; /*=true wenn Window Manager
- benutzt werden soll */
-
-
- #if distance==small
- int *_first_process; /* Adresse des ersten Prozesses */
- #else
- int far *_first_process;
- #endif
-
-
- void interrupt(*_int8_ptr)(void); /* Speicher für benötigten
- Interruptvektor */
-
- int _sperre=0; /* wenn >0 erfolgt kein Prozeßwechsel */
- int _j; /* Hilfsvariable */
-
- /*** SYSTEM ROUTINEN ***/
-
-
- p() /* Semaphor sperren */
- {
- ++_sperre;
- }
-
- v() /* Semaphore freigeben */
- {
- --_sperre;
- }
-
- void _put_frame_char(x,y,c)
- char x,y,c;
- {
- /* set cursor position */
- asm mov ah,2
- asm mov bh,0
- asm mov dh,y
- asm mov dl,x
- asm int 10h
- /*display character */
- asm mov ah,10
- asm mov bh,0
- asm mov cx,1
- asm mov al,c
- asm int 10h
- }
-
-
- void draw_box(x1,y1,x2,y2) /* Zeichnen eines Rahmens */
- char x1,y1,x2,y2;
- {
- int i;
- --x1; --x2; --y1; --y2;
-
- _put_frame_char(x1,y1,'╔');
- _put_frame_char(x2,y1,'╗');
- _put_frame_char(x1,y2,'╚');
- _put_frame_char(x2,y2,'╝');
-
- for (i=x1+1; i<x2; ++i) {
- _put_frame_char(i,y1,'═');
- _put_frame_char(i,y2,'═');
- }
-
- for (i=y1+1; i<y2; ++i) {
- _put_frame_char(x1,i,'║');
- _put_frame_char(x2,i,'║');
- }
- }
-
- stop_all_process()
- {
- /* Alle Prozesse außer dem gerade aktiven stoppen */
- int i;
- p();
- for (i=0; i<_count; ++i)
- if (i!=_aktiv) _stoped[i]=255;
- _beendet=_count-1;
- v();
- }
-
- kill (pid) /* Prozeß mit der Nummer pid stoppen */
- unsigned char pid;
- {
- p();
- if (pid!=_aktiv) _stoped[pid]=255;
- ++_beendet;
- v();
- }
-
-
- void interrupt _int8_handling() /* Scheduler */
- {
-
- /* Aufbau des Stacks nach Aufruf
- dieser Interruptroutine
-
- pushf +22
- push cs +20
- push ip +18 */
-
- /* Befehle die C automatisch einbindet
- push ax +16
- push bx +14
- push cx +12
- push dx +10
- push es +8 -16
- push ds +6 -18
- push si +4
- push di +2
- push bp SP +0
-
- mov bp,"Name des Datensegment"
- mov ds,bp
- mov bp,sp */
-
-
- /* Verbrauchte Prozessor Zeit für Task erhöhen */
- ++_p_time[_aktiv];
-
-
- if (_beendet==_count | _ctrl_break) {
- /* Rücksetzten des Interruptvektors falls alle
- Prozesse beendet wurden oder ein CTRL-BREAK
- aufgetreten ist */
-
- asm xor ax,ax
- asm mov es,ax
- asm mov si,offset _int8_ptr
- asm mov di,8*4
- asm mov cx,2
- asm cld
- asm rep movsw
-
- _beendet=0;
- goto _int8_weiter;
- }
-
- if (_sperre>0) goto _int8_weiter; /* kein Wechsel, da
- Prozeß in einem
- kritischen Bereich
- arbeitet */
-
- /* Falls Stacksegment verändert wurde,
- Prozess nicht verlassen */
- if (_SS!=_save_sp[_aktiv][0]) goto _int8_weiter;
-
- /* Sichern der Cursorposition des aktuellen Prozesses*/
- if (_using_windows) {
- cur_pos[_aktiv][1]=wherey();
- cur_pos[_aktiv][0]=wherex();
- }
-
-
- /*Stackpointer des alten Prozesses sichern */
- _save_sp[_aktiv][0]=_SS;
- _save_sp[_aktiv][1]=_SP;
-
- /* Prozeß mit kleinster CPU Zeit
- heraussuchen und aktivieren */
- asm mov cx,_count
- asm mov di,offset _stoped
- asm mov si,offset _p_time
- asm xor bx,bx
- asm mov ax,0FFFFH
- _next_process:
- asm cmp word ptr[di],0
- asm jne _process_stoped
- asm cmp ax,[si]
- asm jbe _process_stoped
- asm mov ax,[si] /*AX=kleinste Zeit*/
- asm mov _aktiv,bl
- _process_stoped:
- asm add di,2
- asm add si,2
- asm inc bx
- asm loop _next_process
-
- /* Alle Zeit Zähler um kleinste Zeit senken */
- asm mov cx,_count
- asm mov di,offset _p_time
- dec_next_ptime:
- asm sub [di],ax /* AX enthält noch die
- niedrigste Prozessorzeit */
- asm add di,2
- asm loop dec_next_ptime
-
- /* Stackpointer auf alte Werte setzen */
- _SS=_save_sp[_aktiv][0];
- _SP=_save_sp[_aktiv][1];
-
- /*Window Manager */
- if (_using_windows) {
- window(def_w[_aktiv][0],def_w[_aktiv][1],
- def_w[_aktiv][2],def_w[_aktiv][3]);
- gotoxy(cur_pos[_aktiv][0],cur_pos[_aktiv][1]);
- }
-
- _int8_weiter:
- asm pushf
- asm call dword ptr ds:_int8_ptr
- }
-
- /*** INITIALISIERUNG ***/
-
- co_start(windows,anzahl,prozesse)
- char windows;
- int anzahl,*prozesse;
- {
- /* Initialiesieren der startwerte */
-
- if (anzahl>_max) {
- /* Es dürfen nicht mehr Prozesse als maximal
- Vorgesehen gestarten werden */
- exit(0);
- }
-
- _first_process=prozesse;
- _count=anzahl;
- _beendet=0;
- _ctrl_break=0;
- _aktiv=0;
- _using_windows=windows;
-
- for (_j=1; _j<_count; ++_j) {
- _stoped[_j]=0;
- _p_time[_j]=0;
-
- /* Vorbereiten der einzelnen Stacks */
- asm mov ax,_stack_size
- asm mov bx,_j
- asm inc bx
- asm mul bx
- asm add ax,offset _stack
- asm sub ax,2
- asm mov di,ax
- #if distance==huge
- asm mov [di],cs
- asm sub di,2
- #endif
- asm mov [di],offset _return_adresse
- asm pushf
- asm pop [di-2]
- asm mov bx,_j
- asm shl bx,1
- #if distance==huge
- asm shl bx,1
- #endif
- asm add bx,distance
- asm add bx,bp
- #if distance==small
- asm mov ax,cs
- asm mov [di-4],ax /* Codesegment */
- #else
- asm mov ax,ss:[bx+2]
- asm mov [di-4],ax
- #endif
- asm mov ax,ss:[bx] /* Instruction Pointer */
- asm mov [di-6],ax
- asm mov [di-16],es
- asm mov [di-18],ds
-
- /* Sichern des vorgesehenen SS und SP Register */
- _save_sp[_j][1]=_DI-24;
- _save_sp[_j][0]=_DS;
-
- }
- _save_sp[0][0]=_DS;
-
- /* Sichern des Timer Inerrupts */
- _int8_ptr=getvect(8);
-
- /* Setzen der einzelnen Interrupt Vektoren */
- setvect(0x8, _int8_handling);
-
- _s_ss=_SS;
- _s_sp=_SP;
-
- asm mov ax,ds
- asm mov ss,ax
- asm mov sp,offset _stack+_stack_size
-
- if (_using_windows)
- window(def_w[0][0],def_w[0][1],
- def_w[0][2],def_w[0][3]);
-
- #if distance==huge
- asm call dword ptr [_first_process]
- #else
- asm call word ptr [_first_process]
- #endif
-
- asm _return_adresse:
-
- ++_beendet;
- _stoped[_aktiv]=255; /* Beendeter Prozeß sperren */
- while (_beendet<_count) {}
- /* Warteschleife bis alle
- Prozesse beendet wurden */
- while (_beendet!=0) {} /* Warten bis alle Interrupt's
- zurückgesetzt wurden */
-
- _SS=_s_ss;
- _SP=_s_sp;
-
- }
-
-
- /********************************************************/
- /* Ende MT.C */