2. THREADS COME FROM:
A few choices:
The operating system
A user-mode library
Some combination of the two…
3. KERNEL THREADS:
Threads implemented inside the OS
Thread operations (creation, deletion, yield)
are system calls
Scheduling handled by the OS scheduler
Described as “one-to-one”
One user thread mapped to one
kernel thread
Every invocation of Thread.start()
creates a kernel thread
process
OS threads
4. USER THREADS:
Implemented as a library inside a process
All operations (creation, destruction, yield)
are normal procedure calls
Described as “many-to-one”
Many user-perceived threads map to a single
OS process/thread
process
OS thread
5. code
(text segment)
static data
(data segment)
heap
(dynamic allocated mem)
thread 1 stack
PC (T2)
SP (T2)
thread 2 stack
thread 3 stack
SP (T1)
SP (T3)
PC (T1)
PC (T3)
THREADED ADDRESS SPACE:
Every thread always has
its own user stack and
program counter
For both user, kernel
threads
For user threads, there
is only a single kernel
stack, program counter,
PCB, etc.
User address space (for both user
and kernel threads)
6. USER THREADS VS. KERNEL THREADS
User threads are faster
Operations do not pass through the OS
But, user threads suffer from:
Lack of physical parallelism
Only run on a single processor!
Poor performance with I/O
A single blocking operation stalls the entire
application
For these reasons, most (all?) major OS’s
provide some form of kernel threads
7. PROBLEMS WITH MANY-TO-MANY
THREADS:
Lack of coordination between user and
kernel schedulers
“Left hand not talking to the right”
Specific problems
Poor performance
e.g., the OS preempts a thread holding a crucial lock
Deadlock
Given K kernel threads, at most K user threads can
block
Other runnable threads are starved out!
8. THREAD-SAFE BLOCKING LOCKS:
Atomically test-and-set locked status
If lock is already held:
Set thread state to blocked
Disable interrupts
Add PCB (task_struct) to a wait queue
Invoke the scheduler
Next task re-enables interrupts