OS Ch 2: Process and Thread Management
Process Scheduling (aka processor scheduling, scheduling)
processes in ready state "competing" for the CPU at the same time. OS uses the scheduler (the part of OS responsible for scheduling) to make the choice for next process to run. This choice varies depending on the scheduling algorithm used.
DISADVANTAGES of threads in KERNEL space
1. require OS support --> significant modification to OS 2. expensive to manage: bc thread calls become system calls
ADVANTAGES of threads in USER space
1. requires NO OS modification. 2. state save and scheduling are invoked faster than kernel call (NO context switching) 3. Scheduler can be customized for each application. (e.g. Garbage-collector thread)
3 states a process may be in:
1. running (actually using the CPU at that instant) 2. ready (runnable, temporarily stopped to let another process run) 3. blocked (unable to run until some external event happens, e.g. for I/O)
How do threads work?
1. start w/one thread in a process 2. use library call to create new threads and to use threads
Distinguishing factor btwn compute-bound (CPU-bound) and I/O-bound jobs is...
LENGTH OF THE CPU BURSTS!! a process is... CPU-bound: CPU computation vs. I/O-bound: process enters a blocked state waiting for external device to complete work
Understanding Interrupt
Let's say running process P issues a read() system call. 1. P is blocked and another process Q in the ready state is run. 2. While Q is running, a disk interrupts, indicating the completion of the disk read previously issued by P. So P is moved to the ready state. **the interrupt itself only specifies the interrupt number. As with TRAP, the OS has stored in a memory location specified by the hardware an interrupt vector that contains the address of the interrupt handler. *Interrupt can happen in either supervisor or user mode
ADVANTAGES of threads in KERNEL space
ONE thread table for the ENTIRE SYSTEM. So if a thread blocks/page fault is generated/infinite loop going on, the kernel just picks another one (not necessarily the one from same process)
process model
OS raising the abstraction for the user processes. in reality, we have the diagram on the left. from each user view, they are running contunuously (sses the diagram on the upper right).
What is Critical Regions (aka Critical Sections, Mutual Exclusion)?
part of the program where the shared memory/resource is accessed (part in program where memory/resource accessed is shared)
Highest Penalty Ratio Next
penalty ratio r: r = T/t T: time in the system t: running time of process to date (or 1, whichever is larger) **NON-PREEMTIVE
3 types of Scheduling Algs: Interactive Systems
preemption crucial for fairness & rapid response time to short requests
3 types of Scheduling Algs: Real Time
preemption not that important
3 types of Scheduling Algs: Batch
primary concern: efficiency. **NO WAITING USER **NON PREEMPTIVE or preemptive w/long time before being preempted **reduces process switching
Modeling Multiprogramming
CPU Utilization = 1 - p^n. p = fraction of the process waiting time for I/O to complete. n = # processes waiting for I/O (MPL) **n processes are independent, meaning multiple process can be running at the same time, while others are waiting (not the case for a single CPU) **OS overhead: process switching varies in CPUs
thread_exit
causes thread to exit and disappear terminate the calling thread
Mutual Exclusion with Busy Waiting: The TSL Instruction
"Test and Set Lock" --> TSL **requires help from the hardware still uses enter_region and leave_region. **implemented using binary semaphore **TSL Instrction (TSL RX, LOCK) or TAS(LOCK): reads content of LOCK into register RX and sets it to 1 (this operation of reading and writing LOCK is atomic (meaning inseparable, done in one step). **then, old value of lock (in register RX) is compared with 0. If it is nonzero, the lock was already set, so the program goes back and tests again. When the process currently in its critical region is done with its critical region, lock is set to 0 using leave_region. **LOCK is used as a shared variable. When lock is 0, any process can set it to 1 using the TSL instruction and back to 0 when it's done
virtual memory
(abstraction provided by the OS to the user processes) the memory as viewed by the process each process thinks that it has CONTIGUOUS memory starting @ location zero. this isn't true of all processes or they'd be using the same memory. in reality, the real memory assigned to a single process is NOT CONTIGUOUS & DOES NOT include LOCATION ZERO
virtual time
(abstraction provided by the OS to the user processes) the time used by just this process. it progresses at a rate INDEPENDENT of other processes.
Scheduling in Batch Systems:
**FIFO **Shortest Job First (SJF) **Shortest Remaining Time Next (SRTN)
Selfish RR
**PREEMPTIVE **active queue: get CPU in RR fashion. process remain in this queue until termination/blocked (all have same priority) **waiting queue: waiting to be accepted to the active queue, get accepted once priority matches the ones in active queue/or active queue empty **starts w/priority of 0
Priority Scheduling
**PREEMPTIVE **each job assigned priority **run job according to priority **user RR among processes w/SAME priority **CAN STARVE PROCESSES
RR (Round Robin)
**PREEMPTIVE **each process assigned quantum to run **switch to ready if quantum runs out **if process blocked/finished before quantum runs out, CPU switches to next process **SHORT quantum = too many switches = system less EFFICIENT **LONG quantum = poor response to short interactive requests = system less RESPONSIVE
Counting Semaphores
**allows a number of processes in the CR **semaphore S holds a positive number, k (if k = 1, we have the original CR problem) **Uses atomic operations: DOWN(S) or P(S) UP(S) or V(S),
Binary Semaphores (Mutexes)
**an abstraction for the TSL **semaphores that are initialized to 1 and used by 2+ processes to ensure that only one of them can enter its CR at the same time **a semaphore S has two possible values: "open" (1) and "close" (0) **mutual exclusion guaranteed by each process doing down just before entering its CR and up just after leaving it. --> only ONE process at a time will be reading/writing DOWN(S) or P(S): checks if S is "open" (1) and sets it to "close" (0) in ATOMIC operation UP(S) or V(S): simply sets S to "open (1) loop forever: DOWN(S) CS UP(S) NCS **TWO CONSECUTIVE Vs DO NOT permit TWO SUBSEQUENT Ps to succeed. (the gate cannot be double opened).
Shortest Process Next
**applying SJF to interactive scheduling **estimates process' run time
Processor Sharing
**merge all ready & running. **permit all jobs to run at once. **w/N jobs, each job running at 1/N speed of what it would run alone **PREEMTIVE
Shortest Remaining Time Next (SRTN)
**pick the job w/shortest remaing time next **PREEMPTIVE: compare the runtime of a new job to the remaining time of existing job **CAN STARVE A PROCESS THAT REQUIRES A LONG BURST --> can be prevented by priority aging
Mutual Exclusion with Busy Waiting: Disabling Interrupts
**process disable all interrupts just after entering its critical region and re-enable just before leaving the region ** this prevents other processes from intervening since clock interrupts cannot occur w/interrupts disabled NOT USED: **doesn't work for user-mode programs **disabling interrupts for too long can lead yo system seeming unresponsive **don't want to give user processes the power to turn off interrupts VIOLATES CONDITION 4
Multilevel Queues
**processes assigned to queues and don't move btwn the queues **each queue may have DIFFERENT scheduling policies **must have policy among the queues
InterProcess Communication (IPC)
**processes need to communicate w/each other using (e.g. in a shell pipeline, the output of the 1st process must be passed to the 2nd process, and so on down the line) **need to consider: 1. how to pass info btwn processes 2. make sure processes are NOT in each other's way 3. ensure proper execution sequence
Multiple Queues
**separate queues with DIFFERENT priority classes **process move btwn queues **priority aging used to prevent starvation
Shortest Job First (SJF)
**sort jobs by execution time needed **run the shortest job first **NON-preemptive **SMALLEST AVERAGE TURNAROUND TIME **CAN STARVE A PROCESS THAT REQUIRES A LONG BURST --> can be prevented by priority aging
Mutual Exclusion
**way of making sure that if one process is using a shared resource (e.g. variable or a file), it prohibits other processes from reading & writing the shared resource at the same time **needed to avoid race conditions. **required by conflicting sections
threads are like processes
1). have same states: running, ready, blocked 2). have their own stacks 3). stacks contain frames for procedure calls, local variables, and return address to use when procedure comes back
DISADVANTAGES of threads in USER space
1. Can't let a thread execute a system call that blocks the entire process because it will block all other threads. Page fault also blocks entire process, meaning all threads are blocked. 2. Threads don't voluntarily give up CPU. Thread w/an infinite loop prevents all other threads in this process from ever running.
Mutual Exclusion with Busy Waiting: 4 proposals
1. Disabling Interrupts 2. Lock Variables 3. Strict Alternation 4. The TSL Instruction
4 requirements for a critical section implementation
1. No two processes may be simultaneously inside their critical region. 2. No assumptions may be made about speeds or the number of concurrent threads/processes. 3. No process running OUTSIDE its critical region MAY BLOCK other processes. 4. No process should have to wait forever to enter its critical region.
Termination mechanisms from outer point of view
1. Normal exit (voluntary) 2. Error exit (voluntary) 3. Fatal Error (involuntary) 4. Killed by another process (involuntary)
When is scheduling desirable/manditory? (i.e. when to make scheduling decisions)
1. Process creation (fork() system call) --> desirable 2. Process termination (exit() system call) --> necessary 3. a process blocks --> necessary 4. process unblocks --> desirable 5. process is preempted --> necessary
Scheduling in Interactive Systems
1. RR 2. Process Sharing 3. Priority Scheduling 4. Selfish RR 5. Multiple Queues 6. Shortest Process Next 7. Highest Penalty Ratio Next 8. Guaranteed Scheduling 9. Lottery Scheduling 10. Fair Share Scheduling
uers' viewpoint for process creation
1. System initialization, incudling daemon processes. 2. Execution of a process creation system call (e.g. fork()) by a running process. 3. A user request to create a new process. 4. Initiation of a batch job.
Two Threads in One Process vs Two Processes
1. Threads in the SAME process SHARE MEMORY; whereas separate processes do not. 2. switching execution from one thread to another thread in the SAME process is much faster than switching execution from one process to other processes.
Scheduling Alg Goals
1. fairness 2. respecting priority (favoring jobs that are considered more important) 3. efficiency (don't spend excessive time in the scheduler & try to keep all parts of the system busy) 4. low turnaround time (minimize the time from submission of a job to its termination) 5. high throughput (maximize the # of jobs completed per day) 6. low response time (minimize the time from when an interactive user issues a command to when the response is given) 7. degrade gracefully under load
Understanding Interrupt: Actions by Q Just Prior to the Interrupt
1. interrupt CAN OCCUR ALMOST ANYWHERE --> SO WE DON"T KNOW WHAT HAPPENED JUST BEFORE THE INTERRUPT Cannot say what caused the interrupt. what we can say is what instruction immediately PRECEEDED the interrupt
Termination mechanisms from internal point of view
1. kill(): sends a signal to another process. For many types of signals, if the signal is NOT caught, the process is terminated. 2. exit(): used for self termination and can indicate success or failure.
Understanding Interrupt: properties of interrupts
1.UNPREDICTABLE, so cannot tell what was executed just before interrupt occured --> asynchronous transfer of control 2. cannot single out an instruction that caused the interrupt the user code in the process currently running is unaware and cannot detect that an interrupt occurred. 3. Interrupts can also happen when the OS itself is executing --> serious difficulties since both the main line code (the OS code that was interrupted) and the interrupt handling code are from the same "program", namely the OS and hence might be using the same variables. 4. The interprocess control of transfer is neither stack-like nor queue-like. Any of the ready process can run. 5. The system might have been in user-mode or supervisor mode when the interrupt occurred. The interrupt processing itself is in supervisor mode.
Understanding Interrupt: Actions by the OS when Returning Control to Q
10. The C procedure (that did the real work in the interrupt processing) continues and returns to the assembly code. 10. Assembly language restores Q's state (e.g. register) and starts Q at the point it was when the interrupt occurred.
Mutual Exclusion with Busy Waiting: Dekker --> Peterson's
1st working soln: Dekker. Then Peterson's soln using enter_region and leave_region made Dekker's soln obsolete. **before entering the CR, each process calls enter_region with its own process number (0 or 1) as parameters **this call will cause it to wait until it's safe to enter **after a process has finished w/the shared variables, it will call 'leave_region' to indicate that it is done
Readers & Writers Problem
2 classes of processes: readers & writers readers: can work CONCURRENTLY writers: need EXCLUSIVE ACCESS problem is to: 1. prevent 2 WRITERS from running concurrently 2. prevent a reader & writer from running concurrently 3. PERMIT multiple READERS to run concurrently WHEN NO WRITER ACTIVE
Producer-Consumer Problem (aka bounded-buffer problem)
2 processes share a common, fixed-size buffer producer: a process that puts info INTO the buffer consumer: a process that TAKES OUT INFO FROM THE BUFFER when producer wants to put a new item into the buffer that's already full: producer goes to sleep, is awakened when the consumer has removed 1+ items when consumer wants to remove an item from the buffer that is empty: goes to sleep until the producer puts something in the buffer and wakes it up both processes tests to see if the other should be awakened. If so, wakes it up.
Understanding Interrupt: Executing the Interrupt Itself
2. the hardware saves the program counter & some other registers 3. the hardware finds the address of the interrupt handler and jumps to it. 4. As w/trap, the hardware automatically switches the system into supervisor mode (**MAAY HAVE BEEN IN SUPERVISOR MODE ALREADY) Note: steps 2 & 3 are similar to procedure call, but the interrupt is asynchronous
Which of the four mechanism for process creation dominates from the system's viewpoint?
2nd: Execution of a process creation system call (fork) by a running process. In early versions of Unix, only one process (called init) is created at system initialization. All the others are created by the fork() system call.
Understanding Interrupt: Actions by the Interrupt Handler Upon Being Activated
5. an assembly language routine in the kernel saves registers 6. the assembly routine switches to the kernel stack 7. the assembly routine calls a procedure in a high level language (often C) 8. The C procedure (also in the kernel) does the real work: a). Determines what caused the interrupt, b). moves the blocked process (associated w/the action causing interrupt) to the ready list, 9. The scheduler decides which process to run.
Why is thread much less expensive than switching btwn separate processes?
Bc threads in the same process share so much state
Why have init? Why not have all processes created via method 2?
Because without init, there would be no running process to create any others.
Why should we avoid busy waiting?
Busy waiting wastes CPU time, so it should only be used when the wait is short.
daemon
Disk And Execution MONitor. A program that is not invoked explicitly, but lies dormant waiting for some condition(s) to occur. In Unix/other computer multitasking OS, a daemon is a computer program that runs in the background, not associated w/particular user. They have specific function. Typically, daemons have names that end with the letter "d".
Dispatchers & Workers
Mutithreaded application can have a dispatcher thread that fields requests and then pass each request onto an idle worker thread. Both dispatcher & worker share memory --> very low overhead for passing request.
FIFO
NON-preemptive **do in the order received **single queue for ready processes **when a process unblocks, it goes to the end of the ready queue
Thread Usage
When a process P executing an application is blocked, there is still computation that can be done for P. Another process cannot do this computation since it doesn't have access to P's memory. BUT TWO THREADS in the SAME PROCESS do share the same memory so that problem doesn't occur for threads
atomic operations/actions
a group of related operations that are either ALL COMPLETED or NOT AT ALL
process
a program in execution
process table
a table holding data about each process (organized by the OS).
priority aging
a technique to prevent starvation: raises priority to ensure that lower priority processes can also run **ASSUMES: all jobs terminate or the policy is preemptive **starvation = certain processes never run bc not high enough priority
process behavior
alternate btwn CPU activity (CPU Burst) and I/O activity (I/O burst)
semaphores
an abstraction to control access to shared resources **a variable (int) that can be incremented/decremented semaphore of value 0: indicates no wakeups were saved semaphore of positive value: 1+ wakeups are pending **uses atomic operations
two atomic operations on semaphores: down() and up()
down() = P() = checks if the semaphore value is GREATER than 0. If GREATER THAN 0: decrease the value (uses up one of the stored wakeup) and continues. IF VALUE == 0: PROCESS PUT TO SLEEP W/O COMPLETING THE DOWN for the moment. up() = V() = INCREMENTS THE VALUE OF THE SEMAPHORE ADDRESSED AND WAKES UP A PROCESS **if 1+ process(es) were sleeping on that semaphore, unable to complete an earlier down operation, one of them is chosen by the system and is allowed to complete its down. **Thus, after an up on a semaphore w/processes sleeping on it, the semaphore will still be 0, but there will be one fewer processes sleeping on it.
process table entry/process control block
each entry in the process table. the data of a process
Mutual Exclusion with Busy Waiting: Lock Variables
have a single, shared (lock) variable, initially 0. When a process wants to enter its critical region, it first tests the lock. If the lock is 0, it means that no process is in its critical region, so the process sets it to 1 and enters the critical region. If the lock is 1, it means some process is in its critical region so the process just waits until it becomes 0. **FLAW: process A sees lock variable is 0. Then it is switched to process B, B also sees that it is 0 and sets it to 1. When A runs again, it thinks that the lock variable is still 0 (from the last time it checked) and sets it to 1 --> TWO PROCESSES IN CRITICAL REGION SIMULTANEOUSLY VIOLATES CONDITION 1
Mutual Exclusion with Busy Waiting: Strict Alternation
have variable, 'turn', keeping track of whose turn it is to enter the critical region. Initially, turn is 0, meaning process 0 enters the critical region. BUSY WAITING: process 1 continuously checks to see when 'turn' becomes 1. When process 0 leaves the CR, it updates the turn variable to 1, so that process 1 can access the critical area. NOT USED: imagine P0 and P1 both finished their turns and are both in their NON-critical region. P0 executes its whole loop quickly, exits its CR and sets the 'turn' to 1. It is P1's turn to go but it is still busy with its NON-CR and P0 finishes its NON-CR and goes back to the top of the loop. Since the 'turn is 1 and P1 isn't in its CR still busy, P0 cannot enter its critical region and waits until P1 sets 'turn' back to 0. **requires two process strictly alternate in entering CR VIOLATES CONDITION 3
Why is Scheduling important?
if you have bunch of users and/or if the demands of the jobs differ
thread_create
includes parameter indicating what procedure to run
Things to note w/modeling multiprogramming
increasing MPL does increase CPU Utilization (up to a point). **another important limitation: memory assuming that we have many jobs loaded at once, meaning we must have enough memory for them
IMPORTANT NOTE OF WHEN SCHEDULER CAN RUN
it can run ONLY WHEN THE OS IS RUNNING
Why is it important that down/P and up/V operations for the semaphore value is done atomically?
it is guaranteed that once a semaphore operation has started, NO OTHER PROCESS CAN ACCESS the SEMAPHORE until the operation has completed/blocked. Atomicity is absolutely essential to solving synchronization problems and avoiding race conditions.
spin lock
lock that uses busy waiting
Double Buffering in the Producer Consumer Pipeline
loop Read 10KB from disk1 to inBuffer. Compute from inBuffer to outBuffer. Write outBuffer to disk2. end loop **cylinder: disks **circles: buffers need two inBuffers and two outBuffers **blue indicates the buffer contains valid data 1. thread 1 reads data from the input disk to the top input buffer. 2. thread 1 reads data from the input disk to the BOTTOM input buffer. At the same time, thread 2 uses the CPU to compute, reading from the top input buffer and writes to the top output bugger. 3. thread 1 reads the input disk into the top input bugger, overwriting what was written before (circle no longer blue), thread 2 computes using the bottom buffers, and thread 3 writes from the top blue output buffer to the output disk. 4. similar thing happens as in step 3 until the input is exhausted. So except for the very 1st time this process runs, multiple threads active at the same time, speed up the whole process.
Process Hierarchies
modern general purpose OS permit a user to CREATE & DESTROY processes. In Unix, creating a process is done by the fork() --> creates a child process. Destroying a process is done by exit() --> terminates the current process (and the kill() --> sometimes terminate another process). After a fork(), both parent & child keep running and each can fork off other processes. This creates process tree w/root of the tree that is a special process created by the OS during startup. A process can choose to wait for children to terminate.
Race Conditions
processes working together can share common storage that each one can read/write. different result depending on the order of execution! 2+ competing processes 1. two processes, A & B about to perform some actions 2. The program doesn't determine which one goes first 3. result of A first != result of B first there is a race btwn 2 or more processes that are reading/writing some shared data and the final result differs depending on which one runs precisely when
multiprogramming
rapid switching from one process to another. this gives the illusion of multiple jobs running at once --> "pseudoparallelism". gives each process illusion that it is running alone.
thread_yield
release the CPU to let another thread run
Preemptive Scheduling
scheduler lets the process run for a max. of some fixed time. After that time, move the process from "running" to "ready" and picks another process to run w/o process request. **OS can move an active process to a ready state W/O the process request **meeds a clock interrupt **need to guarantee fairness **expensive
Nonpreemptive Scheduling
scheduler picks a process, lets it run until it blocks (I/P or wait for another process) or voluntarily release the CPU.
Sleep & Wakeup
sleep: a system call that cause the CALLER TO BLOCK VOLUNTARILY until other process wakes it wake: a system call that accepts a PROCESS TO BE AWAKENED (unblocked) as a PARAMETER
Medium-Term Scheduling
swap in/out from main memory to secondary memory
For ANY number of processes,
the CR problem can be solved using P and V like following: loop forever P(S) CS V(S) NCS
Process State Diagram
the number of processes changes only for two arcs: create (fork) and terminate (exit). a process P that was running blocks (for I/O). At some point later on, a disk interrupt occurs and the driver detects that P's request is satisfied. P is unblocked, so moves from blocked to ready. At some later time, the OS scheduler looks for a ready job to run and picks P. A preemptive scheduler has the dotted line preempt. Suspend and resume are medium term scheduling: 1). done on longer time scale, 2). involves memory management, 3). sometimes called two level scheduling
Multiprogramming Level (MPL) (aka Degree of Multiprogramming)
the number of processes waiting for I/O
Downside of thread usage
the problem with memory sharing among threads is that each thread is NOT PROTECTED from the others in its process. This is a performance/simplicity trade-off.
thread_join
thread blocks (waits) until another thread finishes its work
threads in user space:
thread table in each process (contains info about threads' program counter, stack pointer) so that run time system can manage them if thread blocks locally, runtime system stores thread info in table and finds new thread to run
Threads (aka lightweight processes)
to have multiple threads of control running the in the address space (memory management concept) of a single process. SHARE THE PROCESSOR WITH OTHER THREADS **for now, think of an address space as the memory in which a process runs **each thread is somewhat like a process in that it shares the processor with other threads. but a thread contains less state than a process.
Multithreading
to permit multiple threads of control to execute within one process