Title: Synchronization Issues
1Synchronization Issues
- Enable/Disable is dangerous for user tasks
- Hardware dependent
- Leads to Spaghetti codeare all paths really
safe? - Is deadlock possible. Can the system detect
deadlock? - Too much power at task level
2System Support for Synchronization
critical section
need a HW interlock to prevent simultaneity
The term semaphore means signal. It comes from
the railroads. A semaphore requires some form of
mutual exclusion in hardware like
disabling interrupts. By making it an OS call, we
leave implementation up to the OS/HW. Same
system call on many HW platforms.
3Semaphore Implementations
- Some processors have a Test-and-Set Instruction
- provides hardware level atomicity for
synchronizing critical sections. - example
- volatile bit flag
-
- while (!flag)
- flag true
- ltexcute code in critical sectiongt
-
- If processor has a test and set operation, it
could like like this in assembly code - loop tst flag, loop //sometimes they just
skip the next instruction - lt execute critical section gt
- But we still dont want to rely on our
compilerso we use a system call - sem1 s // declare a semaphore
- while(!set(s)) // os_set(semaphore) is a
system calllet OS worry about atomicity - ltexecute critical sectiongt
- clear(s)
- Rely on the system to properly enable/disable
interrupts as needed
bad time for an interrupt?
4A Better Semaphore
- Problem with first semaphore busy-waiting. OS
cant tell the difference between busy waiting
and doing real work. - How can we solve this? Try a blocking semaphore
- struct sem2
- sem1 s
- processQueue Q
- int count
-
- void os_init_sem(sem2 s)
- s?count MAX_PROC_IN_SECTION // probably one
-
- void os_wait(sem2 s)
- set(s?sem1)s?count--
- if (s?count lt 0)
- block calling process and put it in s?queue
- start any process in the ready-to-run queue
- clear(s?sem1)
-
sem cs1 . os_wait(cs1) ltexecute critical
sectiongt os_signal(cs1) // tiny has wait and
signal // but they are thread // specific
Problem still rely on user To check in and out
properly
void os_signal(sem2 s) set(s?sem1)
s?count if (s?count lt 0) move proc.
from s-gtqueue to ready queue
clear(s?sem1)
5Monitors, better than Semaphores?
- Semaphores are like gotomakes your multithreaded
system into spaghetti - Hard to tell if you have created a deadlock
situation - An alternative? The Monitor you see this in Java
with synchronized methods - Only one thread can be executing in a monitor at
a time. The compiler builds in all of the
os_calls and semaphores needed to protect the
critical section - No chance of forgetting to signal when leaving!
unless of course a process dies in the monitor. - Basic ideabury semaphores in the compiler
- class queue synchronized
- Vector data
- queue() data new Vector()
- void put(Object x)
- data.add(x)
-
- Object get(Object x)
- data.remove(0)
-
class top q new queue() Producer p new
Producer(q) Consumer c new Consumer(q) p.run
() c.run()
individual methods can also be synchronized
6Process v. Thread
- Process
- Each process runs in a separate virtual address
space. Address 0x1 in process one is not the same
memory location as address 0x1 in another
process. - Context switching is expensive
- need to reload memory management variables
- may need to invalidate cache or do other cache
coherency tricks - Anything address based needs to be saved and
restored - Threads lightweight
- All threads run in the same address space
- Still have same basic state machine (ready,
running, blocked, killed) - Still need context switching for registers,
stack, but not for memory system, cache, etc. Can
communicate through shared memory - The JVM is a process that can contain many
Threads. Java threads all run in the same memory
space. - How can processes in different addresses spaces
communicate, access hardware devices, establish
communication, share semaphores, etc.?