/* PLP Aufgabe 1 23. April 1999 / Stand 30. April 1999 */ #include #include #define EV_QUEUE 0x0001 #define EV_TAST 0x0002 #define EV_FERT 0x0001 #define EV_TERM 0x8000 /* functionen */ void init (void); /* initalisierung */ void clup (void); /* aufraeumen */ void erfa (void); /* erfassung */ void ausg (void); /* ausgabe */ /* tasks */ void rtsk (ULONG plow, ULONG phigh, ULONG id); /* task zum rechnen einer zeile */ void etsk (ULONG plow, ULONG phigh); /* task zur zentralen steuerung */ /* typen */ struct felddef /* Zeile der Tabelle */ { int a; /* Werte */ int b; int c; ULONG tsk; /* taskid des zugeordneten rtsk */ ULONG bel; /* kennzeichner, ob mit berechnung belegt */ ULONG smid; /* sperre pro task/zeile */ }; /* globale variablen */ struct felddef feld[3+1]; /* Tabelle mit Werten,Belegt und taskids */ ULONG err; /* hilfsvariable fehlerauswertung */ ULONG QID_qcal; /* Ids der Tasks und Queues global */ ULONG TID_etsk; /* Ids der Tasks und Queues global */ ULONG TID_root; /* Ids der Tasks und Queues global */ ULONG Task_argument[4]; /* hilfsvariable zur taskerzeugung */ void main (void) { ULONG events=0; /* ergebnis des ereignisses */ char c = ' '; /* puffer fuer tastaturabfrage */ init(); /* init */ err=t_create("etsk",100,4096,4096,0,&TID_etsk);/* Erfassungstask erzeugen */ Task_argument[0]= 50; Task_argument[1]=150; /* Erfassungstask starten */ err = t_start(TID_etsk, T_PREEMPT|T_USER,etsk, Task_argument); if (err!=0) { printf ("\ntask err %d",err); } else { printf ("\ntask started"); } /* Queueerzeugung */ err = q_create("qcal",100,Q_GLOBAL|Q_FIFO|Q_NOLIMIT,&QID_qcal); if (err!=0) { printf ("\nqueue err %d",err); } else { printf ("\nqueue created"); } while (c != 'x') { c = ' '; c = getch(); /* ein zeichen zesrtörend lesen */ if (c != 'x') ev_send(TID_etsk,EV_TAST); /* bei 'x' oder 'X' terminieren einleiten */ ev_receive (EV_FERT|EV_TERM,EV_WAIT|EV_ANY,0,&events); printf ("\nready"); /* auf term oder fertig warten */ tm_wkafter (50); /* gib anderen tasks zeit zum arbeiten */ }; tm_wkafter (150); /* gib etsk zeit zum sterben */ clup (); /* aufräumen */ printf ("\nprogramm terminated"); return; } void init (void) { int id = 0; while ((id<4)) /* alle zeilen initialisieren */ { id++; feld[id].tsk = 0; feld[id].a = 0; feld[id].b = 0; feld[id].c = 0; feld[id].bel = 0; feld[id].smid= 0; err = sm_create("smid",count,SM_GLOBAL,&feld[id].smid); } t_ident("ROOT",0,&TID_root); /* root-id feststellen fuer events */ } void clup (void) { int id = 0; while ((id<4)) /* alle zeilen initialisieren */ { id++; err = sm_delete(feld[id].smid); /* semaphoren entfernen */ } err = q_delete(QID_qcal); /* Queue loeschen */ } void erfa (void) { int id=1; /* Zeilenindikator des ergebnisses */ while ((feld[id].bel!=0)&(id<4)) id++; /* suche freie zeile */ if (id>3){printf("%s","\nno free slot");} /* keine freie zeile */ else /* freie zeile entdeckt */ { feld[id].bel = 1; /* zeile sperren */ printf ("\nrow %d",id); /* daten fuer zeile "id" erfassen */ printf ("%s","\nA? "); scanf ("%d",&feld[id].a); printf ("%s","\nB? "); scanf ("%d",&feld[id].b); printf ("%s","\nC? "); scanf ("%d",&feld[id].c); if (feld[id].tsk==0) { /* kein rechentask fuer zeile id aktiv */ err = t_create("rtsk",100,4096,4096,0,&feld[id].tsk); Task_argument[0]= 50; /* rechentask erzeugen */ Task_argument[1]=150; Task_argument[2]= id; err = t_start(feld[id].tsk, T_PREEMPT|T_USER,rtsk, Task_argument); } else { /* rechentask fuer zeile id noch aktiv */ err =sm_v(feld[id].smid); /* V-Operation auf das Semaphore der Rechenzeile "id" */ } ev_send(TID_root,EV_FERT); /* eingabe fertig an root melden */ } return; } void ausg (void) { int id=-1; /* Zeilenindikator des ergebnisses */ ULONG buf[4]; /* puffer fuer ergebnis von queue */ printf ("\nresults in queue detected"); err = q_receive(QID_qcal,Q_NOWAIT,0,buf); /* ergebnis von queue */ id = buf[2]; /* die Zeile steht im 2. Parameter */ printf ("\nrow %d",id); /* daten fuer zeile "id" ausgeben */ printf ("\nA %d",feld[id].a); printf ("\nB %d",feld[id].b); printf ("\nC %d",feld[id].c); printf ("\nE %d",buf[1]); /* das ergebnis steht im 1. Parameter */ feld[id].bel = 0; /* kein task mehr fuer diese zeile aktiv */ return; } void rtsk (ULONG plow, ULONG phigh, ULONG id) { ULONG buf[4]; /* puffer fuer ergebnis */ while (1) /* task laeuft bis er selbst terminiert */ { err =sm_p(feld[id].smid,SM_WAIT,1500); /* P-Operation auf das Semaphore der Rechenzeile "id" */ if (err==1) /* timeout von max 15 sec erreicht */ { feld[id].tsk = 0; /* kein task mehr fuer zeile aktiv */ fclose(); /* Resourcefreigabe vor Terminate */ t_delete(0); /* dann terminieren */ } buf[1] = (feld[id].a+feld[id].b)/feld[id].c; /* rechnen */ buf[2] = id; /* id fuer ergebnis merken */ tm_wkafter (500); /* 5 sec rechenzeit */ err = q_send(QID_qcal,buf); /* ergebnis an queue */ ev_send(TID_etsk,EV_QUEUE); /* ergebnis liegt vor */ } } void etsk (ULONG plow, ULONG phigh) { ULONG events=0; /* ergebnis des ereignisses */ while (1) /* task laeuft bis er selbst terminiert */ { printf ("\ntask waiting"); /* endlos auf event warten */ ev_receive (EV_TAST|EV_QUEUE|EV_TERM,EV_WAIT|EV_ANY,0,&events); printf ("\nevent recogniced %d",events); /* event eingetreten */ if (EV_TERM & events) /* programm beenden (von root) */ { printf ("\ntask terminating"); fclose(); /* Resourcefreigabe vor Terminate */ t_delete(0); /* dann terminieren */ } if (EV_TAST & events) erfa (); /* eingabeaufforderung (von root) */ if (EV_QUEUE & events) ausg (); /* ausgabeaufforderung (von rtsk) */ } }