Tentamen Datorteknik och realtidssystem, TSEA81 Datum Lokal

Relevanta dokument
Tentamen Datorteknik och realtidssystem, TSEA81 Datum Lokal

Tentamen. Datorteknik och realtidssystem

Tentamen. Datorteknik och realtidssystem

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

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

Fö 7 TSEA81. Scheduling

Tentamen. Datorteknik och realtidssystem

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

Fö 2 TSEA81 Datorteknik och realtidssystem

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

Fö 4 TSEA81. Monitors and Message passing

Operativsystem ID1200/06 och ID2200/06 Tentamen TENA 6 hp :00-18:00

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

Fö 8 TSEA81. Real-time Linux

Operativsystem ID1200/06 Tentamen :00-18:00

Tentamen i Realtidsprogrammering för Au3, D3, E3

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

KTH STH TENTAMEN. HI1024:TEN2 - Praktisk tentamen Tid: 8-13, den 18 februari 2012

(2) Skriv ett program som skapar ett antal processer vars relationer beskrivs av nedanstående tidsdiagram a

Raspberry Pi och Tellstick, ett program i C.

Tentamen *:58/ID100V Programmering i C Exempel 3

HI1024, Programmering, grundkurs, 8hp KTH STH TENTAMEN. HI1024:TEN2 - Praktisk tentamen Tid: Fredagen den 21 oktober 2011,

Övning från förra gången: readword

Tentamen. Datorteknik och realtidssystem

Realtidsstöd i Minix. En laborationrapport. Oktober 2012

En kort text om programmering i C.

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

Realtidsprogrammering Ordinarie tentamen

HI1024 Programmering, grundkurs TEN

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

tentaplugg.nu av studenter för studenter

Lösningar till tentamen i EIT070 Datorteknik

Omtentamen i Realtidsprogrammering för Au3, D3, E3

... Funktionsanrop. Vad händer när man kör ett program?

Grundprogrammen. combine

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

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

HI1024, Programmering, grundkurs, 8hp KTH STH TENTAMEN. HI1024:TEN1 - Teoretisk tentamen Tid: Torsdagen den 20 oktober 2011,

Lösningar till uppgifterna sätts ut på kurssidan på nätet i dag kl Omtentamen i Programmering C, Fri, Kväll,

Pekare och arrayer. Indexering och avreferering

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)

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

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

Operativsystem ID1200/06 och ID2200/06 Tentamen TENA 6 hp :00-18:00

Kompilatorer och interpretatorer

Lösningar till tentamen i EIT070 Datorteknik

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

#include <stdio.h> #include <string.h>

Lösningar till tentamen i EIT070 Datorteknik

Tentamen omfattar 40 poäng fördelade på 7 uppgifter. 20 poäng krävs för betyget 3, 30 poäng för betyget 4 och 36 poäng för betyget 5.

Recap Mera om nya typer Kort Fält. Programmering. Sommarkurs Verónica Gaspes. IDE-sektionen.

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

Kurskod D0010E Datum Skrivtid 5tim

Tentamen i Algoritmer & Datastrukturer i Java

2... uppvisa förmåga att skapa och/eller hantera flerprocessiga program där de ingående processerna ges

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

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

BMI = (vikt i kg) / (längd i m) 2. Lösningsförslag

Institutionen för elektro- och informationsteknologi, LTH

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

Programmering i C, 7,5 hp

TENTAMEN. Luleå tekniska universitet

HI1024 Programmering, grundkurs TEN

Tentamen. Datorteknik Y, TSEA28

Tentamen i TDIU16 Process- och operativsystemprogrammering

OOP Tentamen

Kompilatorer och interpretatorer

BINÄRA TRÄD. (X = pekarvärdet NULL): struct int_bt_node *pivot, *ny; X X X 12 X X 12 X X -3 X X

TENTAMEN PROGRAMMERING I JAVA, 5P SOMMARUNIVERSITETET

Grundläggande programmering med C# 7,5 högskolepoäng. Provmoment: Ladokkod: Tentamen ges för: TEN1 NGC011 ADAEK17, ASYST17 samt öppen för alla

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

TENTAMEN OOP

Övning 3 i 2D1324. Strukturering h filer deklaration vs definition Debuggning gdb Preprocessorn #define assert(s) FILE LINE Länkning

TDDC74 Lab 04 Muterbara strukturer, omgivningar

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

Programmering av inbyggda system. Kodningskonventioner. Viktor Kämpe

Klassdeklaration. Metoddeklaration. Parameteröverföring

printenv sort pager printenv grep args sort pager

Dataminne I/O Stack 0x005D 0x3D SP low byte 0x005E 0x3E SP high byte

Maskinorienterad programmering

Tentamen i Introduktion till programmering

Dynamiskt minne. Vad är dynamiskt minne Motivering Hur gör man i C Övningar

struct egendefinierad typ struct LECTURE_TYPE { char teacher[99]; float lengthinminutes; char type; /* L = lecture, E = exercise */ };

Uttryck och villkor. Föreläsning 2

Outline. Datorsystemtekni. Kravspecifikation. Kravspecifikation (forts.)

Fortsä'ning Pekare. Ulf Assarsson. Originalslides av Viktor Kämpe

Problemlösning. Veckodagsproblemet Gissa talet Siffersumman

#include <pthread.h> #include <stdio.h> int p1[2]; void* char_print (void* parameter) { int fds; fds = *((int *)parameter); int i;

Exam Concurrent and Real-Time Programming

Mål. Datorteknik. Repetition av avbrott. Innehåll. Mätning och styrning. Datorer för mätning och styrning. timer. Datorsystem A/D. Analog insignal D/A

LÖSNINGSFÖRSLAG TILL Tentamen i objektorienterad programmering i C++ I

*Pekarvärden *Pekarvariabler & *

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

Abstrakta datastrukturer

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

TENTAMEN I PROGRAMMERING. På tentamen ges graderade betyg:. 3:a 24 poäng, 4:a 36 poäng och 5:a 48 poäng

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

Tentamen Lösningar EDA698 Realtidssystem

Arduinokurs. Kurstillfälle 4

Länkade listor kan ingå som en del av språket, dock ej i C Länkade listor är ett alternativ till:

Transkript:

Tentamen Datorteknik och realtidssystem, TSEA81 Datum 2018-04-0 Lokal G6 Tid 14-18 Kurskod TSEA81 Provkod TEN1 Kursnamn Datorteknik och realtidssystem Institution ISY Antal uppgifter 5 Antal sidor 16 (inklusive denna sida) Kursansvarig Anders Nilsson Lärare som besöker skrivsalen Anders Nilsson Telefon under skrivtiden 01-28 265 Besöker skrivsalen Cirka 15 och 17 Kursadministratör Gunnel Hässler 01-28 2606 Tillåtna hjälpmedel Betygsgränser Inga Poäng Betyg 41-50 5 1-40 4 21-0 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

2

Uppgift 1: Periodiska processer(10p) Ett realtidssystem med två periodiska processer, P1 och P2, ska schemaläggas. Följande krav gäller: P1 ska arbeta/köra under tidsenheter i tidsintervallet [i7, (i + 1)7], där i är ett heltal och i 0. P2 ska arbeta/köra under tidsenheter i tidsintervallet [i5, (i + 1)5], där i är ett heltal och i 0. Varje process aktiveras (är körklar) vid startpunkten för respektive tidsintervall. Det innebär att P1 aktiveras vid var 7:e tidsenhet, med start vid tidpunkten 0 och P2 aktiveras vid var 5:e tidsenhet, med start vid tidpunkten 0. Varje process har en deadline vid slutet av respektive tidsintervall. Det innebär att P1 har en deadline vid var 7:e tidsenhet, med början vid tidpunkten 7 och P2 har en deadline vid var 5:e tidsenhet, med början vid tidpunkten 5. Tänk på att för varje deluppgift nedan tydligt visa och motivera hur du kommer fram till svaret. Ett sätt kan vara att rita en tidslinje där det framgår när och hur länge respektive process kör och var de har sina deadlines. För följande deluppgifter, avgör om processerna uppfyller kraven. Om de uppfyller kraven ange var det finns outnyttjad processortid. Om de inte uppfyller kraven ange vid vilka tidpunkter processerna missar sina deadlines. Eventuellt missade deadlines medför att det arbete som inte utförts inom ett tidsintervall förkastas, dvs det ackumuleras inte till kommande tidsintervall. Ange också den faktiska utnyttjandegraden under ovanstående förutsättningar och krav. (a) (5p) Antag att schemaläggningen Earliest Deadline First (EDF) används. (b) (5p) Antag att schemaläggningen priority based preemptive scheduling (prioritetsbaserad påtvingad schemaläggning) används samt att P1 har högre prioritet än P2.

Uppgift 2: Semaforer(8p) Antag att funktionerna wait och signal för semaforerna i ett realtidsoperativsystem fungerar enligt följande pseudokod: void wait(scb * Mutex) så länge fältet count i Mutex är lika med noll flytta körande process PCB från ReadList till WaitList anropa Schedule minska fältet Count i Mutex med ett void signal(scb *Mutex) nollställ flagga för att anropa Schedule om fältet WaitList i Mutex inte representerar en tom lista flytta ett PCB från listan WaitList till ReadyList sätt flagga för att anropa Schedule öka fältet count i Mutex med ett om flaggan för att anropa Schedule är satt anropa Schedule Betrakta sedan följande program i Simple-OS: #include <simple_os.h> #include <stdio.h> #define STACK_SIZE 5000 /* define task stack spaces */ stack_item A_stack[STACK_SIZE]; stack_item B_stack[STACK_SIZE]; si_semaphore S1; // define semaphore void do_work() int i; volatile int work_data; for(i=0; i < 75000000;i++) work_data=i; 4

/* task A */ void A(void) si_sem_wait(&s1); printf("p\n"); si_wait_n_ms(1000); printf("r\n"); si_sem_signal(&s1); printf("o\n"); do_work(); printf("c\n"); si_sem_wait(&s1); printf("e\n"); si_wait_n_ms(2000); printf("s\n"); si_sem_signal(&s1); printf("s\n"); while(1); /* task B */ void B(void) si_wait_n_ms(500); printf("t\n"); si_sem_wait(&s1); printf("a\n"); do_work(); printf("s\n"); si_sem_signal(&s1); printf("k\n"); while(1); // wait on semaphore // sleep for 1000 ms // signal on semaphore // do some work for some time // wait on semaphore // sleep for 2000 ms // signal on semaphore // wait for ever // sleep for 500 ms // wait on semaphore // do some work for some time // signal om semaphore // wait for ever /* main program */ int main(void) /* initialise simple OS kernel */ si_kernel_init(); /* initialise semaphore to 1 */ si_sem_init(&s1, 1); /* create tasks */ si_task_create(a, &A_stack[STACK_SIZE-1], 10); // high priority si_task_create(b, &B_stack[STACK_SIZE-1], 20); // low priority /* start the kernel, also starting tasks */ si_kernel_start(); return 0; 5

Beskriv steg för steg vad som händer från det att de båda processerna A och B är körklara. Var noga med att tala om vilka processer som är körande, vilka listor dom ligger i vid olika tillfällen, semaforens värde samt motivera varför olika händelser sker. Listornas exakta namn är inte viktigt, bara det framgår vad deras syfte är. Ange också den resulterande utskriften. 6

Uppgift : Await / Cause(10p) Följande programrader är listningar av funktionerna Await och Cause. Tyvärr har vissa av raderna blivit felaktiga. Ange vilka av raderna som är felaktiga och vad det ska stå där för att få korrekt funktion. OBSERVERA! Om du ändrar på redan korrekta rader så medför det poängavdrag! 00 /* Await */ 01 void si_ev_wait(si_event *ev) 02 0 int pid; 04 DISABLE_INTERRUPTS; 05 if (!ready_list_is_empty(ev->wait_list, WAIT_LIST_SIZE)) 06 07 pid = wait_list_insert_highest_prio(ev->wait_list, 08 WAIT_LIST_SIZE); 09 wait_list_insert(pid); 10 11 else 12 1 ev->mutex->counter++; 14 15 pid = process_get_pid_running(); 16 wait_list_remove(pid); 17 wait_list_insert(ev->wait_list, WAIT_LIST_SIZE, pid); 18 schedule(); 19 ENABLE_INTERRUPTS; 20 21 22 /* Cause */ 2 void si_ev_cause(si_event *ev) 24 25 int done; 26 int pid; 27 done = wait_list_is_empty(ev->wait_list, WAIT_LIST_SISZE); 28 DISABLE_INTERRUPTS; 29 ev->mutex->counter--; 0 while(!done) 1 2 pid = ready_list_remove_one(ev->mutex->wait_list, WAIT_LIST_SIZE); wait_list_remove(ev->mutex->wait_list, WAIT_LIST_SIZE, pid); 4 done = wait_list_is_empty(ev->wait_list, WAIT_LIST_SIZE); 5 6 ENABLE_INTERRUPTS; 7 7

Uppgift 4: 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. 8

Uppgift 5: Monitor(12p) Man önskar ta fram ett program med tre processer, A, B och C. Processerna ska kommunicera via en gemensam buffer. Processen A ska kontinuerligt producera/skriva data till buffern. Processen B ska konsumera/läsa var tredje data som skrivits i buffern, med början på det första datat, samt skriva ut det data som lästs. Processen C ska konsumera/läsa två på varandra följande data i buffern, med början på det andra datat, samt skriva ut de data som lästs. Låt processen A producera data enligt en uppräkning, såsom: 0, 1, 2,, 4, 5, 6,... osv. Processen B ska då konsumera data enligt följande: 0,, 6,... osv. Processen C ska då konsumera data enligt följande: 1, 2, 4, 5,... osv. Utskriften skulle alltså kunna se ut enligt följande: B:0 C:1 C:2 B: C:4 C:5 B:6... Din uppgift är att skriva programkoden (C-kod) för processerna A, B och C. Själva huvudprogrammet och initieringar är redan gjorda enligt nedan. Du får INTE göra ytterligare globala definitioner eller programsatser. Dvs, du får endast skriva den kod som ingår i processerna A, B och C. #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #include <unistd.h> #define BUFFER_SIZE 10 /* buffer */ struct int data[buffer_size]; int in_pos; int out_pos; int count; pthread_mutex_t M; pthread_cond_t C; buf; 9

sem_t S1; sem_t S2; sem_t S; void *A_thread(void *unused)... void *B_thread(void *unused)... void *C_thread(void *unused)... int main(int argc, char **argv) pthread_mutex_init(&buf.m, NULL); buf.in_pos = 0; buf.out_pos = 0; buf.count = 0; sem_init(&s1, 0, 0); sem_init(&s2, 0, 0); sem_init(&s, 0, 0); pthread_t A_thread_handle; pthread_t B_thread_handle; pthread_t C_thread_handle; pthread_create(&a_thread_handle, NULL, A_thread, 0); pthread_create(&b_thread_handle, NULL, B_thread, 0); pthread_create(&c_thread_handle, NULL, C_thread, 0); pthread_join(a_thread_handle, NULL); pthread_join(b_thread_handle, NULL); pthread_join(c_thread_handle, NULL); while(1); Observera, din programkod måste vara kommenterad för full poäng. 10

Lösningsförslag fråga 1: 1a Med EDF (Earliest Deadline First) är det möjligt att uppnå 100 procent utnyttjandegrad, vilket också blir fallet här, dvs U e = 1. P2 (alternativt P1) kommer dock att missa sin deadline vid tidpunkten t=5. P1 P2 2 0 1 2 4 5 6 7 8 9 10 11 12 1 14 15 16 17 18 19 20 21 22 2 24 25 26 27 28 29 0 1 2 4 5 1b Med prioritetsbaserad påtvingad schemaläggning och där prioritetsordningen P1 > P2 gäller kommer P1 alltid att klara sina deadlines, men P2 missar deadlines vid tidpunkterna t=5, 10 och 25. Det kommer att finnas outnyttjad processortid under tidsintervallen t=1-14 samt t=4-5. Utnyttjandegraden blir sålunda U e = /5. P1 P2 2 2 1 1 0 1 2 4 5 6 7 8 9 10 11 12 1 14 15 16 17 18 19 20 21 22 2 24 25 26 27 28 29 0 1 2 4 5 Lösningsförslag fråga 2: Programmet skriver ut: P T R O C E S S Här finns tre tillfällen som kan orsaka ett processbyte. När en process gör sleep (och en annan process är körklar), när en process anropar wait (och semaforens värde är 0) samt när en process kör signal (och en högre prioriterad process är körklar). Tre listor blir aktuella, en time-list för då sleep anropas (T), en wait-list för semaforen (W) och en ready-lista för körklara processer (R). A B körande counter T W R 1) A 1 A,B 2) wait A 0 A,B ) sleep(1) sleep(0.5) - 0 A,B - 4) wait (B) 0 A B (B) 5) signal A 1 A,B 6) wait A 0 A,B 7) sleep(2) (B) 0 A B 8) signal A 1 A,B 1) Från det att båda processerna är körklara blir A (högst prioritet) körande. 2) A gör wait (W tom) counter ) printf(p), A gör sleep(1), B blir körande och gör sleep(0.5) varpå båda ligger i T 4) B vaknar först (läggs i R), printf(t), B gör wait (counter==0) och läggs i W 5) A vaknar, printf(r), kör signal (B till R, counter++, schedule anropas), och A med högst prio fortsätter, printf(o), do work, printf(c) 6) A gör wait (counter==1) och fortsätter (counter ), print(e) 11

7) A gör sleep(2) (läggs i T), B blir körande men counter==0 så B läggs i W 8) A vaknar, print(s), gör signal (B till R, counter++, schedule anropas), och A med högst prio fortsätter, printf(s), A går in i oändlig while-loop Lösningsförslag fråga : 00 /* Await */ 01 void si_ev_wait(si_event *ev) 02 0 int pid; 04 DISABLE_INTERRUPTS; 05 if (!wait_list_is_empty(ev->mutex->wait_list, WAIT_LIST_SIZE)) 06 07 pid = wait_list_remove_highest_prio(ev->mutex->wait_list, 08 WAIT_LIST_SIZE); 09 ready_list_insert(pid); 10 11 else 12 1 ev->mutex->counter++; 14 15 pid = process_get_pid_running(); 16 ready_list_remove(pid); 17 wait_list_insert(ev->wait_list, WAIT_LIST_SIZE, pid); 18 schedule(); 19 ENABLE_INTERRUPTS; 20 21 22 /* Cause */ 2 void si_ev_cause(si_event *ev) 24 25 int done; 26 int pid; 27 DISABLE_INTERRUPTS; 28 done = wait_list_is_empty(ev->wait_list, WAIT_LIST_SISZE); 29 0 while(!done) 1 2 pid = wait_list_remove_one(ev->wait_list, WAIT_LIST_SIZE); wait_list_insert(ev->mutex->wait_list, WAIT_LIST_SIZE, pid); 4 done = wait_list_is_empty(ev->wait_list, WAIT_LIST_SIZE); 5 6 ENABLE_INTERRUPTS; 7 12

Lösningsförslag fråga 4: 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å.. 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. Lösningsförlag fråga 5: #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #include <unistd.h> #define BUFFER_SIZE 10 /* buffer */ struct int data[buffer_size]; int in_pos; int out_pos; int count; pthread_mutex_t M; pthread_cond_t C; buf; 1

sem_t S1; sem_t S2; sem_t S; void *A_thread(void *unused) int num = 0; while(1) pthread_mutex_lock(&buf.m); while (buf.count == BUFFER_SIZE) pthread_cond_wait(&buf.c, &buf.m); buf.data[buf.in_pos++] = num++; buf.count++; pthread_cond_broadcast(&buf.c); if (buf.in_pos == BUFFER_SIZE) buf.in_pos = 0; pthread_mutex_unlock(&buf.m); sem_post(&s1); void *B_thread(void *unused) int data; while(1) sem_wait(&s1); pthread_mutex_lock(&buf.m); while(buf.count == 0) pthread_cond_wait(&buf.c, &buf.m); data = buf.data[buf.out_pos++]; buf.count--; pthread_cond_broadcast(&buf.c); if (buf.out_pos == BUFFER_SIZE) 14

buf.out_pos = 0; printf("b:%d\n", data); pthread_mutex_unlock(&buf.m); sem_post(&s2); sem_wait(&s); void *C_thread(void * unused) int data; int i; while(1) sem_wait(&s2); pthread_mutex_lock(&buf.m); for (i=0; i<2; i++) while(buf.count == 0) pthread_cond_wait(&buf.c, &buf.m); data = buf.data[buf.out_pos++]; buf.count--; pthread_cond_broadcast(&buf.c); if (buf.out_pos == BUFFER_SIZE) buf.out_pos = 0; printf("c:%d\n", data); pthread_mutex_unlock(&buf.m); sem_post(&s); int main(int argc, char **argv) pthread_mutex_init(&buf.m, NULL); buf.in_pos = 0; 15

buf.out_pos = 0; buf.count = 0; sem_init(&s1, 0, 0); sem_init(&s2, 0, 0); sem_init(&s, 0, 0); pthread_t A_thread_handle; pthread_t B_thread_handle; pthread_t C_thread_handle; pthread_create(&a_thread_handle, NULL, A_thread, 0); pthread_create(&b_thread_handle, NULL, B_thread, 0); pthread_create(&c_thread_handle, NULL, C_thread, 0); pthread_join(a_thread_handle, NULL); pthread_join(b_thread_handle, NULL); pthread_join(c_thread_handle, NULL); while(1); 16