4.2 1) Store the register state of the thread, including the stack pointer and program counter, somewhere in memory. 2) Choose a new thread to be run, based on the system's scheduling policy 3) Load the new thread's data (stack pointer, PC, etc.) into the appropriate registers/memory locations 4.3 A multi-threaded program gains performance when the program has significant I/O (e.g. waiting for user input) while there is useful work elsewhere (e.g. calculating some value). It can perform this work while waiting for the I/O. 4.4 Heap memory and global variables. 4.8 If we assume that the program has enough concurrency to utilize all of the processors, then: a) This case will have poor performance, since we can never utilize all the processors on the system, and thus run at a fraction of our possible rate, especially for CPU-bound processes. b) CPU-bound processes will achieve their maximum performance (since all available processing power is utilized), but if the program has any I/O, we might waste time have a particular kernel thread block on I/O and thus have an idle processor c) This fixes case b) above, as we can now schedule a backup kernel thread when another blocks on I/O, so we should see the highest performance across applications with some I/O. 5.1 Since I/O bound programs typically utilize the CPU for extremely short bursts and then block on I/O. Thus is is important to give them a higher priority to run to increase the response time of the system. If we scheduled CPU-bound processes at an equal or higher priority, we might take a double hit in response time: we have to wait for a long CPU-bound burst and _then_ for the I/O. 5.2 a) One way to increase CPU utilization is to minimize context switches, which waste CPU time. We can minimize context switches by increasing the time quantums for each process, but this reduces response time. b) This is basically the argument over shortest-job-first scheduling. SJF minimizes average wait time (and thus average turnaround time) at the expense of maximum wait time, since certain processes might starve indefinitely and thus increase the maximum wait time. c) Maximizing I/O utilization means careful scheduling and more interrupts, and thus more context switches and lower CPU utilization. 5.5 Shortest job first and priority scheduling can result in starvation, because there can always be a shorter job or job with higher priority in the queue.