1. Answer the following questions true or false:
a. An operating system can be viewed as a “resource allocator” to
control various I/O devices and user programs.
b. The following instructions must be protected to ensure that a
computer system operates correctly: change to monitor mode,
read from monitor memory, write into monitor memory, and turn
off timer interrupts.
c. I/O instructions and turning interrupts on are not generally
considered to be privileged instructions.
d. Deadlock can be prevented in the dining philosophers problem
by simply reducing the number of philosophers that are allowed
to eat at the same time by one.
e. On a uniprocessor system, the critical section problem can be
solved simply by disabling interrupts while a shared variable
is being modified.
f. A thread is generally more lightweight than a process because
threads have their own virtual address spaces while processes
may have shared address spaces.
g. A deadlock cannot arise for a set of processes unless there is
a circular wait condition.
2. You are to implement the OS2000 timer interrupt handler tint() for
the timer interrupt mechanism used on the x99 hardware architecture.
x99 has two 64-bit hardware registers, a COUNT register and a
COMPARE register. COUNT is initially zero and COMPARE is
initially 1000. Every microsecond, x99 increments COUNT by one
and compares the value of COUNT with COMPARE. If the values are
equal, the x99 hardware generates a timer interrupt, which calls
tint(). To do proper OS2000 scheduling, tint() needs to increment
a global variable TICK by one every millisecond. To do this,
tint() must read and write COUNT and COMPARE to ensure that a
timer interrupt is regularly generated. Register reads and writes
are atomic, but there is no atomic read-then-write operation.
a) Consider the following tint() implementation. Every time the
timer interrupt goes off, tint() increments TICK by one and
resets COUNT to zero. COMPARE is left unchanged. Will this
approach generate a timer interrupt every millisecond?
Explain why or why not.
b) Explain in English a more robust method than the one used
in part a for updating the hardware registers to generate a
timer interrupt every millisecond. You can assume that tint()
requires less than a millisecond to execute, so long as it
does not use a divide operation. For this part of the
problem, you can also assume that all interrupts are disabled
while tint() executes (i.e. if any other interrupts occur,
they will not be handled until after tint() completes).
c) You are now told that due to a new change in x99, there are
high priority interrupts that cannot be disabled and may go off
and “preempt” tint() while it is executing. These interrupts
occur infrequently, but may require more than a millisecond to
process. Using pseudo-C, write a correct implementation of
tint() that accounts for the fact that other interrupts may go
off and delay the completion of tint(). If multiple
milliseconds elapse before tint() completes, TICK should be
incremented to account for each millisecond.
3. Give short answers to each of the following questions.
a) What is the difference between fork and clone in
Linux?
b) What is the difference between maskable and non-maskable
interrupts?
c) What is the difference between a thread and a process?
d) What is the difference between kernel mode and user mode?
4. Write a new Linux 5.4 system call pinfo() that takes a PID
and a pointer to struct proc_struct as its arguments, and
populates the structure with the process state information for
that process. The system call should be numbered 436. The
prototype of the system call will be:
int pinfo(pid_t pid, struct proc_struct *proc);
Assume a pid_t is defined as an int. Assume that struct
proc_struct is defined in a file already as:
struct proc_struct {
pid_t pid; /* id of process */
pid_t parent_pid; /* process id of parent */
long nice; /* process nice value */
}
a) Write the C code for your system call function and show any
other changes that need to be made to the Linux kernel code to
allow your system call to be called from a user program. Your
code should work properly on an x86 multiprocessor system.
Your system call should return 0 if it is able to locate the
process information for the target pid and fill in the
information successfully. Otherwise, it should return -1.
b) Write a simple C program that calls your system call and
prints the result.