synchronisation hardware Flashcards
(13 cards)
describe synchronisation hardware
Many systems provide hardware support for critical section
Uniprocessors - could disable interrupts
Currently running code would execute without preemption
Generally too inefficient on multiprocessor systems
Delay in one processor telling others to disable their interrupts
Modern machines provide the special atomic hardware
instructions (Atomic = non-interruptible) TestAndSet or
Swap which achieve the same goal:
TestAndSet: Test memory address (i.e. read it) and set it in
one instruction
Swap: Swap contents of two memory addresses in one
instruction
We can use these to implement simple locks to realise mutual
exclusion
modern machines provide
special atomic instructions what are they
Swap
TestAndSet
what does TestAndSet do
Test memory address (i.e. read it) and set it in
one instruction
what does Swap do
Swap contents of two memory addresses in one
instruction
what does atomic mean
non - interruptable
what are Testandset and swap used for
used to implement simple locks to realise mutual exclusion
The general pattern for using locks is:
do {
[acquire lock]
[critical section]
[release lock]
[remainder section]
} while (TRUE);
code for TestAndSet instruction
boolean TestAndSet (boolean *target) {
boolean original = *target; // Store the original value
*target = TRUE;
// Set the variable to TRUE
return original:
// Return the original value
}
boolean TestAndSet (boolean *target) {
boolean original = *target;
*target = TRUE;
return original:
}
what does the code do and why is the code useful
- In a nutshell: this single CPU instruction sets a variable to
TRUE and returns the original value. - This is useful because, if it returns FALSE, we know that only our thread has changed the value from FALSE to TRUE; if it returns TRUE, we know we haven’t changed the value.
what is the solution code using text and set
Shared boolean variable lock, initialized to false
do {
while (TestAndSet(&lock)) ; // wait until we successfully
// change lock from false to true
[critical section]
lock = FALSE; // Release lock
[remainder section]
} while (TRUE);
what does this code achieve
do {
while (TestAndSet(&lock)) ;
//waits until lock changes from false to true
[critical section]
lock = FALSE; // Release lock
[remainder section]
} while (TRUE);
achieves mutual exclusion but not bounded waiting - one process could potentially wait for ever
due to the unpredictability of context switching
Bounded-waiting Mutual Exclusion with TestAndSet()
All data structures are initialised to FALSE.
wants_in[] is an array of waiting flags, one for each process.
lock is a boolean variable used to lock the critical section
code for bounded-waiting Mutual Exclusion with TestAndSet()
boolean wants_in[], key = FALSE, lock = FALSE; //all false to begin with
do {
wants_in[i] = TRUE; // I (process i) am waiting to get in.
key = TRUE; // Assume another has the key.
while (wants_in[i] && key) { // Wait until I get the lock
// (key will become false)
key = TestAndSet(&lock); // Try to get the lock
}
wants_in[i] = FALSE; // I am no longer waiting: I’m in now
[** critical section *]
// Next 2 lines: get ID of next waiting process, if any.
j = (i + 1) % NO_PROCESSES; // Set j to my right-hand process.
while ((j != i) && !wants_in[j]) { j = (j + 1) % NO_PROCESSES };
if (j == i) { // If no other process is waiting…
lock = FALSE; // Release the lock
} else { // else ….
wants_in[j] = FALSE; // Allow j to slip in through the ’back door’
}
[ remainder section ***]
} while (TRUE);