home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / 1990 / 03 / multi / mt.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-12-19  |  8.8 KB  |  378 lines

  1. /********************************************************/
  2. /*                          MT.C                        */
  3. /*              Multitasking in Turbo-C               */
  4. /*                (C) 1990 by J.Peter & toolbox            */
  5. /*                                                      */
  6. /*    Compiler: Turbo-C Borland (Version 2.0 !)       */
  7. /*    für die Speicher-Modelle : Small & Huge         */
  8. /*     Compilieren mit: tcc -B demo_mt                 */
  9. /*    einbinden in die Library mit:                   */
  10. /*       tlib lib\cs.lib +mt                          */
  11. /*    bzw.                                            */
  12. /*       tlib lib\ch.lib +mt                          */
  13. /********************************************************/
  14.  
  15. #include <math.h>
  16. #include <string.h>
  17. #include <dos.h>
  18. #include <conio.h>
  19. #include <stdio.h>
  20. #include <fcntl.h>
  21. #include <stdlib.h>
  22. #include <stddef.h>
  23.  
  24. #define _max 10   /* Höchstgrenze für die Anzahl der
  25.              parallenen Prozesse             */
  26.  
  27. #define small 8
  28. #define huge  10
  29. #define distance small    /* nötig zum Zugriff auf die
  30.                Prozessadressen auf dem Stack */
  31.  
  32.  
  33. /*************** SYSTEM PARAMETER **************/
  34.  
  35. unsigned def_w[_max][4];/* Speicher für Fenstergröße der
  36.                einzelnen Prozesse            */
  37.  
  38.  
  39. int cur_pos[_max][2];   /* Speicher für Cursorposition */
  40.  
  41. #define _stack_size 2000 /* Größe des für jeden Prozeß zu
  42.                 reservierenden Stacks         */
  43.  
  44.  
  45. int _p_time[_max];    /* Verbrauchte Prozessorzeit */
  46. int _stoped[_max];    /* Wird auf 255 gesetzt, falls
  47.                Prozess nicht mehr aktiviert
  48.                werden soll                    */
  49.  
  50. int _s_ss,_s_sp;    /* Sichern von SS & SP, bevor SS
  51.                auf das Datensegment gesetzt
  52.                wird                           */
  53. int _count;             /* Anzahl der parallel
  54.                laufenden Prozesse   */
  55.  
  56. int _stack[_max][_stack_size]; /* Stack Segment der
  57.                   parallelen Prozesse */
  58. int _save_sp[_max][2];           /* Zum Sichern der
  59.                   Stapelzeiger SS:SP
  60.                   für jeden Task          */
  61.  
  62. unsigned char _aktiv;     /* Enthält Nummer (0,1,..) des
  63.                gerade aktiven Prozesses      */
  64. unsigned char _beendet; /* Anzahl der beendeten Prozesse */
  65. unsigned char _ctrl_break;   /* wird auf 255 gesetzt,
  66.                 falls ein <Ctrl>+<C>
  67.                 aufgetreten ist          */
  68. unsigned char _using_windows; /*=true wenn Window Manager
  69.                  benutzt werden soll     */
  70.  
  71.  
  72. #if distance==small
  73.   int *_first_process;    /* Adresse des ersten Prozesses */
  74. #else
  75.   int far *_first_process;
  76. #endif
  77.  
  78.  
  79. void interrupt(*_int8_ptr)(void); /* Speicher für benötigten
  80.                      Interruptvektor      */
  81.  
  82. int _sperre=0;    /* wenn >0 erfolgt kein Prozeßwechsel */
  83. int _j;     /* Hilfsvariable */
  84.  
  85. /***   SYSTEM ROUTINEN ***/
  86.  
  87.  
  88. p()    /* Semaphor sperren */
  89. {
  90.   ++_sperre;
  91. }
  92.  
  93. v()    /* Semaphore freigeben */
  94. {
  95.   --_sperre;
  96. }
  97.  
  98. void _put_frame_char(x,y,c)
  99. char x,y,c;
  100. {
  101.    /* set cursor position */
  102.    asm mov ah,2
  103.    asm mov bh,0
  104.    asm mov dh,y
  105.    asm mov dl,x
  106.    asm int 10h
  107.    /*display character */
  108.    asm mov ah,10
  109.    asm mov bh,0
  110.    asm mov cx,1
  111.    asm mov al,c
  112.    asm int 10h
  113. }
  114.  
  115.  
  116. void draw_box(x1,y1,x2,y2)  /* Zeichnen eines Rahmens */
  117. char x1,y1,x2,y2;
  118. {
  119.   int i;
  120.   --x1; --x2; --y1; --y2;
  121.  
  122.   _put_frame_char(x1,y1,'╔');
  123.   _put_frame_char(x2,y1,'╗');
  124.   _put_frame_char(x1,y2,'╚');
  125.   _put_frame_char(x2,y2,'╝');
  126.  
  127.   for (i=x1+1; i<x2; ++i) {
  128.       _put_frame_char(i,y1,'═');
  129.       _put_frame_char(i,y2,'═');
  130.    }
  131.  
  132.    for (i=y1+1; i<y2; ++i) {
  133.       _put_frame_char(x1,i,'║');
  134.       _put_frame_char(x2,i,'║');
  135.    }
  136. }
  137.  
  138. stop_all_process()
  139. {
  140. /* Alle Prozesse außer dem gerade aktiven stoppen */
  141.   int i;
  142.   p();
  143.   for (i=0; i<_count; ++i)
  144.     if (i!=_aktiv) _stoped[i]=255;
  145.   _beendet=_count-1;
  146.   v();
  147. }
  148.  
  149. kill (pid)    /* Prozeß mit der Nummer pid stoppen */
  150. unsigned char pid;
  151. {
  152.   p();
  153.   if (pid!=_aktiv) _stoped[pid]=255;
  154.   ++_beendet;
  155.   v();
  156. }
  157.  
  158.  
  159. void interrupt _int8_handling()   /* Scheduler */
  160. {
  161.  
  162. /* Aufbau des Stacks nach Aufruf
  163.    dieser Interruptroutine
  164.  
  165.      pushf           +22
  166.      push cs         +20
  167.      push ip         +18 */
  168.  
  169. /* Befehle die C automatisch einbindet
  170.      push     ax     +16
  171.      push     bx     +14
  172.      push     cx     +12
  173.      push     dx     +10
  174.      push     es     +8    -16
  175.      push     ds     +6    -18
  176.      push     si     +4
  177.      push     di     +2
  178.      push     bp  SP +0
  179.  
  180.      mov bp,"Name des Datensegment"
  181.      mov ds,bp
  182.      mov bp,sp */
  183.  
  184.  
  185.      /* Verbrauchte Prozessor Zeit für Task erhöhen */
  186.      ++_p_time[_aktiv];
  187.  
  188.  
  189.      if (_beendet==_count | _ctrl_break) {
  190.        /* Rücksetzten des Interruptvektors falls alle
  191.       Prozesse beendet wurden oder ein CTRL-BREAK
  192.       aufgetreten ist */
  193.  
  194.        asm xor ax,ax
  195.        asm mov es,ax
  196.        asm mov si,offset _int8_ptr
  197.        asm mov di,8*4
  198.        asm mov cx,2
  199.        asm cld
  200.        asm rep movsw
  201.  
  202.        _beendet=0;
  203.        goto _int8_weiter;
  204.     }
  205.  
  206.      if (_sperre>0) goto _int8_weiter; /* kein Wechsel, da
  207.                       Prozeß in einem
  208.                       kritischen Bereich
  209.                       arbeitet */
  210.  
  211.      /* Falls Stacksegment verändert wurde,
  212.     Prozess nicht verlassen */
  213.      if (_SS!=_save_sp[_aktiv][0]) goto _int8_weiter;
  214.  
  215.      /* Sichern der Cursorposition des aktuellen Prozesses*/
  216.      if (_using_windows) {
  217.     cur_pos[_aktiv][1]=wherey();
  218.     cur_pos[_aktiv][0]=wherex();
  219.      }
  220.  
  221.  
  222.      /*Stackpointer des alten Prozesses sichern */
  223.      _save_sp[_aktiv][0]=_SS;
  224.      _save_sp[_aktiv][1]=_SP;
  225.  
  226.      /* Prozeß mit kleinster CPU Zeit
  227.     heraussuchen und aktivieren */
  228.      asm mov cx,_count
  229.      asm mov di,offset _stoped
  230.      asm mov si,offset _p_time
  231.      asm xor bx,bx
  232.      asm mov ax,0FFFFH
  233. _next_process:
  234.      asm cmp word ptr[di],0
  235.      asm jne _process_stoped
  236.      asm cmp ax,[si]
  237.      asm jbe _process_stoped
  238.      asm mov ax,[si]       /*AX=kleinste Zeit*/
  239.      asm mov _aktiv,bl
  240. _process_stoped:
  241.      asm add di,2
  242.      asm add si,2
  243.      asm inc bx
  244.      asm loop _next_process
  245.  
  246.      /* Alle Zeit Zähler um kleinste Zeit senken */
  247.      asm mov cx,_count
  248.      asm mov di,offset _p_time
  249. dec_next_ptime:
  250.      asm sub [di],ax   /* AX enthält noch die
  251.               niedrigste Prozessorzeit */
  252.      asm add di,2
  253.      asm loop dec_next_ptime
  254.  
  255.      /* Stackpointer auf alte Werte setzen */
  256.      _SS=_save_sp[_aktiv][0];
  257.      _SP=_save_sp[_aktiv][1];
  258.  
  259.      /*Window Manager */
  260.      if (_using_windows)  {
  261.     window(def_w[_aktiv][0],def_w[_aktiv][1],
  262.            def_w[_aktiv][2],def_w[_aktiv][3]);
  263.     gotoxy(cur_pos[_aktiv][0],cur_pos[_aktiv][1]);
  264.      }
  265.  
  266. _int8_weiter:
  267.      asm pushf
  268.      asm call dword ptr ds:_int8_ptr
  269. }
  270.  
  271. /*** INITIALISIERUNG ***/
  272.  
  273. co_start(windows,anzahl,prozesse)
  274. char windows;
  275. int anzahl,*prozesse;
  276. {
  277.   /* Initialiesieren der startwerte */
  278.  
  279.   if (anzahl>_max) {
  280.      /* Es dürfen nicht mehr Prozesse als maximal
  281.     Vorgesehen gestarten werden               */
  282.      exit(0);
  283.    }
  284.  
  285.   _first_process=prozesse;
  286.   _count=anzahl;
  287.   _beendet=0;
  288.   _ctrl_break=0;
  289.   _aktiv=0;
  290.   _using_windows=windows;
  291.  
  292.   for (_j=1; _j<_count; ++_j) {
  293.      _stoped[_j]=0;
  294.      _p_time[_j]=0;
  295.  
  296.      /* Vorbereiten der einzelnen Stacks */
  297.      asm mov ax,_stack_size
  298.      asm mov bx,_j
  299.      asm inc bx
  300.      asm mul bx
  301.      asm add ax,offset _stack
  302.      asm sub ax,2
  303.      asm mov di,ax
  304. #if distance==huge
  305.      asm mov [di],cs
  306.      asm sub di,2
  307. #endif
  308.      asm mov [di],offset _return_adresse
  309.      asm pushf
  310.      asm pop [di-2]
  311.      asm mov bx,_j
  312.      asm shl bx,1
  313. #if distance==huge
  314.      asm shl bx,1
  315. #endif
  316.      asm add bx,distance
  317.      asm add bx,bp
  318. #if distance==small
  319.      asm mov ax,cs
  320.      asm mov [di-4],ax     /* Codesegment */
  321. #else
  322.      asm mov ax,ss:[bx+2]
  323.      asm mov [di-4],ax
  324. #endif
  325.      asm mov ax,ss:[bx]   /* Instruction Pointer */
  326.      asm mov [di-6],ax
  327.      asm mov [di-16],es
  328.      asm mov [di-18],ds
  329.  
  330.      /* Sichern des vorgesehenen SS und SP Register */
  331.      _save_sp[_j][1]=_DI-24;
  332.      _save_sp[_j][0]=_DS;
  333.  
  334.   }
  335.      _save_sp[0][0]=_DS;
  336.  
  337.    /* Sichern des Timer Inerrupts */
  338.    _int8_ptr=getvect(8);
  339.  
  340.    /* Setzen der einzelnen Interrupt Vektoren */
  341.    setvect(0x8, _int8_handling);
  342.  
  343.    _s_ss=_SS;
  344.    _s_sp=_SP;
  345.  
  346.    asm mov ax,ds
  347.    asm mov ss,ax
  348.    asm mov sp,offset _stack+_stack_size
  349.  
  350.    if (_using_windows)
  351.       window(def_w[0][0],def_w[0][1],
  352.          def_w[0][2],def_w[0][3]);
  353.  
  354. #if distance==huge
  355.    asm call dword ptr [_first_process]
  356. #else
  357.    asm call word ptr [_first_process]
  358. #endif
  359.  
  360. asm _return_adresse:
  361.  
  362.    ++_beendet;
  363.    _stoped[_aktiv]=255;    /* Beendeter Prozeß sperren */
  364.    while (_beendet<_count) {}
  365.                /* Warteschleife bis alle
  366.                   Prozesse beendet wurden */
  367.    while (_beendet!=0) {}  /* Warten bis alle Interrupt's
  368.                   zurückgesetzt wurden       */
  369.  
  370.    _SS=_s_ss;
  371.    _SP=_s_sp;
  372.  
  373. }
  374.  
  375.  
  376. /********************************************************/
  377. /*                  Ende MT.C                       */
  378.