Tentamen. Datorteknik och realtidssystem

Relevanta dokument
Tentamen Datorteknik och realtidssystem, TSEA81 Datum Lokal

Tentamen. Datorteknik och realtidssystem

Tentamen Datorteknik och realtidssystem, TSEA81 Datum Lokal

Fö 5+6 TSEA81. Real-time kernel + Real-time OS

Tentamen. Datorteknik och realtidssystem

Fö 7 TSEA81. Scheduling

Fö 5+6 TSEA81. Reflektion av Lab 2. clock.c (module) Real-time kernel + Real-time OS

Tentamen Grundläggande programmering

Namn: (Ifylles av student) Personnummer: (Ifylles av student) Tentamensdatum: Tid: Hjälpmedel: Inga hjälpmedel

Exam Concurrent and Real-Time Programming

Fö 7+8 TSEA81. Scheduling + Real-time Linux. wait. } else { sem->wait_list, WAIT_LIST_SIZE, pid); // semaphore waiting list

Fö 4 TSEA81. Monitors and Message passing

Föreläsning 10 Datalogi 1 DA2001. Utskrift på skärmen. Syntax. print( Hej ) Hur är det? Hej. print( Hej,end= ) print( Hur är det? ) HejHur är det?

Fö 4 TSEA81. Monitors and Message passing. Condition variables - händelsevariabler

Tentamen i Introduktion till programmering

Systemnära programmering Tentamen. Systemnära programmering, 7.5hp 5 november 2012

Föreläsning 2 Programmeringsteknik och C DD1316. Mikael Djurfeldt

Skriv i mån av plats dina lösningar direkt i tentamen. Skriv ditt kodnummer längst upp på varje blad.

Aktivitetsschemaläggning för flerkärninga processorer

Tentamen i TDIU16 Process- och operativsystemprogrammering

Föreläsning 2 Programmeringsteknik och C DD1316. Programmering. Programspråk

Enkla datatyper minne

TENTAMEN OOP

Tentamen. Datorteknik och realtidssystem

Kurskod D0010E Datum Skrivtid 5tim

Tentamen Lösningar EDA698 Realtidssystem

Institutionen för elektro- och informationsteknologi, LTH

Datorteknik. Föreläsning 5. Realtidssystem och realtidsprogrammering. Institutionen för elektro- och informationsteknologi, LTH.

En kort text om programmering i C.

tentaplugg.nu av studenter för studenter

F5 Selektion och iteration. ID1004 Objektorienterad programmering Fredrik Kilander

Programmera i C Varför programmera i C när det finns språk som Simula och Pascal??

Synkronisering. Ordning och reda

Tentamen *:58/ID100V Programmering i C Exempel 3

Realtidsprogrammering Ordinarie tentamen

Synkronisering - Semaforen. Om att vänta men inte i onödan

HI1024 Programmering, grundkurs TEN

PROGRAMMERING-JAVA TENTAMINA

Föreläsning 2 Programmeringsteknik DD1310. Programmering. Programspråk

Det finns en referensbok (Java) hos tentavakten som du får gå fram och läsa men inte ta tillbaka till bänken.

Programmering i C++ En manual för kursen Datavetenskaplig introduktionskurs 5p

Tentamen ID1004 Objektorienterad programmering October 29, 2013

Programmering I Tobias Wrigstad fredag, 2009 augusti 28

Tentamen i Algoritmer & Datastrukturer i Java

Tentamen i. för D1 m fl, även distanskursen. lördag 26 februari 2011

Operativsystem ID1200/06 Tentamen :00-18:00

Mekanismer. (implementation)

Försättsblad till skriftlig tentamen vid Linköpings Universitet Cover page for written exam at Linköping University

Skizz till en enkel databas

Outline. Datorsystemtekni. Kravspecifikation. Kravspecifikation (forts.)

Föreläsning 3: Booleans, if, switch

Tentamen vid Institutionen för Datavetenskap, Linköpings universitet

Föreläsning 10. Pekare (Pointers)

TDDC74 Programmering: Abstraktion och modellering Tenta, kl 14 18, 11 juni 2014

Realtidssystem. - Dödläge - EDAF85 - Realtidssystem (Helsingborg) Elin A. Topp. Föreläsning 5

TDDIU81. Processer och trådar. Andreas Dahlberg, Jonathan Doherty, Tony Magnusson, Patrik Ottosson, Rasmus Siljedahl

Uppgift 1 ( Betyg 3 uppgift )

Kompilering och exekvering. Föreläsning 1 Objektorienterad programmering DD1332. En kompilerbar och körbar java-kod. Kompilering och exekvering

Möte 7: Uppföljning av föreläsningen med Peer Instruction - (PI)

Realtidssystem. - Schemaläggning - EDAF85 - Realtidssystem (Helsingborg) Elin A. Topp. Föreläsning 6

Det finns en referensbok (Java) hos tentavakten som du får gå fram och läsa men inte ta tillbaka till bänken.

Symboliska konstanter const

Realtidsstöd i Minix. En laborationrapport. Oktober 2012

Visual Basic, en snabbgenomgång

732G Linköpings universitet 732G11. Johan Jernlås. Översikt. Repetition. Muddy. Funktioner / metoder. Punktnotation. Evalueringsordning

Tentamen i Algoritmer & Datastrukturer i Java

Lösningsförslag. Programmeringsmetodik, KV: Java och OOP. 17 januari 2004

Summering av fält. Synkronisering. Summering av fält. Bounded Buffer. Bounded Buffer (get) Bounded Buffer (put)

Summering av fält 1.1. Synkronisering - Semaforen. Summering av fält 1.3. Summering av fält 1.2. Summering av fält 2.3 (INTE GK)

Lösningsförslag. TDDC74 Programmering: Abstraktion och modellering. Dugga 3 (provkod TEN1), Tid: kl 14-16, Datum:

Klassdeklaration. Metoddeklaration. Parameteröverföring

Objektorienterad Programmering (TDDC77)

Programmering i C, 7,5 hp

Johan Karlsson Datavetenskap för teknisk kemi, 10p, moment 1 Datavetenskap Umeå Universitet. Tentamen

Programmering, grundkurs, 8.0 hp HI1024, TEN1. Fredagen den 2 mars 2012

Operativsystem ID1200/06 (ID2200/06 6hp) Tentamen :00-18:00

JavaScript. Innehåll. Historia. Document object model DHTML. Varför Javascript?

I Skapa Hej.java och skriv programmet. I Kompilera med javac Hej.java. I Rätta fel och repetera tills du lyckas kompilera ditt program

Omtentamen i Realtidsprogrammering för Au3, D3, E3

Tentamen Nätverksprogrammering Lösningsförslag

Föreläsning 2 Programmeringsteknik DD1310. Programmering. Programspråk

Föreläsning 6: Introduktion av listor

Tentamen i Realtidsprogrammering för Au3, D3, E3

(Lösningsförslag finns sist i denna fil.)

Grundläggande datalogi - Övning 1

Försättsblad till skriftlig tentamen vid Linköpings Universitet Cover page for written exam at Linköping University

Föreläsning 2 Programmeringsteknik och C DD1316

Fö 2 TSEA81 Datorteknik och realtidssystem

Det finns en referensbok (Java) hos tentavakten som du får gå fram och läsa men inte ta tillbaka till bänken.

Tentamen Programmeringsteknik II och NV2 (alla varianter) Skriv bara på framsidan av varje papper.

Grundläggande programmering med C# 7,5 högskolepoäng

TENTAMEN. Luleå tekniska universitet

Grundkurs Programmering

Anmälningskod: Lägg uppgifterna i ordning. Skriv uppgiftsnummer (gäller B-delen) och din kod överst i högra hörnet på alla papper

Svar till tentamen den 16 december 2013 Datorarkitekturer med operativsystem, EDT621, 7,5 poäng

Systemutvecklare SU13, Malmö

HI1024 Programmering, grundkurs TEN

Tentamen. Datorteknik Y, TSEA28

HI1024 Programmering, grundkurs TEN

Tentamen Datastrukturer (DAT036)

Transkript:

Tentamen Datorteknik och realtidssystem, TSEA81 Datum 2017-04-18 Lokal KÅRA Tid 14-18 Kurskod TSEA81 Provkod TEN1 Kursnamn Datorteknik och realtidssystem Institution ISY Antal frågor 5 Antal sidor (inklusive denna sida) 14 Kursansvarig Anders Nilsson Lärare som besöker skrivsalen Anders Nilsson Telefon under skrivtiden 013-28 2635 Besöker skrivsalen Cirka 15 och 17 Kursadministratör Gunnel Hässler 013-28 2606 Tillåtna hjälpmedel Betygsgränser Inga Poäng Betyg 41-50 5 31-40 4 21-30 3 0-20 U Viktig information Alla svar ska ha en motivation om inget annat anges. Om du svarar med programkod räknas kommentarer i programkoden som motivation. Svar som ej är motiverade kan leda till poängavdrag Om inget annat anges ska du anta att schemaläggningsmetoden som används är priority based, preemptive, scheduling Om du är osäker på det exakta namnet för en viss funktion, skriv en kommentar om vad funktionen gör så kommer vi troligtvis att förstå vad du menar. (Detsamma gäller syntaxen för programspråket C.) Skriv läsbart! Oläsbar text kan inte bedömas och ger därmed inga poäng. Lycka till! 1

Fråga 1: Semaforer(10p) Användning av semaforer och händelsevariabler kan ibland, och ibland inte, resultera i ett processbyte. T ex, en Await-operation på en händelsevariabel resulterar alltid i ett processbyte eftersom man då tvingas att vänta på händelsevariabeln. (a) (2p) Beskriv en situation där en Signal-operation på en semafor resulterar i ett processbyte. (b) (2p) Beskriv en situation där en Signal-operation på en semafor inte resulterar i ett processbyte. (c) (3p) En Await-operation används normalt på följande sätt: while (condition) Await(change) där condition utgör ett villkor (sant eller falskt) som resultatet från ett försök till access av gemensamma data. Ge två exempel på varför det är viktigt att gemensamma data är reserverade, med en Waitoperation på semaforen associerad med händelsevariabeln, när en Await-operation utförs. (d) (3p) Antag att en buffer skyddas av en semafor S. Det finns processer som skriver till buffern, vi kallar dom producenter, och processer som läser från buffern, vi kallar dom konsumenter. Producenter måste vänta när buffern är full, och konsumenter måste vänta när buffern är tom. En händelsevariabel, vi kallar den Change, associeras med semaforen S, och kan användas för detta syfte i pseudokod på följande sätt för producenter: while (buffer full) Await(Change) write to buffer Cause(Change) och på följande sätt för konsumenter: while (buffer empty) Await(Change) read from buffer Cause(Change) för att implementera villkorliga kritiska regioner. Antag en situation där det finns producenter och konsumenter som väntar på Change, på grund av att buffern varit full eller tom när dessa processer försökt att accessa buffern. Antag också att buffern innehåller exakt ett data-element och att en annan konsument läser detta data-element. När konsumenten sedan gör: Cause(Change) kommer alla väntande processer, konsumenter som producenter, att aktiveras. Detta är ju till synes onödigt eftersom buffern nu är tom och det finns egentligen ingen anledning att aktivera några konsumenter. Modifiera implementationen av pseudokoden för producenter och konsumenter ovan genom att använda två händelsevariabler, Non Full och Non Empty, så att konsumenter enbart aktiverar producenter, och producenter enbart aktiverar konsumenter. 2

Fråga 2: Periodiska processer(10p) Ett realtidssystem med tre periodiska processer, P1, P2 och P3, ska implementeras. Följande krav gäller: P1 ska köras under 1 tidsenhet i tidsintervallet [i4, (i + 1)4], där i är ett heltal och i 0. P2 ska köras under 2 tidsenheter i tidsintervallet [i8, (i + 1)8], där i är ett heltal och i 0. P3 ska köras under n tidsenheter i tidsintervallet [i12, (i + 1)12], där i är ett heltal och i 0. Varje process aktiveras vid startpunkten för respektive tidsintervall. Det innebär att P1 aktiveras vid var 4:e tidsenhet, med start vid tidpunkten 0, P2 aktiveras vid var 8:e tidsenhet, med start vid tidpunkten 0, och P3 aktiveras vid var 12:e tidsenhet, med start vid tidpunkten 0. Varje process har en deadlline vid slutet av respektive tidsintervall. Det innebär att P1 har en deadline vid var 4:e tidsenhet, med början vid tidpunkten 4, P2 har en deadline vid var 8:e tidsenhet, med början vid tidpunkten 8, och P3 har en deadline vid var 12:e tidsenhet, med början vid tidpunkten 12. Tänk på att för varje deluppgift nedan tydligt visa och motivera hur du kommer fram till svaret. (a) (5p) Antag att prioritetsbaserad påtvingad schemaläggning (priority-based preemptive scheduling) används. Antag också att P1 har högre prioritet än P2, och att P2 har högre prioritet än P3. Bestäm största möjliga värde på n, förutsatt att processernas krav uppfylls och att de klarar sina respektive deadlines. (b) (5p) Antag att schemaläggningen EDF (earliest deadline first) används. Bestäm största möjliga värde på n, förutsatt att processernas krav uppfylls och att de klarar sina respektive deadlines. 3

Fråga 3: Meddelandehantering(12p) Ett realtidsprogram som använder meddelandehantering ska implementeras, och programmet ska använda en buffer för att hantera data. En producent-process ska skriva data till buffern och en konsument-process ska läsa data från buffern. Om buffern är full när producent-processen försöker skriva data till buffern så ska producentprocessen vänta tills buffen inte är full längre. Därefter ska den försöka att skriva data igen. Om buffern är tom när konsument-processen försöker läsa data från buffern så ska konsumentprocessen vänta tills buffern inte är tom längre. Därefter ska den försöka att läsa data igen. En process ska hantera själva buffern. En buffer-datatyp finns deklarerad enligt följande: /* buffer data type */ typedef struct char data[buf_size]; int write_pos; int read_pos; int count; buf_data_type; typedef buf_data_type* buf_type; En funktion för att initiera buffern finns deklarerad enligt följande: /* buffer initialisation */ void buf_init(buf_type buf) buf->write_pos = 0; buf->read_pos = 0; buf->count = 0; Bufferns status, tom eller full, kan kontrolleras med följande funktioner: /* returns true if buf is empty, false otherwise */ int buf_empty(buf_type buf) return buf->count == 0; /* returns true if buf is full, false otherwise */ int buf_full(buf_type buf) return buf->count == BUF_SIZE; En funktion för att skriva till buffern finns deklarerad enligt följande: /* write buf_item to buf, provided buf is not full */ void buf_write(buf_type buf, char buf_item) if (buf->count < BUF_SIZE) buf->data[buf->write_pos] = buf_item; buf->write_pos++; if (buf->write_pos == BUF_SIZE) 4

buf->write_pos = 0; buf->count++; En funktion för att läsa från buffern finns deklarerad enligt följande: /* read an item from buf, provided buf is not empty */ char buf_read(buf_type buf) char buf_item = \0 ; if (buf->count > 0) buf_item buf->read_pos++; if (buf->read_pos == BUF_SIZE) buf->read_pos = 0; buf->count--; return buf_item; = buf->data[buf->read_pos]; Meddelande-typer finns deklarerade enligt följande: /* message types */ #define READ_MESSAGE 0 #define WRITE_MESSAGE 1 #define OK_MESSAGE 2 #define REPEAT_MESSAGE 3 En datatyp för meddelanden finns deklarerad enligt följande: /* message data type */ typedef struct int type; char buf_item; message_data_type; En global variabel för att spara process-id för buffer-processen finns deklarerad enligt följande: int Buffer_Task_Id; Producent-processen finns deklarerad enligt följande: void producer_task(void) message_data_type message; int length; int send_task_id; char string_to_send[] = "Houston we have a pr\n"; int i; 5

while(1) printf("sending %s\n", string_to_send); for (i = 0; i < strlen(string_to_send); i++) do message.type = WRITE_MESSAGE; message.buf_item = string_to_send[i]; si_message_send((char *) &message, sizeof(message), Buffer_Task_Id); si_message_receive((char *) &message, &length, &send_task_id); while (message.type == REPEAT_MESSAGE); si_wait_n_ms(10000); Konsument-processen finns deklarerad enligt följande: void consumer_task(void) message_data_type message; int length; int send_task_id; int n_chars = 0; while(1) do message.type = READ_MESSAGE; si_message_send((char *) &message, sizeof(message), Buffer_Task_Id); si_message_receive((char *) &message, &length, &send_task_id); while (message.type == REPEAT_MESSAGE); /* print received character and running number */ printf("%c-%d", message.buf_item, n_chars++); Huvudprogrammet skapar tre processer - buffer-processen, producent-processen och konsumentprocessen. Detta finns implementerat enligt följande: /* main */ int main(void) /* initialise kernel */ si_kernel_init(); /* initialise message handling */ si_message_init(); /* create tasks */ si_task_create(buffer_task, &Buffer_Stack[STACK_SIZE-1], 10); Buffer_Task_Id = 1; si_task_create(producer_task, &Producer_Stack[STACK_SIZE-1], 20); si_task_create(consumer_task, &Consumer_Stack[STACK_SIZE-1], 30); 6

/* start the kernel */ si_kernel_start(); /* will never be here */ return 0; Din uppgift är att implementera (skriva koden för) buffer-processen. Själva buffern ska deklareras som en lokal variabel, av typen buf data type, i buffer-processen. Det är inte tillåtet att använda några globala variabler, förutom Buffer Task Id och stackarna för respektive process. Det kan i buffer-processen antas att det bara finns en producent-process och en konsument-process. När det färdiga programmet kör ska följande utskrift fås: Sending Houston we have a pr H-0o-1u-2s-3t-4o-5n-6-7w-8e-9-10h-11a-12v-13e-14-15a-16-17p-18r-19-20Sending Houston we have a pr H-21o-22u-23s-24t-25o-26n-27-28w-29e-30-31h-32a-33v-34e-35-36a-37-38p-39r-40-41Sending Houston we have a pr H-42o-43u-44s-45t-46o-47n-48-49w-50e-51-52h-53a-54v-55e-56-57a-58-59p-60r-61 7

Fråga 4: Prioriteter(8p) Antag att följande testprogram implementeras i ett realtidsoperativsystem, t ex Simple OS. Testprogrammet innehåller en resurs som skyddas av en semafor: /* semaphore for protecting resource */ si_semaphore Mutex; /* resource */ int The_Resource; Testprogrammet innehåller tre processer. Processen P1 har högst prioritet och finns implementerad enligt följande: /* p1_task: first task */ void p1_task(void) /* infinite loop */ while(1) console_put_string("p1 trying to reserve R\n"); si_sem_wait(&mutex); console_put_string("p1 has reserved R\n"); The_Resource = 1; si_sem_signal(&mutex); console_put_string("p1 has released R\n"); si_wait_n_ms(2000); Processen P3 har lägst prioritet och finns implementerad enligt följande: /* p3_task: third task */ void p3_task(void) /* infinite loop */ while(1) console_put_string("p3 trying to reserve R\n"); si_sem_wait(&mutex); console_put_string("p3 has reserved R\n"); si_wait_n_ms(100); The_Resource = 3; si_sem_signal(&mutex); console_put_string("p3 has released R\n"); si_wait_n_ms(1000); Processen P2 har en prioritet mellan P1 och P3 och finns implementerad enligt följande: /* p2_task: second task */ void p2_task(void) /* infinite loop */ while(1) console_put_string("p2 starting to do work\n"); 8

do_work(); där funktionen do work används i syfte att belasta processorn genom att utföra diverse beräkningar. Funktionen do work använder inte semaforen Mutex eller den gemensamma resursen The Resource. När programmet körs erhålls följande utskrift: P3 trying to reserve R P3 has reserved R P1 trying to reserve R P2 starting to do work P2 starting to do work P2 starting to do work P2 starting to do work (a) (3p) Förklara varför programmet beter sig enligt ovan, och förklara hur det kommer sig att processen P2 blir körande och blockerar accessen för P1 till resursen trots att P2 inte använder resursen och dessutom har lägre prioritet än P1. (b) (1p) Vad kallas fenomenet? (c) (4p) Namnge och beskriv hur en vanlig mekanism fungerar för att förhindra att problemet uppstår, dvs så att P2 inte kan blockera P1. Du kan använda de tre specifika processerna P1, P2 och P3 i din beskrivning. 9

Fråga 5: Processbyte(10p) Betrakta situationen i figur 1 nedan. Två processer finns i ReadyList och en är körande, markerad med pekaren Running. CPU:n har under körning använt den körande processens stack och därmed kanske skrivit över tidigare värden för (Reg) och (PC) varför dessa satts inom parentes då de nu får anses vara inaktuella. Utgå från denna situation och beskriv steg för steg hur ett processbyte går till, med avseende på vad som händer i CPU:n, processernas stackar och TCB. Om du vill kan du i din beskrivning förutom pekarna Running och ReadyList använda pekarna Current (som tillfällig markering under bytet av körande process), Next (för att markera nästkommande körande process) samt WaitList eller eventuellt TimeList. Figur 1: Två processer, en körande. 10

Lösningsförslag fråga 1: 1a En Signal-operation på en semafor resulterar i ett processbyte då det finns processer som väntar på semaforen och om någon av de processer som därefter finns i readylistan har högre prioritet än den process om utförde Signal-operationen. 1b En Signal-operation på en semafor resulterar inte i ett processbyte om väntelistan för semaforen är tom, eller om ingen av de processer som finns väntelistan för semaforen har högre prioritet än den process som utförde Signal-operationen. 1c Ett skäl är att utvärderingen av condition behöver läsa gemensamma data, och dessa måste då vara reserverade när det sker. Ett annat skäl är att en Await-operation medför en implicit Signal-operation. Det medför att om gemensamma data då inte först är reserverade med Wait när Await utförs, så kan ju väntelistan vara tom och semaforen då få värdet 2, vilket framledes kan ge okontrollerad access till gemensamma data. 1d Båda händelsevariablerna, Non Full och Non Empty associeras med semaforen S. För producenter bli sedan psudokoden enligt följande: while(buffer full) Await(Non_Full) write to buffer Cause(Non_Empty) och för konsumenter enligt följande: while (buffer empty) Await(Non_Empty) read from buffer Cause(Non_Full) På detta sätt kommer konsumenter enbart att aktivera producenter och producenter enbart att aktivera konsumenter. Lösningsförslag fråga 2: 2a Körschemat för de tre processerna kommer att upprepa sig efter 24 tidsenheter. Då P1 har högst prioritet kommer den att köra vid tidsintervallen 0-1, 4-5, 8-9, 12-13, 16-17 och 20-21. Processen P2 kommer att köra i tidsintervallen 1-3, 9-11 och 17-19. Det utelämnar 5 tomma tidsenheter under tidsintervallet 0-12, och 7 tomma tidsenheter under tidsintervallet 12-14 för processen P3. För att alltid kunna uppfylla villkoren måste n sättas till det lägre av dessa alternativ, dvs n = 5. 11

2b Med EDF (Earliest Deadline First) är det möjligt att uppnå 100 procent utnyttjandegrad. Största värdet på n ges då av följande ekvation: vilket ger n = 6. Körschemat blir enligt följande: 1 4 + 2 8 + n 12 = 1 Tid dp1 dp2 dp3 Process Kommentar 0-1 4 8 12 P1 P1 kortast tid till deadline 1-2 3 7 11 P2 P1 ej körklar, P2 kortast tid till deadline 2-3 2 6 10 P2 P1 ej körklar, P2 kortast tid till deadline 3-4 1 5 9 P3 P1 och P2 ej körklara, P3 kortast tid till deadline 4-5 4 4 8 P1 P2 ej körklar, P1 körklar och kortast tid till deadline 5-6 3 3 7 P3 P1 och P2 ej körklara, P3 kortast tid till deadline 6-7 2 2 6 P3 P1 och P2 ej körklara, P3 kortast tid till deadline 7-8 1 1 5 P3 P1 och P2 ej körklara, P3 kortast tid till deadline 8-9 4 8 4 P3 P2 körklar, P1 körklar och samma tid som P3 till deadline, P3 fortsätter 9-10 3 7 3 P3 P2 körklar, P1 körklar och samma tid som P3 till deadline, P3 fortsätter 10-11 2 6 2 P1 P2 körklar, P3 ej körklar, P1 kortast tid till deadline 11-12 1 5 1 P2 P1 och P3 ej körklara, P2 kortast tid till deadline 12-13 4 4 12 P2 P3 körklar, P1 körklar och samma tid som P2 till deadline, P2 fortsätter 13-14 3 3 11 P1 P3 körklar, P2 ej körklar, P1 kortast tid till deadline 14-15 2 2 10 P3 P1 och P2 ej körklara, P3 kortast tid till deadline 15-16 1 1 9 P3 P1 och P2 ej körklara, P3 kortast tid till deadline 16-17 4 8 8 P1 P1 och P2 körklara, P1 kortast tid till deadline 17-18 3 7 7 P2 P1 ej körklar, P2 och P3 samma tid till deadline, välj t ex P2 18-19 2 6 6 P2 P1 ej körklar, P2 och P3 samma tid till deadline, P2 fortsätter 19-20 1 5 5 P3 P1 och P2 ej körklar, P3 kortast tid till deadline 20-21 4 4 4 P3 P2 ej körklar, P1 körklar och samma tid som P3 till deadline, P3 fortsätter 21-22 3 3 3 P3 P2 ej körklar, P1 körklar och samma tid som P3 till deadline, P3 fortsätter 22-23 2 2 2 P3 P2 ej körklar, P1 körklar och samma tid som P3 till deadline, P3 fortsätter 23-24 1 1 1 P1 P2 och P3 ej körklara, P1 kortast tid till deadline Lösningsförslag fråga 3: När buffern är full eller tom så kan buffer-processen inte omedelbart ge respons till producent- eller konsument-processen, eftersom ingen av dem då kommer att stanna/blockera. Vi håller istället håller reda på när access sker till en full eller tom buffer och skickar ett svarsmeddelande till producentrespektive kosument-processen när buffern inte är full respektive tom längre. Buffer-processen kan implementeras enligt följande: void buffer_task(void) buf_data_type buffer; message_data_type message; int lenght; int send_task_id; int consumer_task_id = -1; int producer_task_id = -1; int consumer_waiting = 0; 12

int producer_waiting = 0; char buf_item; buf_init(&buffer); while(1) si_message_receive((char *) &message, &length, &send_task_id); switch(message.type) case READ_MESSAGE: if (buf_empty(&buffer)) /* note that consumer is waiting, and store its task id */ consumer_waiting = 1; consumer_task_id = send_task_id; else buf_item = buf_read(&buffer); message.type = OK_MESSAGE; message.buf_item = buf_item; si_message_send((char *) &message, sizeof(message), send_task_id); if (producer_waiting) /* if a producer is waiting, let this producer re-send its last item */ message.type = REPEAT_MESSAGE; si_message_send((char *) &message, sizeof(message), producer_task_id); producer_waiting = 0; break; case WRITE_MESSAGE: if (buf_full(&buffer)) /* note that a producer is waiting, and store its task id */ producer_waiting = 1; producer_task_id = send_task_id; else buf_item = message.buf_item; buf_write(&buffer, buf_item); message.type = OK_MESSAGE; si_message_send((char *) &message, sizeof(message), send_task_id); if (consumer_waiting) /* if a consumer is waiting, let this consumer read again */ message.type = REPEAT_MESSAGE; si_message_send((char *) &message, sizeof(message), consumer_task_id); consumer_waiting = 0; break; default: 13

printf("illegal message type!\n"); exit(1); Lösningsförlag fråga 4: 4a När programmet startar så reserverar P3 resursen R. Sedan försöker P1 reservera R, men tvingas vänta eftersom semaforen nu har värdet 0. När P2 aktiveras så tillåts den exekvera, eftersom den har högre prioritet än nuvarande körande process P3, och eftersom P1 (trots att den har högre prioritet än P2 ) inte är redo då den väntar på semaforen. Så länge som P2 kör, hindras P3 att släppa resursen och P1 fortsätter att vara blockerad. 4b Prioritetsinversion (priority inversion) 4c Mekanismen som efterfrågas är prioritetsärvning (priority inheritance). Den fungerar enligt följande: I samband med att P3 reserverar resursen så höjs prioriteten på P3 till samma prioritet som den process som har högst prioritet av de som kan använda resursen, i detta fall P1. Därmed kan inte P2 avbryta P3 varvid P3 kan slutföra sitt arbete. När P3 sedan släpper resursen så återtar P3 sin tidigare prioritet. Därefter kan P1 reservera resursen och köra, alternativt P2 köra och bli avbruten av P1. P1 blir inte längre blockerad av P2. Lösningsförslag fråga 5: Processbytet sker i följande ordning: 1. Justera fälten i TCB för körande process, om det behövs. T ex för att si wait n ms() har anropats eller att prioriteten har ändrats. 2. Flytta TCB för körande process från ReadyList till en annan lista: TimeList om si wait n ms() har anropats, eller någon WaitList beroende på vad man väntar på. 3. Leta upp nästa process, den med högst prioritet i ReadyList, och markera den med Next. 4. Markera nu körande process med Current, och markera den process som ska bli körande, dvs Next, med Running. 5. Kopiera PC i CPU till stacken för nu körande process, dvs den markerad med Current. (görs t ex via PUSH) 6. Kopiera Reg i CPU till stacken för nu körande process, dvs den markerad med Current. (görs t ex via PUSH) 7. Sätt SP i TCB för körande process (Current) till samma som SP i CPU. 8. Sätt SP i CPU till SP i TCB för den process som ska starta (Next). 9. Kopiera Reg från stacken för den process som ska starta (Next) till Reg i CPU. (görs t ex via POP) 10. Kopiera PC från stacken för den process som ska starta (Next) till PC i CPU. (görs t ex via POP) I och med sista steget så sker ett hopp till den nya process som ska köra, dvs den som nu är markerad med Running. Pekarna Next och Current har längre ingen betydelse. 14