537 First Half
atomically means _______________
"as a unit" or "all or none" often called a "transaction" achieved by using "synchronization primitives"
What is FIFO scheduling policy? benefits? when does it do poorly?
"first come first served" principle simple and easy to implement works well in very simple cases when first job is very long, followed by short jobs. called the CONVOY EFFECT
Why use threads?
- Parallelism: use on thread per CPU to perform a "linear task" much faster. - Avoid blocking from I/O: using multiple threads, one can wait for I/O to finish while the others do some useful computations, allowing overlap of I/O and other activities in the same program.
what must be done after a program's code/static data are loaded into a process's AS?
- allocate memory for stack, fill in parameters to main function (argc, argv) - allocate memory for heap - other initialization tasks (IO related) - jump to main routine
3 advantages of using randomness for lottery?
- avoids strange corner cases which more traditional algorithms might have (say LRU) - random is lightweight, and requires very little state information - random is pretty fast
what were the negatives of disabling interrupts as a locking mechanism?
- calling threads must perform privileged instructions (turning on/off interrupts) thus we must trust them (bad idea) - a process could disable interrupts and go into an infinite loop, with OS never regaining control - doesn't work with multiprocessors - interrupts can become lost - inefficient
what is the direct execution protocol (without limits?)
- create entry for process list - allocate memory for program - load program into memory - set up stack with argc/argv - clear registers - execute call main() (wait for program to return) - free memory of process - remove from process list
two common metrics used in scheduling policies?
- historical info (which process has run more over the last minute?) - performance metrics (optimizing for interactive performance, or throughput?)
why does a simple flag variable as a lock fail?
- interleaving the code in the wrong way will lead to 2+ processes possessing the lock at the same time (while loop part) - spin-waiting is very inefficient use of CPU
what do the load-linked and store-conditional instructions do?
- load-linked simply fetches a value from memory and places it in a register - store-conditional only succeeds (and updates the val stored at the addr just load-linked from) if no intervening store to the address has taken place! (returns 1 on success, 0 on failure)
qualities of a good lock?
- provides mutual exclusion - fairness (no starvation) - performance (time overheads, no contention vs contention, multiple CPUs)
what are three internal steps of making a system call?
- put arguments on the stack/well known registers - puts the system call number into a well known location - execute the trap instruction
3 process states?
- running: executing instructions on a processor - runnable/ready: ready to run - blocked: waiting on something else (disk IO)
High level outline of lottery scheduling?
- scheduler knows how many total tickets there are - divide total tickets among the processes - for each time slice, scheduler picks a winning ticket (which is within the range of all tickets), and then the scheduler loads the context of the winning process.
general idea of a ticket lock?
- use a global lock->turn var to decide which thread's turn it is to run. Unlocking is just incrementing this variable. Threads spin while it's not their turn.
analysis of yielding instead of spinning?
- works well for 2 threads - still wasteful, doing lots of context switches and yields if there are many processes - suffers from problems of starvation
evaluation of spin locks?
- yes, works correctly - no, does not ensure that threads don't starve - on a single processor, spin locks have a painful amount of overhead due to lots of spinning. on a system with multiple processors, spin locks are pretty reasonable because critical sections are presumably short
what is the consumer/producer (bounded buffer) problem?
1 or more producer threads generate data items and put them in a queue (bounded buffer), and 1 or more consumer threads grab these data items and consume them in some way. the bounded buffer requires synchronization, o.w. a race condition will arise.
if the main thread creates two additional threads, how many times should pthread_join be called before continuing with main?
2
how many locks does the michael & scott concurrent queue have?
2 - one for the head, one for the tail
what is the turnaround time metric?
A performance metric (Time job completed) - (Time job arrived) T turnaround = T completion - T arrival
general process API (5)
Create Destroy Wait Misc. Status
what is the high level concept of stride scheduling?
Each job in the system has a stride which is is the inverse of the number of tickets it has. Each time a process runs, we will increment a counter for it (its pass value) by its stride, to track its progress. The scheduler always chooses the process with the lowest current pass value.
Advantage of lottery scheduling over stride scheduling?
No global state required, so if a new process comes in that we didn't see before, we're not in a quandary of whether to give it a 0 pass value and have it monopolize the CPU, or do something else. So lottery scheduling makes it easier to incorporate new processes sensibly.
with processes, we saved state to a _____________________. With threads, we'll need one or more ____________________________ to store the state of each thread of a process.
PCB - process control block TCB - thread control block(s)
what is the response time metric?
T(response) = T(first run) - T(arrival)
What is round robin scheduling? how to choose time slice length? downfall?
We specify a time slice (or scheduling quantum) that is a MULTIPLE OF THE TIMER INTERRUPT PERIOD. The scheduler simply switches from job to job every time slice until all jobs are completed. the smaller the time slice, the more responsive it is, but if it becomes very small, then the costs of context switching dominate overall performance. So it's a tradeoff--trying to amortize the cost of switching without making the system slow to respond. awful if we care about turnaround time, because RR drags out jobs as long as possible in the name of response time. Even worse than FIFO in many cases.
Once a thread is created, could it start running right away?
Yes, but it depends on the whims of the scheduler. It may also be put into a "ready" or "runnable" state There is no reason to assume that a thread created first will run first
what is a two-phase lock?
a lock that realizes that spinning can be useful if the lock is about to be released, so it breaks spinning into 2 stages. if the waiting thread does not acquire the lock in the first X number of spins, it goes to stage 2, where it is put to sleep and only woken when lock is freed later.
what is a context switch?
a low level piece of code that saves registers of previous process onto its kernel stack, and restore a few registers to the next process from the that process's kernel stack. the switch itself is the switching of kernel stacks
why do we need to acquire the lock before using signal or wait?
a malicious scheduler could set it up so that parent runs first after thread created, parent sees done is zero, but before it can sleep switch to child thread, which signals the CV (nothing sleeping) and is done, then return to parent which sleeps forever.
what is a preemptive scheduler vs. non preemptive?
a non-preemptive scheduler doesn't consider switching jobs when one is running, it waits until completion. all modern schedulers use preemptive scheduling, i.e. to context switch from one job to another to minimize turnaround time
what is a critical section?
a piece of code that updates a shared resource, and must not be concurrently executed by more than one thread
what type of scheduler does a spin lock require to work / make sense?
a preemptive one, which will interrupt the thread via a timer from time to time
what happens if S (sloppiness) is small vs. large?
a smaller S means the process acts more slowly (precisely) and a bigger S means the counter acts closer to perfectly scalable, but the global counter is further off from the true value
main difference between a procedure call and a system call?
a system call transfers control (jumps) into the OS while simultaneously raising the hardware privilege level (using traps and trap handlers, and then return-from-traps)
what is a process's machine state made up of?
address space, registers (including PC, SP, FP), IO information
what are policies?
algorithms for making some kind of decision within the OS (ex. scheduling policy)
why is allowing a user program to jump anywhere into the kernel a very bad idea?
allowing them to jump anywhere would imply they could get arbitrary code sequences to run (say, just after a permission check) and take over the machine.
what's the purpose of the setpark() system call?
allows a thread to indicate it is about to park, so if it happens to be interrupted and another thread calls unpark before park is called in the original, the subsequent park returns immediately instead of sleeping forever. (wakeup/waiting race)
what is yielding, i.e. yield()?
an OS primitive which a thread can call to give up the CPU and let another thread run. moves caller from RUNNING to READY basically deschedules itself
what is a condition variable / high level outline?
an explicit queue that threads can put themselves on when some state/condition is not in desired state (by waiting), and then some other thread will wake 1+ of these threads when it changes this state (by signaling)
high level outline of limited direct execution protocol?
at boot, trap table initialized, and hardware remembers locations of syscall handlers. at runtime, OS sets up creating process, fills, kernel stack with registers/PC and return-from-traps. hardware helps transition to program by restoring registers and jumping to main. then it's as we expect.
what does the test-and-set ("atomic exchange") instruction do?
atomically returns the old value at the location, and sets it to the passed in value
how to differentiate between parent and child process after a fork, and how to write code for each?
check the return codes: for a child, rc is 0, and for the parent, the return code is the PID of the child. Then just do a couple of if statements to put them down their respective paths.
what's the idea of sloppy counting?
each CPU has a local counter (each having a lock) and then there's a global counter (with a lock). each thread only updates the counter on its CPU (to retain synchronization) and then periodically (when a local sum hits threshold) the global counter is updated by adding the val of a local counter, and then setting the local counter to zero.
what is perfect scaling?
even though more work is done, it is done in parallel, so the time taken to complete the task does not increase
what is the STCF scheduler? downfalls?
every time a new job enters the system, it determines which job has the shortest time to completion left, and runs that job, possibly preempting a running job. avoids the convoy effect, and is optimal for jobs arriving at different times not very good with response time, since a longer job would have to wait for other shorter jobs to complete in their entirety before ever seeing the scheduler.
while lottery scheduling gets the proportions of running times right in a probabilistic sense, the stride scheduler gets each proportion _______________________________
exactly correct, at the end of each "scheduling cycle"
what does exec() system call do?
given the name of an executable (e.g. wc) and some related arguments, it laods code and static data from that executable and overwrites its current code segment and static data with it, and it re-initialized the stack and heap. I.e. it transforms the current running program into a different one. And a successful call does not return.
what's an OK technique for scaling a concurrent linked list?
hand-over-hand locking (lock coupling) use a lock for each node in the list. when traversing the list, first grab the next node's lock, then release the lock of the current/prev node. note that it's not much after, if at all, over the basic granular locking mechanism
two types of register save/restores that happen during context switch?
hardware saves user registers (using kernel stack) kernel registers are saved by the (into memory in the process structure of the proc)
how can we make the execution of code after a fork deterministic?
have the parent wait for the child to finish, using the wait() system call (or waitpid())
mechanisms provide answers to ___________ questions, and policies supply answers to ____________ questions.
how, which
why not substitute a condition variable with a regular shared variable?
hugely inefficient use of CPU (just spinning) and can be incorrect in some cases
what is the problem of priority inversion (esp. with spin locks?) how to avoid it?
if a lower priority thread grabs a lock and gets interrupted in its critical section, the higher priority thread may get stuck spinning forever, or may get stuck waiting on the lower priority thread to finish, which may never happen use priority inheritance, where a higher priority thread can boost the priority of the lower thread it's waiting on to overcome the inversion.
what is mutual exclusion?
if one thread is operating in the critical section of the code, it is guaranteed that the other will be prevented from doing so
why do we need a state variable (e.g. done) for proper behavior when using CVs?
if there's no state variable, parent process always sleeps instead of only sleeping when child isn't done. so if child runs first, parent will sleep and no thread will ever wake it.
what is a cooperative approach, and why do they fail?
in this style, the OS trusts the processes of the system to behave reasonably, and periodically give up the CPU through system calls or yields, or doing something illegal (divide by 0) they fail because a bad or malicious process could never give up CPU, and you'd have to reboot computer.
It's important to note that as job time _____________________, the effectiveness of lottery scheduling increases.
increases
how to solve the problem of which thread to wake up in memory allocation / free example? what do we call this condition?
instead of pthread_cond_signal, use pthread_cond_broadcast to wake up ALL sleeping threads so that the "correct" one is always woken up; the rest will simply recheck the condition and go back to sleep. a "covering condition", since it covers "all" the cases where a thread needs to wake up. the cost is to performance, in waking up possibly more threads than are needed.
what must the hardware do/be careful of when executing a trap?
it must save enough of the calling program's state (PC, certain registers, flags) onto the per-process kernel stack, and pop these off the stack when returning-from-trap.
what are mechanisms?
low-level methods or protocols that implement a needed piece of functionality
a coarse grained locking strategy is when _______________________
one big lock is used any time any critical section is accessed
how many locks does a concurrent hashtable have?
one for each hash bucket (built into the concurrent list)
what is a futex? common 2 calls?
parallels park and unpark each futex has an associated physical memory location and a per-futex, in kernel-queue. futex_wait(addr, expected): puts calling thread to sleep if value at addr is expected, otherwise returns futex_wake(addr): wakes one thread waiting on the queue
what do park() and unpark() do?
park() puts the calling thread to sleep unpark(threadID) wakes a thread
a multi-threaded program with one with multiple _________________________, ie multiple __________________________. Each thread is like a separate __________________________, except that they share the same _____________________________.
points of execution, program counters process, address space, so they can access the same data.
Lottery scheduling is ______________, not _______________________
probabilistic, not deterministic
what is amortization?
reducing the number of times a fixed cost is incurred to reduce total cost. i.e. making a time slice longer to incur context switch costs less often.
important things OS saves for each process?
register context (what's in each), state of process, parent, open files, etc.
each thread has its own private set of _________________________, which means when switching between threads on a processor, a _______________________ must take place
registers to use for computations context switch
what does the fetch-and-add hardware primitive do?
returns the old value while incrementing it, atomically
ready --> running? running --> ready?
scheduled descheduled
what does the kill() system call do?
sends signals to a process (sleep, die. etc.)
what are Mesa semantics?
signaling to a thread only wakes them up, i.e. it is a HINT that the world has changed, but is not a guarantee that it will remain that way when that thread actually runs.
what does trap do? what does return-from-trap do?
simultaneously jumps into the kernel while raising the privilege level to kernel mode returns into the calling using program while simultaneously reducing the privilege back to user mode
reason #2 why consumer/producer problem breaks with just one condition variable? solution?
situations can arise where consumer threads wake other consumer threads (instead of a producer thread) and vice versa, which can leave all threads sleeping indefinitely. use two CVs: one for each type of thread
in what format do programs reside in on a disk/SSD?
some executable format
when a process has multiple threads, each thread has a separate ________________________
stack (in the VAS) sometimes called "thread-local" storage
What's the major difference between a context switch between processes and between threads of a process?
switching threads does not require saving/restoring the address space, i.e. no need to switch which page table we're using.
what does loading do (brief?)
take on-disk program (code, static data) and reads it into the address space of process (which has heap and stack too)
how does the OS set up the machine for time interrupts in a non-cooperative approach?
tells hardware which code to run when a timer interrupt occurs, and starts the timer in the boot sequence (so it can rest assured it will regain control).
what does the compare-and-swap hardware primitive do?
test whether the value specified by ptr is equal to "expected"; if so, update the memory pointed to by ptr with the new value. otherwise, do nothing. Either way, return the actual value.
how does the trap know which code to run inside the OS?
the kernel sets up a trap table at boot time, as it boots in kernel mode. So it tells the hardware what code to run if certain exceptional events occur in specifying the locations of these trap handlers, usually with a special instruction
both wait() and signal() both assume that ___________________________ briefly describe what happens when wait and signal are called
the lock is held by the calling thread when called wait - holding the lock, a process calls wait, and it is put to sleep (releasing the lock) and is put on the CV queue signal - holding the lock, if theres 1+ sleeping processes, wakes one or more of them and passes it the lock; otherwise does nothing
a fine grained locking strategy is when ____________________________
there exist multiple locks, one for each critical section/data structure, which allows more threads to be in locked code at once
______________________________ can be used to let users allocate tickets on any scale they like, and have all of these scales converted to a single global one by the system. ______________________ allows a process to temporarily hand off its tickets to another process (esp. useful for a client/server setting) ________________________, given that processes trust each other, is when a process can temporarily raise/lower the # tickets it owns, to reflect needed CPU time without communicating with other processes
ticket currency ticket transfer ticket inflation
_____________________ are often useful for modeling representing proportions of ownership
tickets
What is the Unfairness metric (U) defined to be? A perfectly fair scheduler would achieve U = ______
time first job completes / time second job completes 1
why should you always use a while loop when checking conditions in a concurrent program?
to be safe about checking conditions, as sometimes spurious wakeups can occur depending on certain implementation details of the thread package, and similar issues.
A proportional share / fair share scheduler: instead of optimizing for ___________________________, the scheduler might instead try to guarantee that ________________________________________.
turnaround or response time, each job obtains a certain percentage of CPU time
why is the trap system a form of protection?
user programs cannot specify an address to jump to, they must request a service via number.
how do we limit what user processes can do with I/O an memory allocation? how do we let user programs "get permission" to do these things?
we use two processor modes, user mode (not privileged) and kernel mode (privileged) we expose system calls, which allow the kernel to carefully expose certain key pieces of functionality to user programs
what is time sharing of the CPU? what is the potential cost?
we virtualize the CPU by running one process, stopping it and running another via context switching. performance, since each will run more slowly if the CPU must be shared.
a process's machine state is ____________________________
what a program can read or update when it is running
when is SJF an optimal scheduling algorithm (for turnaround time?) when does it do poorly?
when all jobs are received at the same time when a large job is received slightly before two small jobs, and those jobs wait for the large one. CONVOY EFFECT
what is a race condition?
when two threads enter their respective "critical sections" at the same time (i.e. updating a global counter) and one of them will overwrite the other--the timing determines the result
how does the OS keep track of processes? what is the name for the struct that holds info about a process?
with a process list of ready processes, and some additional info to track which one is running will also tracked blocked processes process control block (PCB)
why does the producer/consumer problem fail with a single condition variable? (reason #1) simple solution (but still broken)?
with more than one consumer or producer, producers could wake a consumer, but then another consumer could run before that one, leaving the buffer empty when the signaled to consumer runs. use a while loop instead of an if