diff --git a/anno2/YearI/FirstSem/MCAD/altro/LittleBookOfSemaphores.pdf b/anno2/YearI/FirstSem/MCAD/altro/LittleBookOfSemaphores.pdf new file mode 100644 index 0000000..d0443f1 Binary files /dev/null and b/anno2/YearI/FirstSem/MCAD/altro/LittleBookOfSemaphores.pdf differ diff --git a/anno2/YearI/FirstSem/MCAD/altro/hw3sol..htm b/anno2/YearI/FirstSem/MCAD/altro/hw3sol..htm new file mode 100644 index 0000000..8f60242 --- /dev/null +++ b/anno2/YearI/FirstSem/MCAD/altro/hw3sol..htm @@ -0,0 +1,367 @@ + + +
+Synchronization Problems
+ +Notes:
+ +- +Please use real binary semaphores, counting semaphores, +or monitors. If you invent your own synchronization method, there is a 99% chance +you will get it wrong. Plus it makes it very hard to grade - we look very +closely and are more likely to find problems. If you must do this, provide an +implementation of your construct, because otherwise we don't know if:
+ +o +It is possible to implement
+ +o +How it works
+ +- +If you use semaphores, you must specify initial values +for your semaphores (mandatory).
+ +- +If you have a shared state, you should say what mutex +protects the shared state (not mandatory)
+ +- +With semaphores, if you wake up on one semaphore and then +call signal() to wake up the next waiter you might wake yourself up - +semaphores have history, so your next wait might be the one that awakes, +because the other waiters might have been context switchted out before they +call wait().
+ +- +With semaphores, you shouldn't wait while holding a +mutex, unless the routine signaling you does not need the mutex to wake you up.
+ +- +With monitors, you don't need to grab a mutex (or, +shudder, a condition variable) to access shared state. The monitor, by +definition, ensures mutual exclusion.
+ +- +With monitors, wait() doesn't take any parameters - it +just waits until somebody then calls signal().
+ +-
+When writing synchronization code, you should try to
+minimize the number of context switches and the number of times a process is
+awoken when it doesn't need to be. Ideally, in a while() loop, a process should
+only be woken once.
+
+
+wait(mutex) +if (customers_waiting == 0) { + signal(mutex); + wait(barber_sleeping); + wait(mutex); +} +customers_waiting--; +signal(mutex); +signal(customer_queue); +do_cut_hair(); +signal(cut_done); ++ +Customer Code
+wait(mutex); +if (customers_waiting == n) { + signal(mutex); + return; +} +customers_waiting++; +if (customers_waiting == 1) { + signal(barber_sleeping); +} +signal(mutex); +wait(customer_queue); +get_hair_cut(); +wait(cut_done); ++ +As a monitor + +
+monitor barbershop { + int num_waiting; + condition get_cut; + condition barber_asleep; + condition in_chair; + condition cut_done; + + Barber routine + barber() { + while (1); + while (num_waiting == 0) { + barber_asleep.wait(); + } + customer_waiting.signal(); + in_chair.wait(); + give_hait_cut(); + cut_done.signal(); + } + Customer routine + customer () { + if (num_waiting == n) { + return; + } + if (num_waiting == 0) { + barber_asleep.signal(); + } + customer_waiting.wait(); + in_char.signal(); + get_hair_cut(); + cut_done.wait(); + } ++ +
7. +7.9. The Cigarette-Smokers Problem.
+ +Semaphores +are a convenient mechanism for implementing this, because they remember what +elements are on the table.
+ +Sempahore TobaccoAndPaper = 0;
+Sempahore PaperAndMatches = 0;
+Semaphore MatchesAndTobacco = 0;
+Sempaphore DoneSmoking = 1;
void agent()
+{
+ wait(DoneSmoking);
+ int r = rand() % 3;
+ //
+ // Signal which ever combination was
+ // chosen.
+ //
+
+
+ switch( r ) {
+ case 0:
+signal(TobaccoAndPaper);
+ break;
+ case 1:
+signal(PaperAndMatches);
+ break;
+ case 2:
+signal(MatchesAndTobacco);
+ break;
+ }
+}
+
+void Smoker_A()
+{
+ while(true) {
+
+ //
+ // Wait for our
+two ingredients
+ //
+
+
+wait(TobaccoAndPaper);
+ smoke();
+
+ //
+ // Signal that
+we're done smoking
+ // so the next
+agent can put down
+ // ingredients.
+ //
+
+
+signal(DoneSmoking);
+ }
+}
+
+
Smoker
+b and c are similar.
+ +
+
+8. +7.15. File-synchronization
+ ++From the book you should know how to use a conditional-wait construct (priority-based signaling), so we'll use it here. We'll assume for simplicity that no +process has an id greater than or equal to n (or we'd just print an error +message).
+ +type file = monitor
var space_available: binary condition
total: integer
procedure entry file_open(id)
begin
while (total + id >= n)
space_available.wait(id)
total = total + id;
if (total < n - 1)
space_available.signal();
end
procedure entry file_close(id)
begin
total = total - id;
space_available.signal();
end
+
+What +happens here? As long as the incoming processes find adequate space available +(i.e. sums less than n), they will claim that space and open the file. Note +that since we're using a binary condition, we can signal() at will even if +nothing is waiting. If a process finds inadequate space, it will block. When a +process is done, it wakes up the process with the smallest id (the most likely +to fit in the available space). This process, upon waking, then signals the +next process if space is still available, but only after successfully claiming +its own space. At some point (quite possibly with the first process), the space +made available may not be enough for the waking process, and so a process will +be woken up prematurely. This is what the loop is for; it will immediately +block again.
+ + + +