CS 2200

CS 2200
Presentation 18b
MUTEX
Questions?
Our Road Map
Processor
Memory Hierarchy
I/O Subsystem
Parallel Systems
Networking
Recall
• Various schemes allow multiple processes
in memory at the same time
• Virtual memory allowed 2 (or more)
processes to share pages.
– e.g. Multiple users of tin sharing pure code
pages
• Processes can also share pages of data
where both processes can read and write
to memory.
Single Processor Shared Frame
P1 Page
Table
Physical
Memory
P2 Page
Table
MultiProcessor (shared frame)
Processor
Processor
Memory
Processor
Problems?
Example
Process B
Process A
Gets customer
account number
and amount from
memory.
(If Account != 0)
Puts customer
account number
and amount into
memory.
(If Account == 0)
Sets Account = 0
Shared memory
Account
Amount
Example
Process B
Process A
Gets customer
account number
and amount from
memory.
(If Account != 0)
Puts customer
account number
and amount into
memory.
(If Account == 0)
Sets Account = 0
Shared memory
lock Account
Amount
Example
Process B
Process A
Gets customer
account number
and amount from
memory.
(If Account != 0)
Puts customer
account number
and amount into
memory.
(If Account == 0)
Sets Account = 0
Shared memory
lock Account
Amount
Example
Process B
Process A
Gets customer
account number
and amount from
memory.
(If Account != 0)
Puts customer
account number
and amount into
memory.
(If Account == 0)
Sets Account = 0
Shared memory
lock Account
Amount
Example
Process B
Process A
Gets customer
account number
and amount from
memory.
(If Account != 0)
Puts customer
account number
and amount into
memory.
(If Account == 0)
Sets Account = 0
Shared memory
lock Account
Amount
Example
Process B
Process A
Gets customer
account number
and amount from
memory.
(If Account != 0)
Puts customer
account number
and amount into
memory.
(If Account == 0)
Sets Account = 0
Shared memory
lock Account
Amount
Example
Process B
Process A
Gets customer
account number
and amount from
memory.
(If Account != 0)
Puts customer
account number
and amount into
memory.
(If Account == 0)
Sets Account = 0
Shared memory
lock Account
Amount
Example
Process B
Process A
Gets customer
account number
and amount from
memory.
(If Account != 0)
Puts customer
account number
and amount into
memory.
(If Account == 0)
Sets Account = 0
Shared memory
lock Account
Amount
Example
Process B
Process A
Gets customer
account number
and amount from
memory.
(If Account != 0)
Puts customer
account number
and amount into
memory.
(If Account == 0)
Sets Account = 0
Shared memory
lock Account
Amount
Example
Process B
Process A
Gets customer
account number
and amount from
memory.
(If Account != 0)
Puts customer
account number
and amount into
memory.
(If Account == 0)
Sets Account = 0
Shared memory
lock Account
Amount
Mutex
• Mutual Exclusion
• Two or more processes need to share an
area in memory
• Only one should have access at a time
• Designate a single memory location as the
lock
• This location can have two values: 0 or 1.
• For simplicity assume that there are
constants defined: RED and GREEN
Mutex
• If the lock location is GREEN a process
can change it to RED and use the shared
memory area.
• When finished it sets the lock back to
GREEN and lets another process have a
turn.
History
History
• E. Dijkstra applied the concept of
semaphores to Computer Science
Semaphores
void wait(int *s) {
while (*s <= 0) {
/* spin */
}
*s = *s - 1;
}
void signal(int *s) {
*s = *s + 1;
}
/* P */
What is the value
of s when locked?
Unlocked?
/* V */
Usage -- Critical Section Mutex
/* mutex globally initialized to 1
*/
while(1) {
wait(&mutex);
/* Critical Section */
signal(&mutex);
/* Other stuff */
}
While in critical
section mutex = 0
Counting Semaphores
• What happens when mutex variable is
initialized to some value other than 1?
Usage -- Synchronization
/* Initialize synch to 0 */
/* Process P1 executes this code first */
signal(&synch);
/* Process P2 is supposed to wait */
wait(&synch);
/* P2 now continues */
Questions?
An Approach
loop:
loop:
while(lock == RED)
{
// spin!
}
lock = RED;
// Access shared
lock = GREEN;
while(lock == RED)
{
// spin!
}
lock = RED;
// Access shared
lock = GREEN;
goto loop;
goto loop;
Work?
1 Yes
2 No
Need Atomic Operation
• Like atomic swap
int swap(mutex *lock, int val);
• Operation: The value in val is stored in
the mutex variable lock and the value that
was in lock is returned. Both operations
are carried out atomically.
How to use...
while(swap(&lock, RED) == RED)
{
// spin
}
• Swap puts the value RED into the lock variable.
• If the lock variable is RED then no change
occurs.
• If the lock variable is GREEN then the lock
variable becomes RED and GREEN is returned!
Using Atomic Swap
loop:
loop:
while(swap(&lock,RED)
== RED)
{
// spin!
}
while(swap(&lock,RED)
== RED)
{
// spin!
}
// Access shared here
lock = GREEN;
// Access shared here
lock = GREEN;
goto loop;
goto loop;
Another Problem?
Recall Multiprocessor Cache
Coherency
Using Atomic Swap
loop:
loop:
while(swap(&lock,RED)
== RED)
{
// spin!
}
while(swap(&lock,RED)
== RED)
{
// spin!
}
// Access shared here
lock = GREEN;
// Access shared here
lock = GREEN;
goto loop;
goto loop;
It works but...
• The atomic swap fixes our problem but
creates a new one!
Processor
Processor
Processor
Cache
Cache
Cache
lock
Memory
What happens every time
we swap (read & write) to
the lock?
Using Atomic Swap with Caching
loop:
do {
while(lock == RED) {
// spin
}
} while(swap(&lock,RED) == RED)
// Access shared here
lock = GREEN;
loop:
do {
while(lock == RED) {
// spin
}
} while(swap(&lock,RED)== RED)
// Access shared here
lock = GREEN;
goto loop;
goto loop;
Operation
Processor 1
Processor 2
Processor 3
has lock...
while(lock==RED)
while(lock==RED)
lock = GREEN;
invalidates
invalidates
Off doing other stuff invalidates
swap returns Green
swap returns RED
has lock...
while(lock==RED)
has lock...
while(lock==RED)
has lock...
invalidates
lock = GREEN;
swap returns Green Off doing other stuff
has lock...
It works!
• The cache hardware is now helping us!
Processor
Processor
Processor
Cache
Cache
Cache
lock
Memory
Truth in CS:Decker's mutual exclusion algorithm
shared boolean locked[2] = {false, false};
private int my_id; // 0 or 1
// do_critical(f): execute f when we have exclusive
//
access to critical region.
void do_critical(VoidFn f) {
do {
locked[my_id] = false;
while(locked[1-my_id]); // spin while the other
// has access to CS
locked[my_id] = true;
} while(locked[1-my_id]);
// now we have the exclusive access to CS
f();
locked[my_id] = false;
}
Questions?