Here is the code for Problem 50
2. I suspect that hardware will have to manage everything on process switching that the Operating Systems used to do before, namely process table management, process scheduling, etc. The hardware only needs to give CPU a process identification (pid) of a specific process to be executed. The CPU in this case does not do anything except receiving the 'pid' from hardware and executing the given process accordingly. Process switching in hardware may be faster than its software counterpart but it is not so flexible. For example, changing an algorithm, say scheduling algorithm, will not be so easy and may be costly.
6. The register set is listed as per-thread rather than a per-process item because each thread has some registers which hold its current working variables. Even though there is only one set of registers each thread has its own program counter (PC), stack pointer (SP), and other processor-specific register contexts that are not shared with any other process/thread and are flushed out after the thread is executed and so the registers are available for use in some other process/thread.
10. A thread is never preempted by a clock interrupt because is that were to happen then the properties of that thread like it's program counter, stack pointer, registers, state, etc. will not be stored in the thread table and hence the information needed to restart the thread would be lost. A thread is preempted only when a higher-priority thread is placed on the ready queue (it becomes READY, as the result of its block condition being resolved). The preempted thread remains at the start of the ready queue for that priority and the higher-priority thread runs.
14. If a clock interrupt occurs while some thread is executing in the run-time system then obviously enough the thread will stop before completion. The properties of that thread like it's program counter, stack pointer, registers, state, etc. will not be stored in the thread table and hence the information needed to restart the thread would be lost. A nice way to get around with this problem would be to disable or ignore the clock interrupts.
18. In shared-memory parallel programs that use explicit synchronization, race conditions result when accesses to shared memory is not properly synchronized. In this condition two or more processes read or write some shared data, or share common resources such as printing queue, memory, I/O devices, and the final result depends on who runs precisely when. Here not all of the processes manage to complete execution and the one that executes completely wins the "race". Race conditions lead to behavior that is not reproducible. Therefore, it is hard to debug when it happens.
22. Yes, a SWAP instruction that swaps the contents of a register and a memory word in a single indivisible action can be used to write the routine enter_region. Let us see how:
MOVE REGISTER, #1 | store 1 in register
enter_region:
SWAP REGISTER, LOCK | swap the data in register and lock
CMP REGISTER, #0 | was lock zero?
JNE enter_region | if it was non-zero, lock was set, so loop
RET | return to caller; critical region entered
26. The problem of looping forever does not occur if the round-robin scheduling is used instead of priority scheduling. In round-robin scheduling all processes are assumed to be equally important and each process is assigned a time interval, called its 'quantum', which it is allowed to run. So whether its process H, with high priority, or process L, with low priority, it gets same amount of time and equal chance to run. It follows that if H gets ready to run when L is in its critical region (H begins busy waiting), then after the quantum for H is over, L resumes running and leaves its critical region. As a result when H resumes running it enters the critical region and hence does not loop forever.
30. This does not lead to a race conditions because at some later time space is available for sending a message (in once full mailbox) or message is available to be received (from once empty mailbox). At that time a message is sent or a message is received (as per the case) by that process (amongst those competing to send or receive message) that starts running right after space in the mailbox becomes available or message in the mailbox becomes available (as per the case). After this the mailbox might become full again or empty again (as per the case), and the remaining processes keep trying until they succeed too.
34. Time needed for the process to complete would be (T*n) seconds.
38. CPU efficiency is the ratio of the useful CPU time and the total CPU time. Hence we do the calculations as follows:
(a) When Q = infinity, the basic cycle is for the process to run for time T and undergo a process switch for time S. Thus CPU efficiency is T/(S + T).
(b) When Q > T, again the basic cycle is for the process to run for time T and undergo a process switch for time S. Thus CPU efficiency is again T/(S + T).
(c) When S < Q < T, we notice that time Q is less than time T, so the process will involve T/Q process switches, hence the total time wasted would be (S)(T/Q). Thus CPU efficiency is T/(T + ST/Q), which reduces to Q/(Q + S).
(d) When Q = S (directly means that Q < T), we just substitute S for Q in the CPU efficiency for part (c). Thus CPU efficiency is S/(S+S) = S/2S = 0.5, or in other words the CPU efficiency is 50%.
(e) When Q is nearly equal to zero (directly means that Q < T), we just substitute 0 for Q in the CPU efficiency for part (c). Thus CPU efficiency is 0/(0+S) = 0/S = 0, i.e. the efficiency is nearly equal to 0. It can be noted that in this case there are infinite number of process switches, hence infinite amount of time is wasted and that is the reason why the CPU efficiency is nearly zero.
42. One way to save the CTSS priority system from being fooled by random carriage returns would be to increase the priority of a process only when the user completes a line while the process was blocked waiting for keyboard input. The program should read the line and only raise the priority if the user types those characters in between carriage returns that make syntactic sense.
46. The policy and mechanism for scheduling of kernel threads can be separated by parameterizing the scheduling algorithm in some way, and allowing the user to fill in the parameters. Such a scheduling algorithm should be able to do the full context switch, change the memory map, etc.