You are on page 1of 2

Chapter 5 (synchronization): programs have different interleaving = different runs of the program can produce different results, and

compilers + processor hardware can reorder


instructions, which doesnt affect single-threaded sequences, but affects multiple threads
A race conditions is when the behavior of a program depends on the interleaving of operations of different threads. The results of the program depend on who wins the race
Not all operations are atomic operations, indivisible operations that cannot be interleaved with or split by, load or store of a 32-bit word is atomic
Too Much Milk: roommate 1 sees that theres no milk, goes out to get some, roommate 2 looks and sees theres no milk, also goes out to get some, now they have 2 milk safety: the
program never enters a bad state liveness: the program will
eventually enter a good state
Solution to too much
milk: get a noteA and noteB, start with noteA = 1 and noteB = 1
while noteA == 1,
trap, otherwise buy milk (Petersons algorithm)
Petersons algorithm
is complex and inefficient, since a thread is busy waiting and
consuming CPU
resources, all n threads can busy-wait and a processor can be left
waiting for an event
that wont happen; plus if the compiler/hardware reorders
instructions, the
algorithm is ruined (unless you implement a memory barrier)
shared objects are
objects that can be accessed safely by multiple threads (shared
state with heap,
static and global variables), shared objects hide the details of
synchronizing behind
a clean interface
shared objects
[bounded buffer, barrier], synchronization variables [semaphores,
locks, condition
variables], atomic instructions [interrupt disable, test-and-set],
hardware [multiple
processors,
hardware interrupts]
shared
objects have shared
object layer,
synchronization
variable
layer (member
variables are
synchronization
variables)
two types: locks and
condition
variables, coordinate
access to
state variables, and
atomic
instruction layer
lock provides mutual
exclusion;
when one thread
holds a lock,
no other thread can
hold it, then
does some
operations,
and it appears atomic
to other
threads = no intermediate state, just the state left after the lock release
lock can either be busy or free (lock.acquire() or lock.release()), checking if it is free or busy is an atomic operationlock should
have three properties mutual exclusion, progress (thread must eventually succeed in getting the lock), and bounded waiting (limit
the amount of times a thread gets lock before other thread)
TSQueue returns failure if queue is full, but block bounded queue lets the thread wait until it can insert/remove
A critical section is a sequence of code that atomically accesses shared statethread can get a pointer to a shared object when the
thread is created and stores references to shared objects in other shared objects (e.g. containers)condition variable is to let a
thread wait for a change in the shared state
cv.wait() releases the lock and suspends execution of the calling thread, reacquire the lock before returning from wait, cv.signal will
take one thread of the wait list and eligible to run, broadcast() takes all threads off the waiting list and makes them eligible to run
A condition variable is memoryless, has no internal state, atomically releases the lock, and when a waiting thread is reenabled via
signal, it might not run immediately (just moves to the top of the schedulers ready queue with no special priority, and it must
reacquire the lock and the cv might be false again) wait must be always called from within a loop
running thread with wait() gets put to waiting and then a signal takes a waiting thread and puts it in the ready stateMesa Semantics is when signal takes waiting thread from waiting list
and puts on ready list and they block trying to re-acquire the lock, but Hoare Semantics is when signal suspends current thread and execution goes to signaled threadyou need to add
a loop for using the condition variables (since you must recheck the condition even after a signal())
Always synchronize with locks and condition variables, also acquire lock at the beginning of a method and hold the lock when operating on a CVsynchronization barriers are to check
whether n threads have finished their work with checkin(), no thread can return from checkin() until all threads have entered it, but different from memory barrier since synchronization
barrier called concurrently by many threads, blocking them until all, but memory barrier is called by one thread to prevent thread from proceeding until all memory operations have
completed
FIFOBBQ::remove(){ int item; int myPosition; CV *myCV, *nextWaiter; lock.acquire(); myPosition = numRemoveCalled++; mycv = new CV; removeQueue.append(myCV); while(front <
myPosition || front == nextEmpty) mycv->Wait(&lock); nextWaiter = insertQueue.removeFromFront(); if(nextWaiter != NULL) nextWaiter -> Signal(&lock); lock.release(); return item;}
semaphore has a non-negative value, initialized to non-neg integer, P() waits until the value is positive, decrements value by 1 and returns, V() atomically increments by 1, or if anything
is waiting in P() it wakes it up, no thread can directly read the current value of the semaphore..CV vars are stateless while semaphores have state (which means P() and V() are
commutative), semaphores are not starvation free IncreaseCap (int additionalSeat){for (int i = 0; i < additionalSeat; i++){V(remain_seat);}} Chapter 7 (Scheduling) task = jobs, response
time or delay = user-perceived time to do some task, predictability = low variance in response times for repeated requests, throughput = rate at which tasks are completed, scheduling
overhead = time to switch from one task to another, fairness = equality in the number and timeliness of resources given to each task, starvation = lack of progress for one task, due to
resources given to a higher priority task compute-bound only uses processor, scheduler is work-conserving if it never leaves the processor idle when there is work to do
FIFO minimizes overhead, and will have best throughput with fixed amount of CPU-bound tasks, and is quite fair. But if a task with little work to do lands behind a long task, it seems
inefficient = worst average response time
SJF minimizes average response time, pessimal for variance in response time, can suffer from starvation and frequent context switches, if enough short tasks arrive, long tasks may
never complete, long tasks preempted by short tasks
Round Robin addresses starvation, tasks take turns running on the processor for a limited period of time (time quantum), compromise between FIFO (infinite time quantum) and SJF
(minimum time quantum), weakness of Round Robin is when several tasks start at the same time and same length, it will finish them all at the same time, RR is also bad for mixture of IObound and CPU-bound, max-min fairness is when you give I/O bound their entire share and then redistribute the unused portion among the others to fully satisfy those (ex: if P1 needs
10% of processor to keep busy and the other two processes are cpu-bound, give 10% to I/O and then redistribute equally among the other two 45 and 45)
MFQ wants to balance all goals (responsiveness - run short tasks quickly, low overhead - spend less time making scheduling decisions, and starvation-freedom - all tasks make progress)
MFQ has multiple RR queue each with a different priority level and time quantum, higher priority preempts and have shorter time quanta than lower levels, every time the task uses up
the time quantum, it drops a level, every time it yields the processor from IO, it stays or moves up a level
Chapter 1: OS is a layer of software that manages a computers resources for its users and apps referee: manage resources, stop programs, isolate applications, allocations
illusionist: abstraction of physical hardware, illusion of nearly infinite memory glue: common services;;;;resource allocation, isolation (error in one shouldnt disrupt others = fault isolation),
communication between apps, virtualization gives illusion of resources that are not physically present. OS as glue lets apps focus on their core tasks and os gives generic interface for
drivers and guis;;;os needs to be reliable- do exactly what its designed to do and available - usable a high percentage, security and privacy PORTABILITY means applications dont
change as hardware changes, has to work with new hardware and hardware that doesnt exist yet, overhead = added resource cost of implementing an abstraction and efficiency = lack
of overhead, response time = how long for single task to run
First operating systems were single user and only for reducing programmer errors -> sharing operating systems with batch, doing queue of tasks, then became multitasking/
multiporogramming multiple program at the same time, full util of CPU-> time-sharing supports interactive use of the computer, handling I/O with interrupts and displays reflect the events
Chapter 2 (kernel): kernel has full access to machine hardware and trusted to do anything, process is the execution of an application program with restricted rightscall stack has a
functions params and local variables, heap has dynamically allocated variables and data has global variables, multiple threads share code, data, and heap, but not call stack PCB stores
where process is in memory, where executable is on disk, what user asked to execute, privilegesdual-mode has user and kernel mode, timer interrupt = kernel regains control, system
call transfers control into kernel for privileged instructions (i.e. adjust memory access, disable and enable interrupts) if an application attempts to access restricted memory or change
privilege level = processor exception, base and bound registers = start and stop privilege, but base-bound doesn't provide expandable heap and stack grows with dynamic and local
variables in opposite directions, memory sharing -> no memory to be shared btw diff processes, physical memory address and memory fragmentation = VIRTUAL ADDRESSES - every
processs memory starts at the same place and hardware translates them to physical memory, with virtual addresses, if multiple copies of program run simultaneously, program prints
exactly the same resulthardware timer interrupts processor after specified delay; reasons for kernel to take control from user process = interrupts, processor exceptions, and system
calls interrupt is asynchronous signal to processor; each type of interrupt requires a handler, could be an I/O interrupt or you could polling looping to see if I/O device has an event
processor exceptions occur when divide integer by zero, attempt write to read-only, or bad address system call is voluntary - send receive packets over network, going FROM kernel to
user mode = new process, resume after an interrupt (restoring program counter, restoring register, change back to user level), switch to different process, or user-level upcall
(asynchronous notify of events interrupt vector table points to handler procedures, interrupt stack holds interrupted process registers, stack pointer, program counter, and processor

status, when restoring, increment instruction to go to next one, each processor needs its own interrupt stack, but sometimes each process has its own kernel interrupt stack -> disable
interrupts only defers interrupts-> for system call, locate parameters and validate, then copy into kernel memory and copy results back into user memory -> upcalls = signal or
asynchronous event can be used for preemptive user-level threads or async i/o or reception handling at the user level, virtualized interrupt/exception to make app be like OSThe one
program running at all times on the computer is the kernel. Bootstrap program is loaded at power-up or reboot Typically stored in ROM or EPROM, generally known as firmware
Initializes all aspects of system Loads operating system kernel and starts executionChapter 3 (programming interface) One or more CPUs, device controllers connect through
common bus providing access to shared
memory;;;I/O devices and the CPU can execute
Schemes
Average Response Time
Throughput
Fairness
Starvation
concurrently Each device controller is in charge
of a particular device type Each device
FIFO
no guarantee, but can be
good, no overhead
in some sense
none
controller has a local buffer CPU moves data
pessimal
from/to main memory to/from
local buffers I/O is from the device to local
Shortest Job First
optimal
can be pessimal
in some sense
longer jobs can have
buffer of controller Device controller informs
starvation
CPU that it has finished its operation by causing
an interrupt A trap is a software-generated
Round Robin
average
not good because of
yes
none
interrupt caused either by an error or a user
context switches, large
request Program is a passive entity, process is
overhead
an active entity OS does the following in
process management: Creating and deleting
Multi-level Feedback
average
low overhead, balanced
scheduler monitors
none
both user and system processes Suspending
Queue
with average response time processes to ensure fair
and resuming processes Providing
share of resources
mechanisms for process synchronization
Providing mechanisms for process
communication Providing mechanisms for deadlock handling;;can implement OS functionality flexibility modify without changing apps UNIX thin waist = system call interface is simple
and powerful, most innovations are in user code, and highly portable (OS new hardware) thin waist because innovations in software and hardware. Now we allow user programs to create
and manage their own processes, shell is a job control system - Windows has a system call: createProcess() which
Task Length
Arrival Time Completion Time Response Time
creates and initializes the PCB in kernel, create
and initialize a new address space, load program
0
85
0
220
220
Task Length
Arrival Time Completion Time Response Time pro into address space, copy args into memory,
initialize hardware to start, inform scheduler a new
1
30
10
40
30
0
85
0
85
85 process is ready -UNIX fork() and exec();;;fork()
creates a complete copy of parent, takes no args
2
35
15
75
60
1
30
10
115
105
and returns an int:;;fork creates and initializes
PCB, create a new address space, initialize
3
20
80
100
20
2
35
15
150
135
address space with parents address space, inherit
4
50
85
150
65
3
20
80
170
90 execution context of parent, and inform scheduler
process is ready, but fork returns twice the parent
SJF
Average:
79
4
50
85
220
135 gets returned the PID of the child, on failure, it
returns -1 to parent the child it returns zero {int
child_pid = fork(); if child_pid == 0 it is child, else it is parent exec() FIFO
Average:
110 loads prog into address space, and copies args
into memory and initializes hardware to start at start() wait wait
for a process to finish signal send a notification
to another process a shell is interactive command interpreter, run in a loop and forks execs for processes, signal() is used for terminating an application or suspect temporarily for debug,
UNIX I/O all have open(), close(), read(), and write() system calls, open always returns a file descriptor, read always has a kernel buffer and blocks until data is available to be read, same
with kernel-buffered writes UNIX pipe is kernel buffer with 2 file descriptors for read and write, stdin and stdout 0 is reserved for standard input 1 is reserved for standard output 2 is
reserved for standard error output, shell forks to execute command and parent waits for child to finish, producer-consumer relationship = output of one program can be input to another
program and communication is one-way producer writes and consumers reads, client-server is two-way;;Windows, Linux, Mac have monolithic kernel, where most of the OS functionality
is inside the OS kernel hardware abstraction layer is interface to machine configuration and processor operations in kernel dynamically loadable device is software to manage a specific
hardware after kernel starts running, but can cause bugs in the OS Ch 4 (threads): threads allow programmer create as many as he wants without worrying about the exact number of
processors, can express logically concurrent task, exploit many processors, manage I/O, and shift work to run in the bg for responsiveness, thread is a sequence that can be run
suspended or resumed at any time by thread schedulerthread is WITHIN a process, each thread runs on a dedicated virtual processor with unpredictable and variable speed, an
interrupt handler is not a thread, it is not independently schedulable, and cannot be interrupted, why is some I/O print not in order, creating and scheduling threads are separate
operations, thread_join checks in order though, thread_exit returns the param as the return value fork-join parallelism has thread create child threads to perform work and wait for their
results, data shared between threads only if parent wrote it or written by child and read by parent TCB has computation and metadataperthread computation has thread star, with local
vars params and return address, each thread needs stack and copy of processors registers in order to suspend a thread, resume a thread store thread registersper-thread metadata
has thread ID, scheduling priority and status shared state is program code, static global variables and dynamic heap variables;;;thread creation puts it in INIT state and then READY
state on the ready list, in READY, register values are stored in the TCB to go form ready to running, put register values from TCB into processor registers, to go from RUNNING back to
READY is thread_yield() or preempted by scheduler, thread_join goes to WAITING state until another thread is ready, or I/O request, thread in FINISHED never runs again; a kernel
thread executes kernel code and modifies kernel registers, to create a thread, you need to allocate per-thread state, initialize per-thread state and
put TCB on the ready list, a thread never deletes its own state when it is finished, another thread dress the state, thread context switch can be
voluntary (i.r. thread_yield fro processor or thread_join) or involuntary interrupt saves the state of the running thread and executes the handlers
code. a switch between kernel threads means there is no need to switch modes/stacks and handler can resume any thread on the ready list;; a
process is more than a thread because it has its own address space heap, code, PCB therefore needs processor registers, each thread has
user level stack, kernel interrupt stack and kernel TCB Chapter 8 (virtual address): segmentation array of pairs of base and bound
registers, virtual addresses go from 0 to bound and physical address go from base to base + bound, the number of segment is determined by
the number of bits for the segment number that are set aside in the virtual address, segmented memory has gaps, program memory is a set of
regionshigher order bits of the virtual address are used to index into the array, the rest of the address is added to the base and checked
against the bound at that index. If a program branches into or tries to load data from one of these gaps, hardware generates an exception
segmentation fault if programs are sharing code, you can share some regions of memory but protect others Internal fragmentation is the
wasted space within each allocated block because of rounding up from the actual requested allocation to the allocation granularity. External
fragmentation is the various free spaced holes that are generated in either your memory or disk space. External fragmented blocks are available
for allocation, but may be too small to be of any use. Internal fragmentation occurs when the last allocation unit is not full. External
fragmentation occurs when space is wasted between two allocation units. In a paging system, the wasted space in the last page is lost to
internal fragmentation. In a pure segmentation system, some space is invariably lost between the segments. This is due to external
fragmentation. Page memory means memory is allocated in fixed-sized chunks called page frames. Page frames are fixed-sized and power of
2
Q: A computer with a 32-bit address uses a two level page table. Virtual addresses are split into a 9-bit top-level page table field, an 11-bit
second-level page table field, and an offset. How large are the pages and how many are there in the virtual address space?
A:Twenty bits are used for the virtual page numbers, leaving 12 over for the offset. This yields a 4K page. Twenty bits for the virtual page implies
2^20 pages.
Q:A machine has 48-bit virtual addresses and 32-bit physical addresses. Pages are 8K. How many entries are needed for a conventional page
table? For an inverted page table?
A:With 8K pages and a 48-bit virtual address space, the number of virtual pages is (2^48)/(2^13), which is 2^35 (about 34 billion). An inverted
page table needs as many entries as there are page frames in memory, in this case, 524,288. Clearly, this is a lot more manageable.
Virtual address under paging 4 bit | 10 bit (virtual page number | page offset) If page offset is 10 bits long, how big is a page? 2^10 bytes, how many pages can each process have? 2 ^ 4
(page number), max memory space for each process is 2^14 PageTable[virtual page # in virtual address]. Paged memory management, physical memory is allocated in the unit of the
page frame (eg. 1024kb, 2048kb 2^10 is 1024 bytes since kilobyte is 1024 4 kb is 4 * 2^10 or 2^2 * 2^10) page frame size is always 2th power
paged segmentation = memory is segmented, but each table entry point to a page table, which point to the memory backing that segment
20 base 16 -> convert to binary = 00100000 pad the zeros, the 0000|000000100000 then look at table, decimal representation.

You might also like