Σημαφόροι

89
Προγραμματισμός ΙΙΙ 1 [email protected] Σημαφόροι (Σηματοφόροι / Σηματοφορείς)

Transcript of Σημαφόροι

Προγραμματισμός ΙΙΙ 1 [email protected]

Σημαφόροι(Σηματοφόροι / Σηματοφορείς)

Προγραμματισμός ΙΙΙ 2 [email protected]

• Ο σημαφόρος είναι ένας ΑΤΔ με πράξεις init, down(wait, P) και up (signal, V).

• Η init(s,v) αρχικοποιεί τον σημαφόρο s με την ακέραια τιμή v που πρέπει να είναι >=0.

• Η down(s) μειώνει την τιμή του σημαφόρου s κατά ένα –αν η τιμή του s είναι =0, τότε το καλών νήμα περιμένει μέχρι η τιμή του s να γίνει >0.

• Η up(s) αυξάνει την τιμή του σημαφόρου s κατά ένα –ξεμπλοκάροντας ίσως ένα νήμα που επιχειρεί να μειώσει την τιμή του s μέσω της down.

• Οι πράξεις down και up υλοποιούνται έτσι ώστε να μπορεί να κληθούν ταυτόχρονα χωρίς πρόβλημα.

Σημαφόροι (semaphores)

Προγραμματισμός ΙΙΙ 3 [email protected]

• Αν ένα ή περισσότερα νήματα έχουν μπλοκαριστεί στην down και ένα νέο νήμα εκτελέσει την downτότε μπλοκάρει και αυτό.

• ‘Οταν υπάρχουν πολλά νήματα μπλοκαρισμένα στην down και εκτελεσθεί η up αφυπνίζεται ένα από αυτά– random: η αφύπνιση γίνεται με τυχαία σειρά– fair: η αφύπνιση γίνεται έτσι ώστε κανένα νήμα να μην παραμείνει μπλοκαρισμένο απ’ άπειρο

– fifo: η αφύπνιση γίνεται με σειρά FIFO, δηλαδή με την σειρά που τα νήματα κάλεσαν την down

Σημαφόροι και «δικαιοσύνη»

Προγραμματισμός ΙΙΙ 4 [email protected]

• Δυαδικός σημαφόρος (binary semaphore) – μπορεί να λάβει τιμές 0 ή 1.

• Γενικός σημαφόρος ή σημαφόρος μετρητής (general / counting semaphore) – μπορεί να λάβει τιμές >= 0.

• Οι δυαδικοί σημαφόροι (μπορεί να) έχουν απλούστερη υλοποίηση καθώς χρειάζεται μόνο ένα bitγια να κρατά τις τιμές τους.

• Ένας γενικός σημαφόρος μπορεί να υλοποιηθεί με βάση δυαδικούς σημαφόρους.

Τύποι σημαφόρων

Προγραμματισμός ΙΙΙ 5 [email protected]

Κρίσιμο τμήμα με σημαφόρους

Pi:while (1) {

… down(s); /* entry code */do_critical_section();up(s); /* exit code */…

}

sem s;init(s,1);

Προγραμματισμός ΙΙΙ 6 [email protected]

{?} s ?

Σχόλιοπριν αρχίσει η εκτέλεση

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

τιμήουρά αναμονής

Προγραμματισμός ΙΙΙ 7 [email protected]

s 1

Σχόλιοαρχικοποίηση σημαφόρου με την τιμή 1

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

{}

Προγραμματισμός ΙΙΙ 8 [email protected]

Σχόλιοαρχή εκτέλεσης P0

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 1 {}

Προγραμματισμός ΙΙΙ 9 [email protected]

Σχόλιοαρχή εκτέλεσης P1

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 1 {}

Προγραμματισμός ΙΙΙ 10 [email protected]

Σχόλιοπροσπάθεια P0 να εισέλθει στο ΚΤ, σημαφόρος μειώνεται κατά 1

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {}

Προγραμματισμός ΙΙΙ 11 [email protected]

ΣχόλιοP0 μπαίνει στο ΚΤ

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {}

Προγραμματισμός ΙΙΙ 12 [email protected]

Σχόλιοπροσπάθεια P1 να εισέλθει στο ΚΤ, σημαφόρος έχει τιμή 0 επομένως P1 μπλοκάρεται

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {P1}

Προγραμματισμός ΙΙΙ 13 [email protected]

Σχόλιοαρχή εκτέλεσης P2

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {P1}

Προγραμματισμός ΙΙΙ 14 [email protected]

Σχόλιοπροσπάθεια P2 να εισέλθει στο ΚΤ, σημαφόρος έχει τιμή 0 επομένως P2 μπλοκάρεται

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {P1,P2}

Προγραμματισμός ΙΙΙ 15 [email protected]

Σχόλιοέξοδος P0 από το ΚΤ, οπότε αφυπνίζεται το P1 (το οποίο μπλόκαρε πριν το P2)

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {P2}

Προγραμματισμός ΙΙΙ 16 [email protected]

Σχόλιοτο P1 μπαίνει στο ΚΤ

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {P2}

Προγραμματισμός ΙΙΙ 17 [email protected]

ΣχόλιοP0 εκτελεί κώδικα εκτός ΚΤ, P1 παραμένει στο ΚΤ

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {P2}

Προγραμματισμός ΙΙΙ 18 [email protected]

ΣχόλιοP0 εκτελεί κώδικα εκτός ΚΤ, έξοδος P1 από το ΚΤ, οπότε αφυπνίζεται το P2

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {}

Προγραμματισμός ΙΙΙ 19 [email protected]

Σχόλιοτο P2 και μπαίνει στο ΚΤ

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {}

Προγραμματισμός ΙΙΙ 20 [email protected]

ΣχόλιοP0+P1 εκτελούν κώδικα εκτός ΚΤ, P2 είναι μέσα στο ΚΤ

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {}

Προγραμματισμός ΙΙΙ 21 [email protected]

ΣχόλιοP1 επιχειρεί να μπεί στο ΚΤ, και μπλοκάρεται

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {P1}

Προγραμματισμός ΙΙΙ 22 [email protected]

ΣχόλιοP0 επιχειρεί να μπεί στο ΚΤ, και μπλοκάρεται

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {P1,P0}

Προγραμματισμός ΙΙΙ 23 [email protected]

Σχόλιοέξοδος P2 από το ΚΤ, οπότε αφυπνίζεται το P1

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {P0}

Προγραμματισμός ΙΙΙ 24 [email protected]

Σχόλιοτο P1 και εισέρχεται στο ΚΤ

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {P0}

Προγραμματισμός ΙΙΙ 25 [email protected]

ΣχόλιοP2 συνεχίζει την εκτέλεση του

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {P0}

Προγραμματισμός ΙΙΙ 26 [email protected]

Σχόλιοέξοδος P1 από το ΚΤ, οπότε αφυπνίζεται το P0

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {}

Προγραμματισμός ΙΙΙ 27 [email protected]

Σχόλιοτο P0 και εισέρχεται στο ΚΤ

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {}

Προγραμματισμός ΙΙΙ 28 [email protected]

ΣχόλιοP1 συνεχίζει την εκτέλεση του

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 0 {}

Προγραμματισμός ΙΙΙ 29 [email protected]

Σχόλιοέξοδος P0 από το ΚΤ, και αφού κανένα νήμα δεν περιμένει στον σημαφόρο, αυξάνεται η τιμή του κατά 1

P0:while (1) {

down(s); do_CS();up(s);…

}

sem s;init(s,1);

P1:while (1) {

down(s); do_CS();up(s);…

}

Κατάσταση σημαφόρου

P2:while (1) {

down(s); do_CS();up(s);…

}

s 1 {}

Προγραμματισμός ΙΙΙ 30 [email protected]

• Ένας δυαδικός σημαφόρος παίρνει τιμές 0,1.• Αν δεν υπάρχουν νήματα μπλοκαρισμένα στην down, και η τιμή του σημαφόρου είναι ήδη 1, τυχόν κλήσεις της up δεν έχουν κανένα αποτέλεσμα, και η τιμή του σημαφόρου παραμένει 1.

• Αν θέλουμε να μην «χάνονται» οι κλήσεις της upόταν δεν υπάρχουν μπλοκαρισμένα νήματα στην down, χρησιμοποιούμε γενικό σημαφόρο.

Προσοχή!

Προγραμματισμός ΙΙΙ 31 [email protected]

• Δίνονται 3 νήματα P0, P1 και P2.• Έστω ότι πρέπει να υλοποιηθεί ένα «σημείο» συγχρονισμού ανάμεσα στα νήματα ως εξής:

• Αν το P0 φτάσει στο σημείο Α του κώδικα του πριν το P1 φτάσει στο σημείο Β του κώδικα του ή/και πριν το P2 φτάσει στο σημείο Γ του κώδικα του, τότε το P0 μπορεί να συνεχίσει την εκτέλεση του.

• Αν το P1 φτάσει στο σημείο Β του κώδικα του πριν το P0 φτάσει στο σημείο Α του κώδικα του, τότε το P1 πρέπει να περιμένει.

• Αν το P2 φτάσει στο σημείο Γ του κώδικα του πριν το P0 φτάσει στο σημείο Α του κώδικα του, τότε το P2 πρέπει να περιμένει.

Παράδειγμα

Προγραμματισμός ΙΙΙ 32 [email protected]

Σχόλιοαρχικοποίηση σημαφόρου με την τιμή 0

P0:…up(s);up(s);…

sem s;init(s,0);

P1:… down(s);…

Κατάσταση σημαφόρου

P2:…down(s);…

s 0 {}

Προγραμματισμός ΙΙΙ 33 [email protected]

ΣχόλιοP0 εκτελεί up και αυξάνει την τιμή κατά 1

P0:…up(s);up(s);…

sem s;init(s,0);

P1:… down(s);…

Κατάσταση σημαφόρου

P2:…down(s);…

s 1 {}

Προγραμματισμός ΙΙΙ 34 [email protected]

ΣχόλιοP0 εκτελεί up (ξανά!) αλλά η τιμή παραμένει 1

P0:…up(s);up(s);…

sem s;init(s,0);

P1:… down(s);…

Κατάσταση σημαφόρου

P2:…down(s); …

s 1 {}

Προγραμματισμός ΙΙΙ 35 [email protected]

ΣχόλιοP0 συνεχίζει την εκτέλεση του

P0:…up(s);up(s);…

sem s;init(s,0);

P1:… down(s);…

Κατάσταση σημαφόρου

P2:…down(s); …

s 1 {}

Προγραμματισμός ΙΙΙ 36 [email protected]

ΣχόλιοP1 εκτελεί down και μειώνει την τιμή κατά 1

P0:…up(s);up(s);…

sem s;init(s,0);

P1:… down(s);…

Κατάσταση σημαφόρου

P2:…down(s);…

s 0 {}

Προγραμματισμός ΙΙΙ 37 [email protected]

ΣχόλιοP1 συνεχίζει την εκτέλεση του

P0:…up(s);up(s);…

sem s;init(s,0);

P1:… down(s);…

Κατάσταση σημαφόρου

P2:…down(s);…

s 0 {}

Προγραμματισμός ΙΙΙ 38 [email protected]

ΣχόλιοP2 εκτελεί down και μπλοκάρεται … επ’ αόριστο!

P0:…up(s);up(s);…

sem s;init(s,0);

P1:… down(s); …

Κατάσταση σημαφόρου

P2:…down(s); …

s 0 {P2}

Προγραμματισμός ΙΙΙ 39 [email protected]

• Η προηγούμενη εκτέλεση αντιστοιχεί σε ένα από τα διάφορα πιθανά σενάρια ταυτόχρονης εκτέλεσης.

• Υπάρχουν άλλα σενάρια όπου– το P2 δεν μπλοκάρει, αλλά μπλοκάρει το P1– δεν μπλοκάρει ούτε το P1 ούτε το P2

• Το αποτέλεσμα εξαρτάται από την εναλλαγή των διαφόρων νημάτων.

• Καθώς δεν μπορούμε να ελέγξουμε την εναλλαγή, το παραπάνω πρόγραμμα έχει μη ντετερμινιστικήσυμπεριφορά.

• Η λύση είναι να χρησιμοποιήσουμε γενικό σημαφόρο.

Σχόλιο

Προγραμματισμός ΙΙΙ 40 [email protected]

Σχόλιοαρχικοποίηση σημαφόρου με την τιμή 0

P0:…up(s);up(s);…

sem s;init(s,0);

P1:… down(s);…

Κατάσταση σημαφόρου

P2:…down(s);…

s 0 {}

Προγραμματισμός ΙΙΙ 41 [email protected]

ΣχόλιοP0 εκτελεί up και αυξάνει την τιμή κατά 1

P0:… up(s);up(s);…

sem s;init(s,0);

P1:…down(s);…

Κατάσταση σημαφόρου

P2:…down(s);…

s 1 {}

Προγραμματισμός ΙΙΙ 42 [email protected]

ΣχόλιοP0 εκτελεί up (ξανά!) και αυξάνει την τιμή κατά 1

P0:…up(s);up(s);…

sem s;init(s,0);

P1:… down(s);…

Κατάσταση σημαφόρου

P2:…down(s);…

s 2 {}

Προγραμματισμός ΙΙΙ 43 [email protected]

ΣχόλιοP0 συνεχίζει την εκτέλεση του

P0:…up(s);up(s);…

sem s;init(s,0);

P1:… down(s);…

Κατάσταση σημαφόρου

P2:…down(s);…

s 2 {}

Προγραμματισμός ΙΙΙ 44 [email protected]

ΣχόλιοP1 εκτελεί down και μειώνει την τιμή κατά 1

P0:…up(s);up(s);…

sem s;init(s,0);

P1:… down(s);…

Κατάσταση σημαφόρου

P2:…down(s);…

s 1 {}

Προγραμματισμός ΙΙΙ 45 [email protected]

ΣχόλιοP1 συνεχίζει την εκτέλεση του

P0:…up(s);up(s);…

sem s;init(s,0);

P1:… down(s);…

Κατάσταση σημαφόρου

P2:…down(s);…

s 1 {}

Προγραμματισμός ΙΙΙ 46 [email protected]

ΣχόλιοP2 εκτελεί down και μειώνει την τιμή κατά 1

P0:…up(s);up(s); …

sem s;init(s,0);

P1:… down(s); …

Κατάσταση σημαφόρου

P2:…down(s); …

s 0 {}

Προγραμματισμός ΙΙΙ 47 [email protected]

Σχόλιοόλα τα νήματα συνεχίζουν την εκτέλεση τους

P0:…up(s);up(s);…

sem s;init(s,0);

P1:… down(s);…

Κατάσταση σημαφόρου

P2:… down(s);…

s 0 {}

Προγραμματισμός ΙΙΙ 48 [email protected]

Υλοποίηση Σημαφόρων

Προγραμματισμός ΙΙΙ 49 [email protected]

• Ένας σημαφόρος είναι ένας ακέραιος μαζί με μια ουρά αναμονής όπου τοποθετείται ένα νήμα όταν επιχειρήσει να μειώσει την τιμή του ακεραίου και η τιμή του είναι ήδη 0.

• Οι λειτουργίες down/up εκτελούν «ατομικές» πράξεις στον ακέραιο και την ουρά.

• Οι πράξεις down/up μπορεί να υλοποιηθούν με ενεργή αναμονή.

• Οι πράξεις down/up μπορεί να υλοποιηθούν με βάση τις πράξεις suspend/resume.

Υλοποίηση δυαδικών / γενικών σημαφόρων

Προγραμματισμός ΙΙΙ 50 [email protected]

typedef struct bs {int locked; /* αμοιβαίος αποκλεισμός */int val; /* τιμή σημαφόρου */

} bsem;

void init(bsem *s, int val) {s->locked=0; s->val=val;

}

void down(bsem *s) {int done=0;do {

while (TAS(&s->locked));if (s->val>0) {s->val=0; done=1;}s->locked=0;

} while (!done);}

void up(bsem *s) {s->val=1;

}

Προγραμματισμός ΙΙΙ 51 [email protected]

typedef struct bs {int val; /* τιμή σημαφόρου */

} bsem;

void init(bsem *s, int val) {s->val=val;

}

void down(bsem *s) {beg_atomic();while (s->val == 0) {yield();}s->val=0;end_atomic();

}

void up(bsem *s) {s->val=1;

}

Προγραμματισμός ΙΙΙ 52 [email protected]

typedef struct bs {Queue q;int v;

} bsem;

void init(bsem *s, int v) {queue_init(&s->q);s->v=v;

}

void down(bsem *s) {beg_atomic();if (s->v==0) {suspend(&s->q);}else {s->v=0;}end_atomic();

}

void up(bsem *s) {beg_atomic();if (!queue_empty(&s->q) {resume(&s->q);}else {s->v=1;}end_atomic();

}

Προγραμματισμός ΙΙΙ 53 [email protected]

typedef struct gs {Queue q;int v;

} gsem;

void init(gsem *s, int v) {queue_init(&s->q);s->v=v;

}

void down(gsem *s) {beg_atomic();if (s->v==0) {suspend(&s->q);}else {s->v--;}end_atomic();

}

void up(gsem *s) {beg_atomic();if (!queue_empty(&s->q) {resume(&s->q);}else {s->v++;}end_atomic();

}

Προγραμματισμός ΙΙΙ 54 [email protected]

• Η υλοποίηση των δυαδικών ή γενικών σημαφόρων γίνεται συνήθως από το ίδιο το λειτουργικό σύστημα.

• Εκεί υλοποιείται και ο μηχανισμός εναλλαγής νημάτων, οπότε υπάρχει ακριβής έλεγχος του.

• Μπορούν να γίνουν επιπλέον βελτιστοποιήσεις, π.χ. κατάλληλη δομή διεργασίας έτσι ώστε η προσθήκη σε και απομάκρυνση από μια ουρά αναμονής να μπορούν να υλοποιηθούν αποδοτικά.

• Σπάνια ένα (λειτουργικό) σύστημα δίνει την δυνατότητα στον προγραμματιστή (εφαρμογών) να απενεργοποιήσει την εναλλαγή.

Σχόλιο

Προγραμματισμός ΙΙΙ 55 [email protected]

• Μπορούμε να υλοποιήσουμε γενικούς σημαφόρους χρησιμοποιώντας δυαδικούς σημαφόρους.

• Χρησιμοποιούμε (α) ένα δυαδικό σημαφόρο mtx για αμοιβαίο αποκλεισμό για την πρόσβαση στα δεδομένα του σημαφόρου, και (β) ένα δυαδικό σημαφόρο qπου χρησιμοποιούμε σαν ουρά αναμονής.

• Η αναμονή στην ουρά (σημαφόρο q) γίνεται στην down όταν η τιμή του σημαφόρου είναι 0.

• Πριν το καλών νήμα μπλοκάρει στον σημαφόρο q, πρέπει να αυξήσει τον σημαφόρο mtx έτσι ώστε ένα άλλο νήμα να μπορέσει (κάποια στιγμή) να εκτελέσει τον κώδικα της up, και να το αφυπνίσει.

Γενικοί σημαφόροι με δυαδικούς

Προγραμματισμός ΙΙΙ 56 [email protected]

typedef struct gs {int val,qlen; /* μετρητής, μέγεθος ουράς */bsem mtx,q; /* προστασία πρόσβασης, ουρά */

} gsem;

void init(gsem *s, int val) {s->val=val; s->qlen=0;binit(&s->mtx,1); binit(&s->q,0);

}

void down(sem *s) {bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

}

void up(sem *s) {bdown(&s->mtx);if (s->qlen == 0) {s->val++;} else {s->qlen--; bup(&s->q);}bup(&s->mtx);

}

Προγραμματισμός ΙΙΙ 57 [email protected]

• Υπάρχει περίπτωση προσπεράσματος με ταυτόχρονη εκτέλεση της down.

• Aφού το νήμα P0 αυξήσει τον σημαφόρο s->mxt(δηλαδή ελευθερώσει την είσοδο στην down) και πριν προλάβει να μειώσει τον σημαφόρο s->q(δηλαδή να τοποθετηθεί στην ουρά), μπορεί να προσπεραστεί από ένα άλλο νήμα P1.

• Παρ’ όλα αυτά, ο επ’ άπειρο παραγκωνισμός του νήματος P0 είναι απίθανος --γιατί;

Πρόβλημα A

Προγραμματισμός ΙΙΙ 58 [email protected]

typedef struct gs {int val,qlen; /* μετρητής, μέγεθος ουράς */bsem mtx,q; /* προστασία πρόσβασης, ουρά */

} gsem;

void init(sem *s, int val) {s->val=val; s->qlen=0;binit(&s->mtx,1); binit(&s->q,0);

}

void down(sem *s) {bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

}

void up(sem *s) {bdown(&s->mtx);if (s->qlen == 0) {s->val++;} else {s->qlen--; bup(&s->q);}bup(&s->mtx);

}

Προγραμματισμός ΙΙΙ 59 [email protected]

• Επιπλέον υπάρχει περίπτωση ασυνέπειας με ταυτόχρονη εκτέλεση των down και up.

• Δύο (ή περισσότερα) νήματα μπορεί να φτάσουν και να διακοπεί η εκτέλεση τους στο σημείο της προσπέρασης, και στη συνέχει να εκτελεσθεί δύο (ή περισσότερες) φορές η up.

• Το αποτέλεσμα είναι ότι θα «χαθεί» μια κλήση (ή περισσότερες κλήσεις) up στον σημαφόρο s->q(αφύπνιση από την ουρά) και ένα ή περισσότερα νήματα θα μείνουν μπλοκαρισμένα στην down.

• Είναι μια περίπτωση συνθήκης ανταγωνισμού.

Πρόβλημα B

Προγραμματισμός ΙΙΙ 60 [email protected]

Παράδειγμα

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

sem s;init(s,0);

Κατάσταση σημαφόρου

{?} s->mtx ?

{?} s->q ?

s->val = ?, s->qlen = ?

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 61 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 1

{} s->q 0

s->val = 0, s->qlen = 0

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 62 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 1

{} s->q 0

s->val = 0, s->qlen = 0

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 63 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 0

{} s->q 0

s->val = 0, s->qlen = 0

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 64 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 0

{} s->q 0

s->val = 0, s->qlen = 0

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 65 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 0

{} s->q 0

s->val = 0, s->qlen = 1

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 66 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 1

{} s->q 0

s->val = 0, s->qlen = 1

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 67 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 1

{} s->q 0

s->val = 0, s->qlen = 1

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 68 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 0

{} s->q 0

s->val = 0, s->qlen = 1

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 69 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 0

{} s->q 0

s->val = 0, s->qlen = 1

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 70 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 0

{} s->q 0

s->val = 0, s->qlen = 2

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 71 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 1

{} s->q 0

s->val = 0, s->qlen = 2

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 72 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 1

{} s->q 0

s->val = 0, s->qlen = 2

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 73 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 0

{} s->q 0

s->val = 0, s->qlen = 2

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 74 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 0

{} s->q 0

s->val = 0, s->qlen = 2

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 75 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 0

{} s->q 0

s->val = 0, s->qlen = 1

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 76 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 0

{} s->q 1

s->val = 0, s->qlen = 1

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 77 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 1

{} s->q 1

s->val = 0, s->qlen = 1

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 78 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 1

{} s->q 1

s->val = 0, s->qlen = 1

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 79 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 0

{} s->q 1

s->val = 0, s->qlen = 1

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 80 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 0

{} s->q 1

s->val = 0, s->qlen = 1

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 81 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 0

{} s->q 1

s->val = 0, s->qlen = 0

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 82 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 0

{} s->q 1

s->val = 0, s->qlen = 0

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

«χάνεται»!

Προγραμματισμός ΙΙΙ 83 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 1

{} s->q 1

s->val = 0, s->qlen = 0

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 84 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 1

{} s->q 0

s->val = 0, s->qlen = 0

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 85 [email protected]

Παράδειγμα

sem s;init(s,0);

Κατάσταση σημαφόρου

{} s->mtx 1

{P0} s->q 0

s->val = 0, s->qlen = 0

P0: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P1: down(s)

bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);} else {s->qlen++; bup(&s->mtx); bdown(&s->q);}

P2: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

P3: up(s)

bdown(&s->mtx); if (s->qlen == 0) {s->val=1;} else {s->qlen--; bup(&s->q);} bup(&s->mtx);

Προγραμματισμός ΙΙΙ 86 [email protected]

• Το πρόβλημα είναι ότι αίρεται ο αμοιβαίος αποκλεισμός στην down πριν ένα νήμα προλάβει να μπλοκάρει στην ουρά αναμονής q.

• Αυτό πρέπει αναγκαστικά να γίνει έτσι ώστε να επιτρέψουμε σε κάποιο άλλο νήμα να εκτελέσει κάποια στιγμή την up και να αφυπνίσει τα νήματα που περιμένουν στην q.

• Έτσι όμως επιτρέπουμε και σε άλλα νήματα να εκτελέσουν την down «μερικώς», και να αυξήσουν την τιμή qlen χωρίς να υπάρχει ούτε ένα νήμα που περιμένει στον σημαφόρο q.

Το πρόβλημα

Προγραμματισμός ΙΙΙ 87 [email protected]

• Πρέπει να απαγορέψουμε σε παραπάνω από ένα νήματα να αυξήσουν την τιμή της qlen.

• Χρειαζόμαστε ένα ακόμα δυαδικό σημαφόρο q2, που χρησιμοποιούμε για αμοιβαίο αποκλεισμό μεταξύ των νημάτων που καλούν την down.

• Ουσιαστικά, η ουρά αναμονής που υλοποιούσαμε μέσω του σημαφόρου q σπάει στα δύο, με το πρώτο νήμα να μπλοκάρει στον q και όλα τα υπόλοιπα νήματα που καλούν down «ταυτόχρονα» να μπλοκάρουν στον σημαφόρο q2.

Λύση

Προγραμματισμός ΙΙΙ 88 [email protected]

typedef struct gs {int val,qlen; bsem mtx,q,q2; /* …, σειριοποίηση στην down */

} gsem;

void init(sem *s, int val) {s->val=val; s->qlen=0;binit(&s->mtx,1); binit(&s->q,0); binit(&s->q2,1);

}

void down(sem *s) {bdown(&s->q2);bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);}else {s->qlen++; bup(&s->mtx); bdown(&s->q);} bup(&s->q2);

}

void up(sem *s) {bdown(&s->mtx);if (s->qlen == 0) {s->val++;} else {s->qlen--; bup(&s->q);}bup(&s->mtx);

}

Προγραμματισμός ΙΙΙ 89 [email protected]

typedef struct gs {int val,qlen; bsem mtx,q,q2; /* …, σειριοποίηση στην down */

} gsem;

void init(sem *s, int val) {s->val=val; s->qlen=0;binit(&s->mtx,1); binit(&s->q,0); binit(&s->q2,1);

}

void down(sem *s) {bdown(&s->mtx); if (s->val > 0) {s->val--; bup(&s->mxt);}else {

bdown(&s->q2);s->qlen++; bup(&s->mtx); bdown(&s->q);bup(&s->q2);

}}

void up(sem *s) {bdown(&s->mtx);if (s->qlen == 0) {s->val++;} else {s->qlen--; bup(&s->q);}bup(&s->mtx);

}