Hur kan man designa req_lock_acquire och req_lock_release för ett sådant lås?

Relevanta dokument
Synkronisering. Ordning och reda

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

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

Föreläsning 6: Introduktion av listor

Avbildningar och hashtabeller. Koffman & Wolfgang kapitel 7, mestadels avsnitt 2 4

Tommy Färnqvist, IDA, Linköpings universitet

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

Recitation 4. 2-D arrays. Exceptions

GU / Chalmers Campus Lindholmen Tentamen Programutveckling LEU 482 / TIG167

Mekanismer. (implementation)

Tentamen i TDIU16 Process- och operativsystemprogrammering

Föreläsning 4. ADT Kö Kö JCF Kö implementerad med en cirkulär array Kö implementerad med en länkad lista

Dugga Datastrukturer (DAT036)

Programmeringsteknik med C och Matlab

Support Manual HoistLocatel Electronic Locks

F12 - Collections. ID1004 Objektorienterad programmering Fredrik Kilander

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

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

Föreläsning 3. Stack

Tentamen PC-teknik 5 p

Föreläsning Datastrukturer (DAT036)

Tentamen Grundläggande programmering

Länkade strukturer. (del 2)

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

Abstrakt datatyp. -Algoritmer och Datastrukturer- För utveckling av verksamhet, produkter och livskvalitet.

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

Exam Concurrent and Real-Time Programming

Tentamen TEN1 HI

TDIU01 - Programmering i C++, grundkurs

Classes och Interfaces, Objects och References, Initialization

Exempelsamling Assemblerprogrammering

Schenker Privpak AB Telefon VAT Nr. SE Schenker ABs ansvarsbestämmelser, identiska med Box 905 Faxnr Säte: Borås

Objektsamlingar i Java

TDDC74 Programmering: Abstraktion och modellering Datortenta , kl 14-18

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

Grafer, traversering. Koffman & Wolfgang kapitel 10, avsnitt 4

OOP Objekt-orienterad programmering

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

Föreläsning Datastrukturer (DAT037)

Programmering för språkteknologer II, HT2014. Rum

TDDC74 Programmering: Abstraktion och modellering Dugga 2, , kl 14-16

TDDC74 FÖRELÄSNING 9 ANDERS MÄRAK LEFFLER IDA/HCS

Tentamen Datastrukturer (DAT036)

Datastrukturer, algoritmer och programkonstruktion (DVA104, VT 2015) Föreläsning 6

EDAA20 Föreläsning Klassen ArrayList. Viktiga operationer på ArrayList. Generisk klass

Föreläsning 3. Stack

Lösningar till tentamen i EIT070 Datorteknik

Föreläsning 7 Innehåll. Rekursion. Rekursiv problemlösning. Rekursiv problemlösning Mönster för rekursiv algoritm. Rekursion. Rekursivt tänkande:

Grundläggande datalogi - Övning 4

Typkonvertering. Java versus C

GU / Chalmers Campus Lindholmen Tentamen Programutveckling LEU 482 / TIG167

Att deklarera och att använda variabler. Föreläsning 10. Synlighetsregler (2) Synlighetsregler (1)

Att skriva till och läsa från terminalfönstret

Föreläsning Datastrukturer (DAT036)

Programmering I Tobias Wrigstad fredag, 2009 augusti 28

TDDC30 Programmering i Java, Datastrukturer och Algoritmer Lektion 2. Länkade listor Stackar Köer MyList Iteratorer Lab 2 Exceptions Paket

TDDC74 Programmering: Abstraktion och modellering Dugga 2, , kl 17-19

Datastrukturer. föreläsning 3. Stacks 1

Lite om felhantering och Exceptions Mer om variabler och parametrar Fält (eng array) och klassen ArrayList.

Föreläsning 4. ADT Kö Kö JCF Kö implementerad med en cirkulär array Kö implementerad med en länkad lista Läsanvisningar och uppgifter

Isolda Purchase - EDI

Föreläsning Datastrukturer (DAT036)

Lösningsförslag till tentamen i EDA690 Algoritmer och Datastrukturer, Helsingborg

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

Chapter 4: Writing Classes/ Att skriva egna klasser.

Det är principer och idéer som är viktiga. Skriv så att du övertygar rättaren om att du har förstått dessa även om detaljer kan vara felaktiga.

TDDC30. Objektorienterad programmering i Java, datastrukturer och algoritmer. Föreläsning 3 Jonas Lindgren, Institutionen för Datavetenskap, LiU

Objektorienterad Programkonstruktion. Föreläsning 2 2 nov 2016

Tentamen: Datordel Programmeringsteknik

Föreläsning 8: Exempel och problemlösning

Datalogi, grundkurs 1. Lösningsförslag till tentamen

Schenker Privpak AB Telefon VAT Nr. SE Schenker ABs ansvarsbestämmelser, identiska med Box 905 Faxnr Säte: Borås

Resa Att ta sig runt. Att ta sig runt - Platser. I am lost. Du vet inte var du är

Resa Att ta sig runt. Att ta sig runt - Platser. Du vet inte var du är. Be om att bli visad en viss plats på en karta. Fråga om en viss servicepunkt

Övning 1 - Abstrakta datatyper

Isometries of the plane

Concurrency Saker händer samtidigt. Process En instans av ett program

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

TENTAMEN PROGRAMMERINGSMETODIK MOMENT 2 - JAVA, 4P

Tentamen i kurserna Beräkningsmodeller (TDA181/INN110) och Grundläggande Datalogi (TDA180)

PROGRAMMERING-Java Omtentamina

Lösningar till tentamen i EIT070 Datorteknik

Quicksort. Koffman & Wolfgang kapitel 8, avsnitt 9

Classes och Interfaces, Objects och References Objekt-orienterad programmering och design (DIT952) Niklas Broberg, 2016

Tentamen i Algoritmer & Datastrukturer i Java

Tentamen i Grundläggande Programvaruutveckling, TDA548

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

Beijer Electronics AB 2000, MA00336A,

Outline. I Vi kan lätt göra samma sak för fyra variabler... I Hur gör vi för 400 inlästa värden? I Ofta behöver man flera likadana variabler

LULEÅ TEKNISKA UNIVERSITET

Tentamen FYTA11 Javaprogrammering

Tentamen, EDA690 Algoritmer och Datastrukturer, Helsingborg

Kurskod D0010E Datum Skrivtid 5tim

ADS : STACK ADT: STACK. Stack och Kö -Implementering - Tilllämpningar. Oftast förekommande metoder i Stack. TopOfStack

Deluppgift 17 Processhantering: exec, sleep, exit, plist

Labb LIVE. Exempelkod från föreläsningen. Plushögskolan Frågeutveckling inom MSSQL - SU14

OBS!! Detta är DEL 2 av tentan. För att få ut denna måste du ha lämnat in del 1. Om du inte fått ut del 1 bör du meddela skrivningsvakten. OBS!!

Föreläsning 3-4 Innehåll

TDDC30. Kursledning Kursledare: Jonas Lindgren. Labassistent: Jonas Lindgren Labassistent: Niklas Holma Labassistent: Erik Nilsson

Transkript:

Linköpings universitet 2012-05-21 Institutionen för datavetenskal (IDA) Processprogrammering och operativsystem (TDDI04) Synkronisera koden Instruktioner VIKTIGT PÅ TENTAN! För rätt och effektiv synkronisering är det viktigt att förstå hur koden fungerar och vad den är tänkt att göra. Det finns inga genvägar. Identifiera kritiska sektioner: 1. För varje kodrad eller kodstycke, vad har koden för syfte? 2. Vad vet du efteråt? Vad har kodstycket räknat ut? 3. Måste det du nu vet vara sant i efterföljande kod? Är efterföljande kod beroende av att vad kodstycket räknat ut eller hämtat från minnet fortfarande är likadant? 4. Kan något en annan tråd exekverar förändra vad kodstycket räknat ut, förändra det du vet? 5. Vad gör de andra trådarna? Vilken kod exekverar de? 6. Hur kan du skapa ett lås som är gemensamt för dessa trådar och denna kod? 7. När du låser, finns det operationer som använder låset trots att de egentligen inte behöver? För ökad parallellism behövs kanske flera lås, ett per individuell resurs istället för ett gemensamt för hela resurstypen. 8. Gör det någon skillnad om du låser, eller kvarstår problemet ändå? Kanske måste du låsa på en annan nivå (i anropande funktion). 9. Behövs låset bara över ett funktionsanrop? Går det låsa i funktionen istället? 10. Går det nyttja hårvaruinstruktionen atomic_swap eller test_and_set istället för ett lås? 11. Används flera lås eller semaforer? Kan deadlock eller starvation uppstå? 12. Kan koden skrivas om så synkroniseringen kan lösas på ett bättre, säkrare, effektivare eller enklare sätt? VIKTIGT PÅ TENTAN! Efter att tänkt igenom ovan 11 punkter bör du enkelt kunna besvara: 1. Vilken variabel eller datastruktur är det som behöver låset? 2. Vilka kodrader skall ingå i den kritiska sektionen så den blir minimal? 3. För var och en av kodraderna i kritiska sektionen, varför krävs mutual exclusion? 4. För var och en av kodraderna utanför kritiska sektionen, varför behövs inte låsning? 5. Är lösningen effektiv? Kan flera trådar arbeta parallellt utan att vänta på varandra (mer än absolut nödvändigt) hela tiden? Rekursiv låsning Ibland uppstår situationer där både funktion A och B behöver ta låset, men funktion B anropar funktion A medan den håller i låset. I detta läge behövs ett lås som fungerar rekursivt. Om tråden redan håller i låset skall den inte ta låset igen (det får man ju inte), men hålla reda på att det är låst med dubbla slag, så man även måste låsa upp två gånger innan det släpps. Hur kan man designa req_lock_acquire och req_lock_release för ett sådant lås? Vi förutsätter att vanliga lås med funktionerna lock_acquire, lock_release och is_locked_by_current_thread finns att tillgå. Läs- och skrivlås I fall när det är många trådar som läser men få som ändrar i delad data är naturligtvis lås som tillåter flera samtidiga läsartrådar så länge ingen tråd skriver att föredra. Hur designar man en sådan låsmekanism? Kan det innebära starvation för läsar- eller skrivartrådar? 1

MiniExempel Insättning av unikt ord i fält. Insättningen sker i tre steg. Kontrollera att ordet är giltigt, kontrollera att det inte redan är insatt, hitta en ledig plats, sätt in. Antag att fältet används av många trådar. 1: void insert( char* array[], int size, char* word ) 2: { Parametern array är en pekare till själva ordlistan i vilken alla trådar sätter in ord. Parametern size är en lokal variabel som inte ändras i funktionen. Parametern word är adressen till en sträng. adressen ändras inte då det är en lokal inparameter som inte ändras. Dock skulle innehållet i ordet kunna ändras. I detta fall förutsätter vi att inparameren word är något som inte påverkas av andra trådar. Om den ändras av andra trådar är det upp till anroparen att synkronisera detta. Det går inte lösa internt i insert då vi inte vet var eller hur insträngen eventuellt ändras. (Dock kan vi lösa det om kod är given så vi kan skapa ett lås för ordet som löser det eventuella problemet.) Vi förutsätter alltså i detta fall att inparametern är konstant under funktionens exekvering (synkroniserade externt). Inget annat är givet, ingen kod som ändrar ordet under insättningen är given eller kan förutsättas finnas. 3: if (! is_valid( word ) ) 4: return; Under ovan förutsättningar finns inget som kan ändra ordets giltighet. Om en annan tråd kör insert påverkar det inte hur ordet ser ut. Raderna är alltså inte kritiska och behöver inte synkroniseras. 5: if ( find(array, word) ) 6: return; Vi vet här att ordet inte finns i fältet. Ovan rad har tagit reda på det. Detta kan förändras genom att en annan tråd sätter in samma ord. Följande kod (insättningen) kräver att ordet inte finns för att det skall bli korrekt enlig specifikationen. Synkronisering behövs alltså. 7: for (int i = 0; i < size; ++i) 8: if ( is_empty(array, i) ) 9: break; Vi vet här att position i är ledig (ser du kodningsfelet?). Ovan iterering har letat upp en ledig plats. Detta kan förändras genom att en annan tråd hinner ockupera platsen. Följande kod (insättningen) kräver att platsen är ledig för att det skall bli korrekt. Synkronisera. Iterationsvariabeln i är en lokal variabel (varje anrop får en egen kopia) och inkrement av denna behöver inte synkroniseras (men råkar ändå hamna i kritiska sektionen). 10: store(array, word, i); 11: } Vi vet att ordet är korrekt insatt. Andra insättningar påverkar inte detta. 2

Flertrådad ordlista En ordlista med unika ord. Ett antal internetrobotar söker upp nya ord som läggs till om de inte redan finns. Några kontrolltrådar sorterar bort ord sådant som inte är riktiga ord. 1: /* represent the entier wordlist */ 2: struct set 3: { 4: char* word[size]; 5: }; 6: /* check if a word is added to the set */ 7: int find_word(struct set* s, char* word) 8: { 9: int i; 10: 11: for ( i = 0; i < SIZE; ++i) 12: { 13: if ( strcmp( s->word[i], word ) == 0 ) 14: return i; /* found match */ 15: } 16: return -1; 17: } 18: /* add a word if it does not already exist in the set */ 19: void add_word(struct set* s, char* word) 20: { 21: int i; 22: 23: if ( valid_word(word) ) 24: return; /* invalid characters in word */ 25: 26: if ( find_word(s, word)!= -1 ) 27: return; /* already added */ 28: 29: for ( i = 0; i < SIZE; ++i) 30: { 31: if ( s->word[i] == NULL ) 32: break; /* found free slot */ 33: } 34: 35: if ( i >= SIZE ) 36: return; /* no space left */ 37: 38: s->word[i] = word; 39: } 40: /* remove a word from the set */ 41: void remove_word(struct set* s, char* word) 42: { 43: int i = find_word(s, word); 44: 45: if ( i == -1 ) 46: return; /* already removed or never added */ 47: 48: s->word[i] = NULL; 49: } 3

Varulager Ett varulager har en databas för att hålla reda på hur mycket av varje produkt som finns på lager, och när det är dags att skicka ut nya beställningar. Alla funktioner används av många trådar. 1: struct varudata 2: { 3: char varunamn[16]; 4: double pris; 5: int antal_på_lager; 6: }; 7: struct varudata* lager[size]; 8: int add_new_item(char* namn, double pris, int antal) 9: { 10: for (int i = 0; i < SIZE; ++i) 11: { 12: if (lager[i] == NULL) 13: { 14: lager[i] = new varudata(slag, pris, antal); 15: return i; 16: } 17: } 18: return -1; 19: } 20: void remove_item(int id) 21: { 22: if (id < 0 or id >= SIZE) 23: throw invalid id ; 24: 25: delete lager[id]; 26: 27: lager[id] = NULL; 28: } 29: void increase_stock(int id, int antal) /* called on item arrival */ 30: { 31: if (id < 0 or id >= SIZE) 32: throw invalid id ; 33: 34: lager[id]->antal_på_lager += antal; 35: } 36: bool decrease_stock(int id, char*& namn, double& pris) 37: { 38: if (id >= 0 and id < SIZE) 39: { 40: namn = lager[id]->varunamn; 41: pris = lager[id]->pris; 42: 43: if ( --lager[id]->antal_på_lager < 10 ) 44: return true; /* order new items */ 45: } 46: return false; /* no need to order new items */ 47: } 4

Hashtabell i ADA Ett antal trådar använder tabellen. 90% av accesserna är läsningar (get). Varje index i tabellen består av en länkad lista. Data som hashas till samma position sätts helt enkelt in i listan. Listan är ospecificerad, men kan t.ex. vara en pekare till första elementet, som t.ex. avallokeras om remove gör listan tom. 1: -- to get the data identified by key from table 2: function get(table : in hash_table_type, 3: key : in key_type) returns stored_type is 4: 5: index : integer; -- 3 variable declarations 6: list : list_type; 7: value : stored_type; 8: 9: begin 10: 11: index := hash(key); 12: list := table(index); 13: value := find(list, key); 14: return value; 15: 16: end get; 17: -- to insert the data in the table 18: procedure set(table : in hash_table_type, 19: data : in stored_type) is 20: 21: index : integer; -- 3 variable declarations 22: list : list_type; 23: key : key_type; 24: 25: begin 26: 27: key := get_key(data); 28: index := hash(key); 29: list := table(index); 30: 31: if exists(list, key) then -- replace old data 32: remove(list, key); 33: end if; 34: 35: insert(list, data); 36: 37: end get; 5

Smaskens sa filosofen Fler än fem filosofer spenderar dagarna med att äta och tänka. Först reserverar de en stol och sedan de enda två gafflarna inom räckhåll. När de har båda gafflarna börjar de äta. Trots för få gafflar för att räcka till alla runt bordet så svälter de inte (?) ihjäl. 1: bool fork[5]; /* all initiated to false from start */ 2: bool seat[5]; /* all initiated to false from start */ 3: int free_seats = 5; 4: void philosopher() 5: { 6: int i, j; 7: 8: while ( true ) 9: { 10: random_sleep(); /* thinking a lot */ 11: 12: while (free_seats == 0) 13: ; /* Busy wait is BAD! */ 14: 15: for (i = 0; i < 5; ++i) 16: { 17: if (seat[i] == false) 18: { 19: seat[i] = true; 20: break; 21: } 22: } 23: free_seats--; 24: 25: /* wait for first fork */ 26: while ( fork[i] == false ) 27: ; /* Busy wait is BAD! */ 28: fork[i] = true; 29: 30: /* wait for second fork */ 31: j = (i+1)%5; 32: while ( fork[j] == false ) 33: ; /* Busy wait is BAD! */ 34: fork[j] = true; 35: 36: sleep(2); /* eating */ 37: 38: /* release both forks and seat */ 39: fork[i] = false; 40: fork[j] = false; 41: seat[i] = false; 42: free_seats++; 43: } 44: } TIPS: Tänk till om hur koden kan modifieras för att använda lås, semaforer, conditions eller hårdvaruinstruktioner av typen test_and_set eller atomic_swap. 6

Reservation av index i fält Ett antal trådar använder ett fält för att associera en pekare och heltal. Pekaren läggs på ett ledigt (?) index och det erhållna indexet returneras. 1: /* Each value in this global array of pointers is set to NULL in main */ 2: void* content[128]; 3: /* Add data to free slot in array. This is called from many threads. */ 4: int array_add(void* data) 5: { 6: for (int i = 0; i < 128; ++i) 7: { 8: /* if free, use it */ 9: if (content[i] == NULL) /* determine if index is free */ 10: { 11: content[i] = data; /* save data pointer in free index */ 12: break; 13: } 14: } 15: return i; /* return index used */ 16: } 17: /* Remove data from array. This is called from many threads. */ 18: void* array_remove(int id) 19: { 20: void* ret = content[id]; /* temporarily save the index s pointer */ 21: content[id] = NULL; /* mark the index as free */ 22: return ret; /* return the pointer that was removed */ 23: } TIPS: Skall ett globalt lås för hela arrayen användas, eller går det att använda ett lås för varje individuellt index i tabellen? Finns det i så fall fördelar? Nackdelar? Går det nyttja någon form av hårdvarulösning av typen atomic_swap eller test_and_set? 7

Summering av fält Ett antal trådar skall hjälpas åt att summera ett fält. De delar upp fältet i lika delar och summerar var sin del. Huvudprogrammet skriver ut summan när allt (?) är klart. 1: /* sum: A pointer to the variable containing the final sum. 2: start: A pointer to the first value in an array to sum. 3: stop: A pointer which the summation should stop just before. 4: */ 5: void sum_array(int* sum, int* start, int* stop) 6: { 7: while (start < stop) 8: { 9: *sum = *sum + *start; 10: ++start; 11: } 12: } 13: /* Some code in the main function is omitted for brewity. */ 14: int main() 15: { 16: int sum = 0; 17: int array[512]; 18: 19: load_interesting_data_to_array(array, 512); 20: 21: /* Start four threads to sum different parts of the array. 22: * 23: * thread_create schedules (places in ready queue) a new thread 24: * to execute the sum_array function. As this shecdule is just a 25: * list insert it will return quickly, probably (but not always) 26: * before the new thread even staret execution. 27: */ 28: for (int i = 0; i < 4; ++i) 29: thread_create(sum_array, &sum, array + 128*i, array + 128*(i+1)); 30: 31: printf("the sum is: %d\n", sum); 32: } 8

Starta jobb i ny tråd Ett virusprogram startar kontroll av filer inuti ett filarkiv som en egen tråd. Om filarkivet visar sig korrupt kontolleras det istället (?) som en vanlig fil. 1: /* Open the file as a zip file and scan each file inside for viruses. 2: * Set the output parameter bad to true if the zip is invalid. */ 3: void unpack_and_scan(const char* filename, bool* bad) 4: { 5: zip = open_zip(filename); 6: 7: if (open_failed(zip)) 8: { 9: *bad = true; /* message back to main function */ 10: return; /* exit thread */ 11: } 12: 13: /* Iterate each file contained in the zip and scan it. */ 14: for (file = zip_first(zip); file!= NULL; file = zip_next(zip)) 15: { 16: scan_regular_file(file); 17: } 18: } 19: /* Scan all files given as argument to main. */ 20: int main(int argc, char* argv[]) 21: { 22: int i; 23: for (i = 0; i < argc; ++argc) 24: { 25: switch ( file_extension(argv[i]) ) 26: { 27: case ZIP: 28: { 29: bool bad_file = false; 30: 31: /* thread_create schedules a new thread to execute 32: * unpack_and_scan. As schedule is just a list insert it 33: * will return quickly, probably before the new thread even 34: * stared execution. */ 35: thread_create(unpack_and_scan, argv[i], &bad_file); 36: 37: if ( bad_file ) /* receive message */ 38: { 39: /* bad zip, scan as regular file instead */ 40: scan_regular_file(argv[i]); 41: } 42: break; 43: } 44: 45: /* remaining cases omitted here */ 46: 47: } /* end switch */ 48: } /* end for */ 49: 50: return 0; 51: } 9

En stack är bra att ha Stacken används i ett system där flera trådar lägger till och hämtar ut värden. Trådar som hämtar ut värden väntar (?) tills det finns något att hämta. 1: /* This structure represents one item on the stack. */ 2: struct stack_node 3: { 4: struct stack_node* next; 5: int data; 6: } 7: /* This structure represents the entire stack. */ 8: struct stack 9: { 10: struct stack_node* top; 11: } 12: /* Initiate the stack to become empty. 13: * Called once before any threads are started. */ 14: void stack_init(struct stack* s) 15: { 16: s->top = NULL; 17: } 18: /* Pop one item from the stack. The stack is specified as 19: * parameter. Many threads use this function simultaneously. */ 20: int stack_pop(struct stack* s) 21: { 22: struct stack_node* popped = s->top; /* Get the top element */ 23: 24: while (popped == NULL) /* Was it anything there? */ 25: popped = s->top; 26: 27: int data = popped->data; /* Save the data we want */ 28: s->top = popped->next; /* Remove the top element */ 29: free(popped); /* Free removed element memory */ 30: return data; /* Return the saved data */ 31: } 32: /* Push one item to the stack. The stack and the integer data to push 33: * are specified as parameters. Many threads use this function. */ 34: void stack_push(struct stack* s, int x) 35: { 36: struct stack_node* new_node = malloc(sizeof(struct stack_node)); 37: new_node->next = s->top; 38: new_node->data = x; 39: s->top = new_node; 40: } 10

Kommunikationskö med begränsad storlek Ett fält nyttjas som kommunikationskö mellan flera trådar som både läser och skriver till kön. Är kön full eller tom väntar (?) trådarna tills den inte är det längre. 1: #define SIZE 256 2: /* With this size and 8-bit read- and write positions the position 3: * counters will automatically go from 255 around to 0. 4: * Else we must add code to wrap around (position % SIZE).*/ 5: /* This structure represent a bounded buffer (queue) */ 6: struct bounded 7: { 8: int buffer[size]; 9: int used_size = 0; /* Initiation like this is not possible in 10: int8 read_pos = 0; * real C-code. You must use an init function. 11: int8 write_pos = 0; */ 12: }; 13: /* Read the oldest value in the queue. */ 14: int bounded_read(struct bounded* b) 15: { 16: /* We must wait until the queue have at least one value. */ 17: while (b->used_size == 0) 18: ; /* Busy wait is BAD! */ 19: 20: /* Now we have(?) a value to read (remove). */ 21: --b->used_size; 22: 23: /* Read the value from the read position. */ 24: return b->buffer[b->read_pos++]; 25: } 26: /* Write a new value to the next free position in the queue. */ 27: void bounded_write(struct bounded* b, int x) 28: { 29: /* We must wait until at least one slot is available. */ 30: while (b->used_size == SIZE) 31: ; /* Busy wait is BAD! */ 32: 33: /* Now we have(?) an empty position to use. */ 34: b->buffer[b->write++] = x; 35: ++b->used_size; 36: } 11

Platsreservation En biosalong erbjuder automatisk platsbokning via internet. Varje bokningstråd använder denna funktion för att reservera ett antal platser bredvid varandra på given rad. 1: /* all seats starts empty, indicated by false */ 2: bool seats[rows][columns]; 3: /* Reserve n consecutive seats on row */ 4: bool reserve_seat(int n, int row) 5: { 6: int max_start = 0; 7: int max_count = 0; 8: int c = 0; 9: while (c < COLUMNS) 10: { 11: int start; 12: int end; 13: 14: while (c < COLUMNS && seats[row][c] == true) 15: ++c; 16: start = c; /* first free seat in row */ 17: 18: while (c < COLUMNS && seats[row][c] == false) 19: ++c; 20: end = c; /* column of the next occupies seat */ 21: 22: /* Is it the longest sequence of free seats in row? */ 23: if (max_count < (end - start)) 24: { 25: max_start = start; 26: max_count = end - start; 27: } 28: } 29: 30: /* Was the longest free sequence long enough? */ 31: if (max_count < n) 32: { 33: return false; 34: } 35: 36: /* allocate the seats */ 37: for (c = max_start; c < (max_start + n); ++c) 38: { 39: seats[row][c] = true; 40: } 41: 42: return true; 43: } 12

Förflyttning på spelplan Ett datorspel har en spelplan med ett antal olika objekt. Ett antal spelartrådar flyttar runt objekten på spelplanen genom att anropa flyttningsfunktionen på objektet i en ruta. 1: // struct to represent one square on the board and what s in it 2: struct square 3: { 4: // if the square is occupied with something or not 5: int occupied; 6: // whatever that something is (wall, player, food...) 7: object* content; 8: }; 9: // the playground, shared by all threads 10: struct square board[ X ][ Y ]; 11: class object 12: { 13: public: 14: // move the object one step if possible 15: virtual bool move(int x_off, int y_off) 16: { 17: if ( outside_board(x+x_off, y+y_off) ) 18: { 19: return false; // move failed 20: } 21: 22: if ( board[ x+x_off ][ y+y_off ].occupied ) 23: { 24: return false; // move failed 25: } 26: 27: // destination square is free, go there 28: board[ x+x_off ][ y+y_off ].occupied = true; 29: board[ x+x_off ][ y+y_off ].content = this; 30: 31: // leave the previous square 32: board[ x ][ y ].occupied = false; 33: board[ x ][ y ].content = NULL; 34: 35: // update where the object is on the board 36: x += x_off; 37: y += y_off; 38: 39: return true; // move succeded 40: } 41: 42: private: 43: int x, y; 44: }; 13

Överföring mellan konton En funktion för att överföra en summa pengar mellan två konton i en bank används av ett antal trådar. Kunder kan t.ex. ansluta via internet för att föra över pengar. Varje anslutning hanteras av en tråd. 1: /* representation of one account */ 2: struct bank_account 3: { 4: int balance; 5: char owner[]; 6: }; 7: /* one big array with all accounts */ 8: struct bank_account account[ CUSTOMER_COUNT ]; 9: void transfer(int from, int to, int amount) 10: { 11: if (account[from].balance < amount) 12: return; 13: 14: account[from].balance -= amount; 15: account[ to ].balance += amount; 16: } 14

Linköpings universitet 2012-05-21 Institutionen för datavetenskal (IDA) Processprogrammering och operativsystem (TDDI04) Filtabell Funktioner som hanterar en enkel filtabell. Filpekare läggs till och tillbaka får man fildeskriptorer. Tabellen används gemensamt av många trådar. 1: /* representation av tabellen */ 2: struct file* table[size]; 3: /* add a file to table */ 4: int add_file(struct file* f) 5: { 6: int index = 0; 7: 8: while (index < SIZE && table[index]!= NULL) 9: ++index; 10: 11: if (index == SIZE) 12: return -1; 13: 14: table[index] = f; 15: return index; 16: } 17: /* clear one index */ 18: struct file* clear_index(int i) 19: { 20: if (i < 0 i >= SIZE) 21: return NULL; 22: 23: struct file* r = table[i]; 24: table[i] = NULL; 25: 26: return r; 27: } 28: /* check if index is valid */ 29: bool index_valid(int i) 30: { 31: return (i >= 0 && i < SIZE) && (table[i]!= NULL); 32: } 15