Download CS 519 -- Operating Systems -

Document related concepts

CP/M wikipedia , lookup

VS/9 wikipedia , lookup

Distributed operating system wikipedia , lookup

DNIX wikipedia , lookup

Process management (computing) wikipedia , lookup

Thread (computing) wikipedia , lookup

Transcript
Processes, Threads,
Synchronization
CS 519: Operating System Theory
Computer Science, Rutgers University
Instructor: Thu D. Nguyen
TA: Xiaoyan Li
Spring 2002
Von Neuman Model
Both text (program) and data reside in memory
Execution cycle
Fetch instruction
Decode instruction
CPU
Execute instruction
Memory
Computer Science, Rutgers
2
CS 519: Operating System Theory
Image of Executing Program
100
load R1, R2
104
add R1, 4, R1
108
load R1, R3
112
add R2, R3, R3
R1: 2000
R2:
R3:
PC: 100
CPU
…
2000 4
2004 8
Memory
Computer Science, Rutgers
3
CS 519: Operating System Theory
How Do We Write Programs Now?
public class foo {
static private int yv = 0;
static private int nv = 0;
public static void main() {
foo foo_obj = new foo;
foo_obj->cheat();
}
How to map a program
like this to a Von
Neuman machine?
Where to keep yv, nv?
What about foo_obj and
tyv?
public cheat() {
int tyv = yv;
yv = yv + 1;
if (tyv < 10) {
cheat();
}
}
How to do foo->cheat()?
}
Computer Science, Rutgers
4
CS 519: Operating System Theory
Global Variables
Dealing with “global” variables like yv and nv is easy
Let’s just allocate some space in memory for them
This is done by the compiler at compile time
A reference to yv is then just an access to yv’s location in
memory
Suppose g is stored at location 2000
Then, yv = yv + 1 might be compiled to something like
loadi
load
add
store
2000, R1
R1, R2
R2, 1, R2
R1, R2
Computer Science, Rutgers
5
CS 519: Operating System Theory
Local Variables
What about foo_obj defined in
main() and tyv defined in
cheat()?
1st option you might think of is
just to allocate some space in
memory for these variables as
well (as shown to the right)
2000
yv
2004
2008
nv
foo_obj
tyv
What is the problem with this
approach?
How can we deal with this
problem?
Computer Science, Rutgers
6
CS 519: Operating System Theory
Local Variable
foo->cheat();
tyv = yv;
…
foo->cheat();
tyv = yv;
…
yv
globals
tyv
tyv’
tyv’’
stack
Allocate a new memory location to tyv every time cheat() is called at runtime
Convention is to allocate storage in a stack (often called the control stack)
Pop stack when returning from a method: storage is no longer needed
Code for allocating/deallocating space on the stack is generated by
compiler at compile time
Computer Science, Rutgers
7
CS 519: Operating System Theory
What About “new” Objects?
foo foo_obj = new foo;
foo_obj is really a pointer to a foo object
As just explained, a memory location is allocated for
foo_obj from the stack whenever main() is invoked
Where does the object created by the “new foo”
actually live?
Is the stack an appropriate place to keep this object?
Why not?
Computer Science, Rutgers
8
CS 519: Operating System Theory
Memory Image
Suppose we have executed the
following:
yv = 0
nv = 0
main()
foo_obj = new foo
foo->cheat()
tyv = yv
yv = yv + 1
foo->cheat()
tyv = yv
yv = yv + 1
foo->cheat()
tyv = yv
yv = yv + 1
Computer Science, Rutgers
yv
foo_obj
tyv
tyv’
tyv’’
globals
stack
heap
9
CS 519: Operating System Theory
Data Access
How to find data allocated dynamically on stack?
By convention, designate one register as the stack pointer
Stack pointer always point at current activation record
Stack pointer is set at entry to a method
Code for setting stack pointer is generated by compiler
Local variables and parameters are referenced as offsets from sp
activation record
for cheat_yes()
PC
SP
tyv
CPU
Computer Science, Rutgers
10
CS 519: Operating System Theory
Data Access
The statement
tyv = tyv + 1
Would then translate into something like
addi
0, sp, R1
load
R1, R2
addi
1, R2
store
R1, R2
Computer Science, Rutgers
# tyv is the only variable so offset is 0
11
CS 519: Operating System Theory
Activation Record
We have only talked about
allocation of local variables on
the stack
Other stuff
The activation record is also
used to store:
Local variables
Parameters
The beginning of the previous
activation record
The return address
…
Computer Science, Rutgers
12
CS 519: Operating System Theory
Run Time Storage Organization
Code
Globals
Stack
Each variable must be assigned a storage
class
Global (static) variables
Allocated in globals region at compiletime
Method local variables and parameters
Allocate dynamically on stack
Heap
Memory
Dynamically created objects (using new)
Allocate from heap
Objects live beyond invocation of a
method
Garbage collected when no longer “live”
Computer Science, Rutgers
13
CS 519: Operating System Theory
Why Did We Talk About All That Stuff?
Process = system abstraction for the set of resources
required for executing a program
= a running instance of a program
= memory image + registers’ content (+ I/O
state)
The stack + registers’ content represent the execution
context or thread of control
Computer Science, Rutgers
14
CS 519: Operating System Theory
What About The OS?
Recall that one of the function of an OS is to provide a virtual
machine interface that makes programming the machine easier
So, a process memory image must also contain the OS
Code
Globals
Memory
OS
Stack
Code
Globals
Heap
Stack
OS data space is used to store things
like file descriptors for files being
accessed by the process, status of I/O
devices, etc.
Heap
Computer Science, Rutgers
15
CS 519: Operating System Theory
What Happens When There Are More
Than One Running Process?
OS
Code
Globals
Stack
P0
Heap
P1
P2
Computer Science, Rutgers
16
CS 519: Operating System Theory
Process Control Block
Each process has per-process state maintained by the OS
Identification: process, parent process, user, group, etc.
Execution contexts: threads
Address space: virtual memory
I/O state: file handles (file system), communication endpoints
(network), etc.
Accounting information
For each process, this state is maintained in a process control
block (PCB)
This is just data in the OS data space
Think of it as objects of a class
Computer Science, Rutgers
17
CS 519: Operating System Theory
Process Creation
How to create a process? System call.
In UNIX, a process can create another process using the fork()
system call
int pid = fork();
/* this is in C */
The creating process is called the parent and the new process is
called the child
The child process is created as a copy of the parent process
(process image and process control structure) except for the
identification and scheduling state
Parent and child processes run in two different address spaces
By default, there’s no memory sharing
Process creation is expensive because of this copying
The exec() call is provided for the newly created process to run a
different program than that of the parent
Computer Science, Rutgers
18
CS 519: Operating System Theory
System Call In Monolithic OS
interrupt vector for trap instruction
PC
PSW
in-kernel file system(monolithic OS)
code for fork system call
kernel mode
trap
iret
user mode
id = fork()
Computer Science, Rutgers
19
CS 519: Operating System Theory
Process Creation
fork() code
PCBs
fork()
exec()
Computer Science, Rutgers
20
CS 519: Operating System Theory
Example of Process Creation Using Fork
The UNIX shell is command-line interpreter whose basic purpose
is for user to run applications on a UNIX system
cmd arg1 arg2 ... argn
Computer Science, Rutgers
21
CS 519: Operating System Theory
Process Death (or Murder)
One process can wait for another process to finish
using the wait() system call
Can wait for a child to finish as shown in the example
Can also wait for an arbitrary process if know its PID
Can kill another process using the kill() system call
What all happens when kill() is invoked?
What if the victim process doesn’t want to die?
Computer Science, Rutgers
22
CS 519: Operating System Theory
Process Swapping
May want to swap out entire process
Thrashing if too many processes competing for resources
To swap out a process
Suspend all of its threads
Must keep track of whether thread was blocked or ready
Copy all of its information to backing store (except for PCB)
To swap a process back in
Copy needed information back into memory, e.g. page table,
thread control blocks
Restore each thread to blocked or ready
Must check whether event(s) has (have) already occurred
Computer Science, Rutgers
23
CS 519: Operating System Theory
Process State Diagram
ready
(in
memory)
swap in
swap out
suspended
(swapped out)
Computer Science, Rutgers
24
CS 519: Operating System Theory
Signals
OS may need to “upcall” into user processes
Signals
UNIX mechanism to upcall when an event of interest occurs
Potentially interesting events are predefined: e.g.,
segmentation violation, message arrival, kill, etc.
When interested in “handling” a particular event (signal), a
process indicates its interest to the OS and gives the OS a
procedure that should be invoked in the upcall.
Computer Science, Rutgers
25
CS 519: Operating System Theory
Signals (Cont’d)
When an event of interest occurs the
kernel handles the event first, then
modifies the process’s stack to look as
if the process’s code made a procedure
call to the signal handler.
When the user process is scheduled
next it executes the handler first
From the handler the user process
returns to where it was when the event
occurred
Computer Science, Rutgers
26
Handler
B
B
A
A
CS 519: Operating System Theory
Inter-Process Communication
Most operating systems provide several abstractions
for inter-process communication: message passing,
shared memory, etc
Communication requires synchronization between
processes (i.e. data must be produced before it is
consumed)
Synchronization can be implicit (message passing) or
explicit (shared memory)
Explicit synchronization can be provided by the OS
(semaphores, monitors, etc) or can be achieved
exclusively in user-mode (if processes share memory)
Computer Science, Rutgers
27
CS 519: Operating System Theory
Inter-Process Communication
More on shared memory and message passing later
Synchronization after we talk about threads
Computer Science, Rutgers
28
CS 519: Operating System Theory
A Tree of Processes On A Typical UNIX
System
Computer Science, Rutgers
29
CS 519: Operating System Theory
Process: Summary
System abstraction – the set of resources required for executing
a program (an instantiation of a program)
Execution context(s)
Address space
File handles, communication endpoints, etc.
Historically, all of the above “lumped” into a single abstraction
More recently, split into several abstractions
Threads, address space, protection domain, etc.
OS process management:
Supports creation of processes and interprocess communication (IPC)
Allocates resources to processes according to specific policies
Interleaves the execution of multiple processes to increase system
utilization
Computer Science, Rutgers
30
CS 519: Operating System Theory
Threads
Thread of execution: stack + registers (which includes
the PC)
Informally: where an execution stream is currently at in the
program and the method invocation chain that brought the
execution stream to the current place
Example: A called B which called C which called B which called
C
The PC should be pointing somewhere inside C at this point
The stack should contain 5 activation records: A/B/C/B/C
Thread for short
Process model discussed thus far implies a single thread
Computer Science, Rutgers
31
CS 519: Operating System Theory
Multi-Threading
Why limit ourselves to a single thread?
Think of a web server that must service a large stream of requests
If only have one thread, can only process one request at a time
What to do when reading a file from disk?
Multi-threading model
Each process can have multiple threads
Each thread has a private stack
Registers are also private
All threads of a process share the code and heap
Objects to be shared across multiple threads should be allocated on the heap
Computer Science, Rutgers
32
CS 519: Operating System Theory
Process Address Space Revisited
OS
OS
Code
Code
Globals
Globals
Stack
Stack
Stack
Heap
Heap
(a) Single-threaded address space (b) Multi-threaded address space
Computer Science, Rutgers
33
CS 519: Operating System Theory
Multi-Threading (cont)
Implementation
Each thread is described by a thread-control block (TCB)
A TCB typically contains
Thread ID
Space for saving registers
Pointer to thread-specific data not on stack
Observation
Although the model is that each thread has a private stack,
threads actually share the process address space
 There’s no memory protection!
 Threads could potentially write into each other’s stack
Computer Science, Rutgers
34
CS 519: Operating System Theory
Thread Creation
PC
SP
thread_create() code
PCBs
TCBs
thread_create()
new_thread_starts_here
stacks
Computer Science, Rutgers
35
CS 519: Operating System Theory
Context Switching
Suppose a process has multiple threads …uh oh … a
uniprocessor machine only has 1 CPU … what to do?
In fact, even if we only had one thread per process, we would
have to do something about running multiple processes …
We multiplex the multiple threads on the single CPU
At any instance in time, only one thread is running
At some point in time, the OS may decide to stop the
currently running thread and allow another thread to
run
This switching from one running thread to another is
called context switching
Computer Science, Rutgers
36
CS 519: Operating System Theory
Diagram of Thread State
Computer Science, Rutgers
37
CS 519: Operating System Theory
Context Switching (cont)
How to do a context switch?
Save state of currently executing thread
Copy all “live” registers to thread control block
For register-only machines, need at least 1 scratch register
points to area of memory in thread control block that registers should
be saved to
Restore state of thread to run next
Copy values of live registers from thread control block to
registers
When does context switching take place?
Computer Science, Rutgers
38
CS 519: Operating System Theory
Context Switching (cont)
When does context switching occur?
When the OS decides that a thread has run long enough and
that another thread should be given the CPU
Remember how the OS gets control of the CPU back when it is
executing user code?
When a thread performs an I/O operation and needs to block
to wait for the completion of this operation
To wait for some other thread
Thread synchronization: we’ll talk about this lots in a couple of
lectures
Computer Science, Rutgers
39
CS 519: Operating System Theory
How Is the Switching Code Invoked?
user thread executing  clock interrupt  PC modified by
hardware to “vector” to interrupt handler  user thread state is
saved for restart  clock interrupt handler is invoked  disable
interrupt checking  check whether current thread has run “long
enough”  if yes, post asynchronous software trap (AST) 
enable interrupt checking  exit interrupt handler  enter
“return-to-user” code  check whether AST was posted  if not,
restore user thread state and return to executing user thread; if
AST was posted, call context switch code
Why need AST?
Computer Science, Rutgers
40
CS 519: Operating System Theory
How Is the Switching Code Invoked?
(cont)
user thread executing  system call to perform I/O 
user thread state is saved for restart  OS code to
perform system call is invoked  I/O operation started
(by invoking I/O driver)  set thread status to waiting
 move thread’s TCB from run queue to wait queue
associated with specific device  call context switching
code
Computer Science, Rutgers
41
CS 519: Operating System Theory
Context Switching
BC
CS
BC
UC
BC
BC
CS
Computer Science, Rutgers
At entry to CS, the return address is
either in a register or on the stack (in
the current activation record)
CS saves this return address to the
TCB instead of the current PC
To thread, it looks like CS just took a
while to return!
If the context switch was initiated
from an interrupt, the thread never
knows that it has been context
switched out and back in unless it
looking at the “wall” clock
42
CS 519: Operating System Theory
Context Switching (cont)
Even that is not quite the whole story
When a thread is switched out, what happens to it?
How do we find it to switch it back in?
This is what the TCB is for. System typically has
A run queue that points to the TCBs of threads ready to run
A blocked queue per device to hold the TCBs of threads blocked
waiting for an I/O operation on that device to complete
When a thread is switched out at a timer interrupt, it is still ready to
run so its TCB stays on the run queue
When a thread is switched out because it is blocking on an I/O
operation, its TCB is moved to the blocked queue of the device
Computer Science, Rutgers
43
CS 519: Operating System Theory
Ready Queue And Various I/O Device
Queues
Computer Science, Rutgers
44
CS 519: Operating System Theory
Switching Between Threads of Different
Processes
What if switching to a thread of a different process?
Caches, TLB, page table, etc.?
Caches
Physical addresses: no problem
Virtual addresses: cache must either have process tag or must flush
cache on context switch
TLB
Each entry must have process tag or must flush TLB on context
switch
Page table
Typically have page table pointer (register) that must be reloaded on
context switch
Computer Science, Rutgers
45
CS 519: Operating System Theory
Threads & Signals
What happens if kernel wants to signal a process when
all of its threads are blocked?
When there are multiple threads, which thread should
the kernel deliver the signal to?
OS writes into process control block that a signal should be
delivered
Next time any thread from this process is allowed to run, the
signal is delivered to that thread as part of the context switch
What happens if kernel needs to deliver multiple signals?
Computer Science, Rutgers
46
CS 519: Operating System Theory
Thread Implementation
Kernel-level threads (lightweight processes)
Kernel sees multiple execution context
Thread management done by the kernel
User-level threads
Implemented as a thread library which contains the code for
thread creation, termination, scheduling and switching
Kernel sees one execution context and is unaware of thread
activity
Can be preemptive or not
Computer Science, Rutgers
47
CS 519: Operating System Theory
User-Level vs. Kernel-Level Threads
Advantages of user-level threads
Performance: low-cost thread operations (do not require
crossing protection domains)
Flexibility: scheduling can be application specific
Portability: user-level thread library easy to port
Disadvantages of user-level threads
If a user-level thread is blocked in the kernel, the entire
process (all threads of that process) are blocked
Cannot take advantage of multiprocessing (the kernel assigns
one process to only one processor)
Computer Science, Rutgers
48
CS 519: Operating System Theory
User-Level vs. Kernel-Level Threads
user-level
threads
kernel-level
threads
threads
thread
scheduling
user
kernel
threads
process
thread
scheduling
process
scheduling
processor
processor
Computer Science, Rutgers
process
scheduling
49
CS 519: Operating System Theory
User-Level vs. Kernel-Level Threads
No reason why we shouldn’t
have both
user-level
threads
Most systems now support
kernel threads
thread
scheduling
User-level threads are available
as linkable libraries
user
kernel
kernel-level
threads
thread
scheduling
process
scheduling
processor
Computer Science, Rutgers
50
CS 519: Operating System Theory
Threads vs. Processes
Why multiple threads?
Can’t we use multiple processes to do whatever that is that we
do with multiple threads?
Of course, we need to be able to share memory (and other
resources) between multiple processes …
But this sharing is already supported – see later in the lecture
Operations on threads (creation, termination, scheduling, etc..)
are cheaper than the corresponding operations on processes
This is because thread operations do not involve manipulations of
other resources associated with processes
Inter-thread communication is supported through shared
memory without kernel intervention
Why not? Have multiple other resources, why not threads
Computer Science, Rutgers
51
CS 519: Operating System Theory
Thread/Process Operation Latencies
Operation
User-level
Threads
(s)
Kernel
Threads
(s)
Processes
(s)
Null fork
34
948
11,300
Signal-wait
37
441
1,840
Computer Science, Rutgers
52
CS 519: Operating System Theory
Synchronization
Synchronization
Problem
Threads must share data
Data consistency must be maintained
Example
Suppose my wife wants to withdraw $5 from our account and I
want to deposit $10
What should the balance be after the two transactions have
been completed?
What might happen instead if the two transactions were
executed concurrently?
Computer Science, Rutgers
54
CS 519: Operating System Theory
Synchronization (cont)
The balance might be SB – 5
W reads SB
I read SB
I compute SB + 10 and save new balance
W computes SB – 5 and save new balance
The balance might be SB + 10
How?
Ensure the orderly execution of cooperating
threads/processes
Computer Science, Rutgers
55
CS 519: Operating System Theory
Terminologies
Critical section: a section of code which reads or writes
shared data
Race condition: potential for interleaved execution of a
critical section by multiple threads
Results are non-deterministic
Mutual exclusion: synchronization mechanism to avoid
race conditions by ensuring exclusive execution of
critical sections
Deadlock: permanent blocking of threads
Starvation: execution but no progress
Computer Science, Rutgers
56
CS 519: Operating System Theory
Requirements for ME
No assumptions on hardware: speed, # of processors
Mutual exclusion is maintained – that is, only one thread
at a time can be executing inside a CS
Execution of CS takes a finite time
A thread/process not in CS cannot prevent other
threads/processes to enter the CS
Entering CS cannot de delayed indefinitely: no deadlock
or starvation
Computer Science, Rutgers
57
CS 519: Operating System Theory
Synchronization Primitives
Most common primitives
Locks (mutual exclusion)
Condition variables
Semaphores
Monitors
Need
Semaphores, or
Locks and condition variables, or
Monitors
Computer Science, Rutgers
58
CS 519: Operating System Theory
Locks
Mutual exclusion  want to be
the only thread modifying a set
of data items
Can look at it as exclusive
access to data items or to a
piece of code
Have three components:
Acquire, Release, Waiting
Computer Science, Rutgers
59
CS 519: Operating System Theory
Example
public class BankAccount
{
Lock aLock = new Lock;
int balance = 0;
...
public void deposit(int amount)
{
aLock.acquire();
balance = balance + amount;
aLock.release();
}
Computer Science, Rutgers
60
public void withdrawal(int amount)
{
aLock.acquire();
balance = balance - amount;
aLock.release();
}
}
CS 519: Operating System Theory
Implementing Locks Inside OS Kernel
From Nachos (with some simplifications)
public class Lock {
private KThread lockHolder = null;
private ThreadQueue waitQueue =
ThreadedKernel.scheduler.newThreadQueue(true);
public void acquire() {
KThread thread = KThread.currentThread();
if (lockHolder != null) {
waitQueue.waitForAccess(thread);
KThread.sleep();
}
else {
lockHolder = thread;
}
}
Computer Science, Rutgers
61
// Get thread object (TCB)
// Gotta wait
// Put thread on wait queue
// Context switch
// Got the lock
CS 519: Operating System Theory
Implementing Locks Inside OS Kernel
(cont)
public void release() {
if ((lockHolder = waitQueue.nextThread()) != null)
lockHolder.ready();
// Wake up a waiting thread
}
This implementation is not quite right … what’s missing?
Computer Science, Rutgers
62
CS 519: Operating System Theory
Implementing Locks Inside OS Kernel
(cont)
public void release() {
boolean intStatus = Machine.interrupt().disable();
if ((lockHolder = waitQueue.nextThread()) != null)
lockHolder.ready();
Machine.interrupt().restore(intStatus);
}
Computer Science, Rutgers
63
CS 519: Operating System Theory
Implementing Locks At User-Level
Why?
Expensive to enter the kernel
Parallel programs on multiprocessor systems
What’s the problem?
Can’t disable interrupt …
Many software algorithms for mutual exclusion
See any OS book
Disadvantages: very difficult to get correct
So what do we do?
Computer Science, Rutgers
64
CS 519: Operating System Theory
Implementing Locks At User-Level
Simple with a “little bit” of help from the hardware
Atomic read-modify-write instructions
Test-and-set
Atomically read a variable and, if the value of the variable is currently
0, set it to 1
Fetch-and-increment
Compare-and-swap
Computer Science, Rutgers
65
CS 519: Operating System Theory
Atomic Read-Modify-Write Instructions
Test-and-set
Read a memory location and, if the value is currently 0, set it
to 1
Fetch-and-increment
Return the value of of a memory location
Increment the value by 1 (in memory, not the value returned)
Compare-and-swap
Compare the value of a memory location with an old value
If the same, replace with a new value
Computer Science, Rutgers
66
CS 519: Operating System Theory
Simple Spin Lock
Test-and-set
Spin_lock(lock)
{
while (test-and-set(lock) == 0);
}
Spin_unlock(lock)
{
lock = 0;
}
Computer Science, Rutgers
67
CS 519: Operating System Theory
What To Do While Waiting?
Spinning
Waiting threads keep testing location until it changes value
Doesn’t work on uniprocessor system
Blocking
OS or RT system deschedules waiting threads
Spinning vs. blocking becomes an issue in multiprocessor
systems (with > 1 thread/processor)
What is the main trade-off?
How can we implement a blocking lock?
Computer Science, Rutgers
68
CS 519: Operating System Theory
Deadlock
Computer Science, Rutgers
Lock A
Lock B
A
B
69
CS 519: Operating System Theory
Deadlock
Computer Science, Rutgers
Lock A
Lock B
A
B
70
CS 519: Operating System Theory
Deadlock
Computer Science, Rutgers
Lock A
Lock B
A
B
71
CS 519: Operating System Theory
Deadlock (Cont’d)
Deadlock can occur whenever multiple parties are competing for
exclusive access to multiple resources
How can we deal deadlocks?
Deadlock prevention
Design a system without one of mutual exclusion, hold and wait, no
preemption or circular wait (four necessary conditions)
To prevent circular wait, impose a strict ordering on resources. For instance, if
need to lock variables A and B, always lock A first, then lock B
Deadlock avoidance
Deny requests that may lead to unsafe states (Banker’s algorithm)
Running the algorithm on all resource requests is expensive
Deadlock detection and recovery
Check for circular wait periodically. If circular wait is found, abort all
deadlocked processes (extreme solution but very common)
Checking for circular wait is expensive
Computer Science, Rutgers
72
CS 519: Operating System Theory
Condition Variables
A condition variable is always associated with:
A condition
A lock
Typically used to wait for the condition to take on a
given value
Three operations:
Computer Science, Rutgers
public class CondVar
{
public Wait(Lock lock);
public Signal();
public Broadcast();
// ... other stuff
}
73
CS 519: Operating System Theory
Condition Variables
Wait(Lock lock)
Release the lock
Put thread object on wait queue of this CondVar object
Yield the CPU to another thread
When waken by the system, reacquire the lock and return
Signal()
If at least 1 thread is sleeping on cond_var, wake 1 up. Otherwise, no
effect
Waking up a thread means changing its state to Ready and moving the
thread object to the run queue
Broadcast()
If 1 or more threads are sleeping on cond_var, wake everyone up
Otherwise, no effect
Computer Science, Rutgers
74
CS 519: Operating System Theory
Producer/Consumer Example
Imagine a web server with the following architecture:
One “producer” thread listens for client http requests
When a request is received, the producer enqueues it on a
circular request queue with finite capacity (if there is room)
A number of “consumer” threads services the queue as follows
Remove the 1st request from the queue (if there is a request)
Read data from disk to service the request
How can the producer and consumers synchronize?
Computer Science, Rutgers
75
CS 519: Operating System Theory
Producer/Consumer (cont)
public class SyncQueue
{
public boolean IsEmpty();
public boolean IsFull();
public boolean Enqueue(Request r);
public Request Dequeue();
public LockVar lock = new Lock;
public CondVar waitForNotEmpty = new CondVar;
public CondVar waitForNotFull = new CondVar;
...
}
Computer Science, Rutgers
76
CS 519: Operating System Theory
Producer
public class Producer extends Thread
{
private SyncQueue requestQ;
public Producer(SyncQueue q) {requestQ = q;}
public void run()
{
// Accept a request from some client.
// The request is stored in the object newRequest.
requestQ.lock.Acquire();
while (requestQ.IsFull()) {
waitForNotFull.Wait();
}
requestQ.Enqueue(newRequest);
waitForNotEmpty.Signal();
requestQ.lock.Release();
}
}
Computer Science, Rutgers
77
CS 519: Operating System Theory
Consumer
public class Consumer extends Thread
{
private SyncQueue requestQ;
public Consumer(SyncQueue q) {requestQ = q;}
public void run()
{
requestQ.lock.Acquire();
while (requestQ.IsEmpty()) {
waitForNotEmpty.Wait();
}
Request r = requestQ.Dequeue();
waitForNotFull.Signal()
requestQ.lock.Release();
// Process the request
}
}
Computer Science, Rutgers
78
CS 519: Operating System Theory
Implementing Condition Variables
Can you see how to do this from our discussion of how
to implement locks?
You will need to understand how for a later assignment
Computer Science, Rutgers
79
CS 519: Operating System Theory
Semaphore
Synchronized counting variables
Formally, a semaphore is comprised of:
An integer value
Two operations: P() and V()
P()
While value = 0, sleep
Decrement value and return
V()
Increments value
If there are any threads sleeping waiting for value to become
non-zero, wakeup at least 1 thread
Computer Science, Rutgers
80
CS 519: Operating System Theory
Implementing Semaphores
Let’s do this together on the board
Can you see how to implement semaphores given locks
and condition variables?
Can you see how to implement locks and condition
variables given semaphores?
Hint: if not, learn how
Computer Science, Rutgers
81
CS 519: Operating System Theory
Monitors
Semaphores have a few limitations: unstructured,
difficult to program correctly. Monitors eliminate
these limitations and are as powerful as semaphores
A monitor consists of a software module with one or
more procedures, an initialization sequence, and local
data (can only be accessed by procedures)
Only one process can execute within the monitor at any
one time (mutual exclusion)
Synchronization within the monitor implemented with
condition variables (wait/signal) => one queue per
condition variable
Computer Science, Rutgers
82
CS 519: Operating System Theory
Lock and Wait-free Synchronization (or
Mutual Exclusion Considered Harmful)
Problem: Critical sections
If a process is delayed or halted in a critical section, hard or
impossible for other processes to make progress
Lock-free (aka non-blocking) concurrent objects
Some process will complete an operation on the object in a
finite number of steps
Wait-free concurrent objects
Each process attempting to perform an operation on the
concurrent object will complete it in a finite number of steps
Essential difference between these two?
Computer Science, Rutgers
83
CS 519: Operating System Theory
Herlihy’s Paper
What’s the point?
Lock and wait-free synchronization can be very useful for
building multiprocessor systems; they provide progress
guarantees
Building lock and wait-free concurrent objects is HARD, so a
methodology for implementing these objects is required
Lock and wait-free synchronization provide guarantees but can
be rather expensive – lots of copying
M. Greenwald and D. Cheriton. The Synergy between
Non-blocking Synchronization and Operating System
Structure. In Proceedings of OSDI ’96, Oct, 1996.
Computer Science, Rutgers
84
CS 519: Operating System Theory
Single Word Protocol
Fetch_and_add_sync(obj: integer, v: integer) returns(integer)
success: boolean := false
loop exit when success
old: integer := obj
new: integer := old+v
success := compare_and_swap(obj, old, new)
end loop
return old
end Fetch_and_add_sync
Lock-free but not wait-free!!
Computer Science, Rutgers
85
CS 519: Operating System Theory
Small Objects
Small object: occupies 1 block (or less)
Basic idea of lock-free object implementation
Allocate a new block
Copy object to new block, making sure copy is consistent
Modify copied block, i.e. perform operation on copied block
Try to atomically replace pointer to old block with new one
Basic idea of wait-free object implementation
Same as before, except that processes should announce their
operations in a shared data structure
Any process in step 3 should perform all previously announced
operations, not just its own operations
Computer Science, Rutgers
86
CS 519: Operating System Theory
Large Objects
I’ll leave for you to read
Basic idea is to make local changes in the data structure
using small object protocol
Complicated but not different than locking: e.g., if you
lock an entire tree to modify some nodes, performance
will go down the drain
Computer Science, Rutgers
87
CS 519: Operating System Theory