CS444 Final Exam, Dec. 16,
2003 NAME:_____Solution______________________
Open books, notes, handouts.
Write on these pages, using the backs if need be (I hope not.) Each problem is worth 30 points. I’ll drop
the lowest-score problem.
1.
Short answer.
a.
Describe two ways
the kernel code can stop the UART transmitter interrupts from happening while a
program is running on an x86 system.
Disable Tx interrupts in the UART via its IER register
Mask its IRQ in the PIC
Do cli to make IF=0 in the CPU’s EFLAGS register
b.
In user-level producer
consumer using three semaphores (for example the program on pg. 120, or
prodcons.c of hw5), suppose the shared buffer can hold 10 elements. What are the maximum counts in each of the
three semaphores to use all 10 spots, but no more?
10, 10, and 1 (for mutex semaphore)
c.
Suppose a file
has 100 file data blocks. If it’s a FAT
(File Allocation Table) file, how many disk-block accesses are needed to
determine the last byte in the file if the FAT table is filled in for it? 1 If no information for this file is in the
table? 100
d.
Suppose a page
fault occurs on a code page for a process.
Where will the OS find the data (program code) for the page? from the program’s
executable file What action by
the scheduler will soon happen for this process? sleep call/ block
process
2.
Deadlocks. Suppose there are two resources R and S, and
three processes A, B, and C, and:
process
A holds T, wants R
process
B holds R, wants S
process
C holds nothing, wants R and S
Draw the resource allocation
graph and determine if there is a deadlock.
If so, what processes are involved?
If not, show how the processes can “unwind”, i.e., finish execution in
some order.
|T| -> (A) -> |R|
à (B) à |S|
^
^
|
|
|-----(C)
----|
Unwinding: B gets S, finishes, releases locks on R and S
A gets R,
finishes, releases locks on R and T
C gets R and S,
finishes.
3. System Call Mechanism. In hw2, hw3, and hw5,
and also in Linux, a system call and related execution has the following steps:
1.
call assembly
language function for system call
2.
load system call arguments
in registers, system call # in EAX
3.
start executing
int $0x80
4.
save EFLAGS, EIP
on stack (also CS)
5.
load EIP from
IDT[0x80]
6.
execute the
assembler syscall handler, save registers
7.
execute the C
syscall handler
8.
execute the
assembler syscall handler body, restore registers
9.
execute the iret
instruction
10. execute the next instruction after the int $0x80
a.
Which steps are
part of the trap cycle of the CPU, (and thus involved in the transition from
user to kernel mode under Linux)?
4,5
b.
Which step, when
executed under Linux, involves a transition from kernel mode to user mode?
9
c.
Which steps, when
executed under Linux, are running in user mode in the CPU?
1, 2, 3, 10
d.
Which steps, when
executed under Linux, are running in kernel mode in the CPU?
6, 7, 8, [9] (9 returns
execution to user level, so is somewhat marginal in classification)
e.
Which step could contain
a call to a device driver (hw’s or Linux)?
7
f.
Which steps would
also be in a list like this for handling an interrupt? (Replace “syscall” with
“interrupt” in the steps above to answer this.)
4, 5 with 0x80 replaced by interrupt vector number, 6, 7, and 8
(with syscall replaced by “interrupt”), 9
4.
Scheduling.
Consider the execution of the hw3 kernel with its non-preemptive scheduler with
the following programs, which are nearly the same as the standard test programs
except for the number of A’s that main1 outputs, and main3, which computes as
well as outputting c’s.
int
main1()
{
int sum = 0; int i;
write(TTY1, “aaaaaaaaaaa”, 10);
write(TTY1, “zzz”, 3);
for (i=0;i<100000000;i++)
sum
+= i*i; /* suppose this takes 40ms to
run */
write(TTY1, “AAAA”, 4);
}
int
main2()
{
write(TTY1,”bbbbbbbbbb”, 10);
}
int
main3()
{
int sum = 0; int i;
for (i=0;i<100000000;i++)
sum
+= i*i; /* suppose this takes 40ms to
run */
write(TTY1, “cccc”, 4);
}
The
output from the run using hw3’s kernel is simply aaaaaaaaaazzzAAAAbbbbbbbbbbcccc
a.
What output is
showing when main1 exits? (Don’t forget
write-behind)
aaaaaaaaaazzz
(AAAA is in the output queue, but zzz has had plenty of time to get
output)
b.
What output is
showing when main2 exits?
aaaaaaaaaazzzAAAAbbbb
(bbbbbb is in the output queue.
Recall the output queue holds 6 bytes.)
c.
Does process 1
ever block? When or why not?
Yes, when it has put 6 a’s in the output queue, it first
blocks. Then it blocks on each following
a and each of the three z’s. But the old
output has drained by the time the A’s are enqueued, so all four are put in the
output queue without blocking.
d.
Does process 3
ever block? When or why not?
No, the loop allows the output to drain, so the 4 c’s are
enqueued without blocking.
e.
How would this
trio of user programs run under hw5, with its preemptive scheduler? Show the expected debug_log, with preemptions
and ticks showing at well as output. You
don’t need to show the ~’s, but may if you want.
Showing output insead of ~’s:
aaaaaa*3*3*3*3|(3-1)aaaazz|(3z-1)ccccz*1*1*1*1|(1-2)bbbbbb|(1z-2)AAAA|(2z-0)bbbb
There are other possibilities, but there should be 4 ticks with
*1 and 4 with *3, each followed by a preemption of that process. Process 3 will be the first to go into a
loop, because it will be ready when the others are blocked on their output.
5.
Mutex System Calls. Suppose we want to add a
user-level mutex service to nonpreemptive tiny UNIX (hw3).
a.
Suggest an
appropriate set of new system calls for this service. Also give the appropriate names for the
kernel functions that implement each system call.
One possible set:
syscall mutex_create with
kernel function sys_mutex_create
syscall mutex_destroy with kernel function sys_mutex_destroy
syscall mutex_lock with kernel function sys_mutex_lock
syscall mutex_unlock with kernel function sys_mutex_unlock
b.
Explain in what
functions the scheduler functions sleep() and wakeup() would be called.
mutex_lock calls sleep, mutex_unlock calls wakeup
c.
Would you use cli() and sti() (or set_eflags()) around the call to sleep? Discuss this decision.
Yes, callers of sleep are expected to ensure IF=0 at the call to
sleep, and system call functions are called with IF=1, so cli() is needed
before the call to sleep and sti or set_eflags after. We know that sleep will call scheduler, and
scheduler will choose another process to run, and this process will enable
interrupts as appropriate, so they will not be off for long.
6.
x86 Paging. The
first few PTEs of the SAPC’s only page table look like this, after a reboot:
Address Contents
0x52000 0x00000007
0x52004 0x00001007
0x52008 0x00002007
0x5200c 0x00003007
a.
What is the relationship between VA and PA described here? For what range of VAs?
This shows that VA = PA for 0 <= VA <= 0x3fff. (These are the first 4 PTEs, handling the
first 4 pages of VA space on the SAPC.)
b.
What Tutor
command would you use to make page 3 read-only?
ms 5200c 00003005 or any
command that turns off bit 1 of byte 5200c
c.
How would you
change this page table to make an access to VA 0x2056 cause a page fault? (What
new value for what address?)
This is a page 2 address, so change PTE2, which is at 0x52008:
ms 52008 00000000 or
any command that turns off bit 0 of byte 52008.