Spring 04-05 ECOM 4416: Operating Systems Concepts Final Exam Duration: 2 hours Student ID: __________________ Student Name: __________________ ECE Department IUG- Faculty of Engineering Dr. M. Mikki Eng. Hasan Qannou' Eng. Mohammed El-Shekh-Ali Grade:__________ Notes to students: 1. There are 6 questions and 8 pages in total (including this cover sheet) for this exam. 2. There are 100 points possible 3. Budget your time appropriately. 4. Write your name and student ID at the top of the first page. 5. In general, show your intermediate work and BRIEFLY state your assumptions where appropriate. 6. Write clearly and legibly. If we can't read your answer, we can't grade it. 7. Read the questions carefully and answer the question that is being asked. Question 1 1. (7 pts) Circle “T” if the statement is always true. Otherwise circle “F”. 1 2 3 4 5 6 7 In paging systems, external fragmentation cannot occur Race conditions cannot occur on a uni-processor SJF can be implemented as a priority algorithm, where the priority is determined by the arrival time of the job. Hardware support is needed to synchronize more than two processes It is possible for a single process to deadlock with itself Minimizing turnaround time is the most important criteria in choosing a scheduling algorithm for an interactive system With dynamic partitioning, all memory allocated for a process must be contiguous T/F T/F T/F T/F T/F T/F T/F 2. (5 pts) A DECSYSTEM-20 computer has multiple register sets. Describe the actions of a context switch if the new context is already loaded into one of the register sets. What else must happen if the new context is in memory rather in a register set, and all of the register sets are in use? Ans: (Pg. 103) Changing pointers to the current register set. If a new context is in memory: Swapping Copy register data first into a register set. 1. Question 2 (6 pts) Explain the differences in the degree to which the following scheduling algorithms discriminate in favor of short processes: a. FCFS Answer: Neutral, does not consider burst time of jobs b. RR Answer: Discriminates against long processes. If a process is longer than the time slot of the CPU, it has to be preempted, and go to the end of the queue. Number of \feedbacks a process has to make is directly proportional to the length of the process. c. Multilevel feedback queues 2. (8 pts) Many CPU scheduling algorithms are parameterized. For example, the RR algorithm requires a parameter to indicate the time slice. Multilevel feedback queues require parameters to define the number of queues, the scheduling algorithms for each queue, the criteria used to move processes between queues, etc. These algorithms are thus really sets of algorithms (e.g., the set of RR algorithms for all time slices, etc.). One set of algorithms may include another (in lecture, we talked about using Priority Scheduling to implement SJF). What, if any, relation holds between the following pair of algorithms? a. Priority and SJF. b. Multilevel feedback queues and FCFS. c. Priority and FCFS. d. RR and SJF. 2 Question 3 1. Consider a paging system with the page table stored in memory. a. (3 pts) If a memory reference takes 200 nanoseconds, how long does a paged memory reference take? Solution Teffective= fff b. (3 pts) If we add TLBs, and 75 percent of all page-table references are found in the TLBs, what is the effective memory reference time? (Assume that finding a page-table entry in the TLBs takes zero time, if the entry is there.) 2. (4 pts) Explain why it is easier to share a reentrant module using segmentation than it is to do so when pure paging is used. 3. (10 pts) A system has a 32-bit virtual address space and uses a two-level page table. 9 bits are used to index the top-level page table, and 11 bits are used to index the second-level page table. a) How large are the pages (in bytes)? b) How many virtual pages can the process have? c) What is the size (in bytes) of an entry in the second-level page table, assuming the second-level page table is stored in a single physical page frame? d) If each page table entry includes valid, reference, and dirty bits in addition to the page frame number, what is the maximum number of physical page frames in the system? 3 e) Assuming the page size is fixed, how can the address translation scheme be altered to support more physical page frames? 4 THIS PAGE IS LEFT EMPTY INTENTIONALLY 5 Question 4 1. (8 pts) A file system is the data structure that holds files and directories. a. Is it possible to have two file systems on a single physical disk drive? Why or why not? b. Is it possible to have a file system that spans two physical disk drives? Why or why not? c. Is it possible to have a file that is not in a file system? Why or why not? d. The mount operation allows you to graft the directory tree from one file system onto the directory tree of another file system. Does this mean that a file can span both file systems? Why or why not? 2. Consider a dynamic partitioning system in which memory consists of the following holes, sorted by increasing memory address (all sizes are in Kilobytes): 10 4 18 9 20 7 12 15 Hole created by last allocation (a) (8 pts) Suppose a new process requiring 11 kB arrives, followed by a process needing 9 kB of memory. Show the list of holes after both these processes are placed in memory for each of the following algorithms (start with the original list of holes for each algorithm). i) First Fit: (uses 18 then 10) 4 9 20 7 12 ii) Worst Fit: (uses 20 then 18) 10 4 9 7 12 iii) Best Fit: (uses 12 then 9) 10 4 18 7 12 iv) Next Fit: (uses 15 then 10) 4 18 9 20 7 15 15 15 15 (b) (2 pts) Keeping the hole list sorted by size can make some of the allocation algorithms faster. State one advantage of keeping the list sorted by address instead. 6 THIS PAGE IS LEFT EMPTY INTENTIONALLY 7 Question 5 1. ( 8 pts) For a multi-threaded process, indicate whether each of the following items should be part of the process descriptor (P), the thread descriptor (T), or both (B): a. Stack pointer b. Priority c. Page table d. Resource usage accounting P/T/B P/T/B P/T/B P/T/B 2. ( 4 pts) What is the primary motivation for two-level page tables? 3. (4 pts) Why is it better for disk scheduling to be performed by the disk controller itself, rather than by the operating system? 4. (4 pts) What is the difference between a race condition and deadlock? 8 Question 6 Answer yes or no, or with a single term or phrase, as appropriate. 1. (2 pts) Does the test-and-set instruction need to be a privileged instruction? 2. (2 pts) A program containing a race condition will always/sometimes/never result in data corruption or some other incorrect behavior? 3. (2 pts) A system that meets the four deadlock conditions will always/sometimes/never result in deadlock? 4. (2 pts) A resource allocation graph that has a cycle in it always/sometimes/never means that there is a deadlock? 5. (2 pts) Can the system call instruction be a privileged instruction? 6. (2 pts) Round-robin scheduling always/sometimes/never results in more context switches than FCFS? 7. (2 pts) What are the two components of a virtual address used in segmented virtual memory? 8. (2 pts) The layout of virtual pages for a virtual address space is always/sometimes/never contiguous in physical memory? 9 1. (4 pts) Potpourri: Answer yes or no, or with a single term or short answer, as appropriate. You should go through these quickly, answering with the first answer that comes to mind — it probably is the correct one. Only dwell on ones you are unsure of after finishing the other questions. (a) A resource allocation graph that has a cycle in it always/sometimes/never means that there is a deadlock? sometimes (see the example in deadlock lecture) (b) Can the system call instruction be a privileged instruction? no – if it is, then user programs cannot invoke kernel operations (c) In what Nachos file was the Semaphore class implemented? synch.cc (d) Round-robin scheduling always/sometimes/never results in more context switches than FCFS? sometimes – if every job has an execution time less than the quantum, then it has the same number as FCFS. 10 Question 2. (15 pts) Give brief answers to each of the following questions. (a) What is the purpose of system call instructions, and how do they work? Give two examples of common system calls. System call instructions enable user programs to invoke operations in the kernel. System call instructions cause an exception, which causes the CPU to vector into the OS. The OS saves the process state, detects that it is a system call exception, identifies the system call number from the argument to the instruction, and invokes the system call routine. When the routine finishes, the OS restores the process state and returns from the system call. Two common examples are read() and write(). (b) What is the difference between interrupts and exceptions? Give two examples of each. Interrupts are asynchronous events external the CPU (e.g., timer interrupt, device interrupt). Exceptions are synchronous events that occur as the result of executing instructions (e.g., divide by zero, system call). (c) What is the difference between fork() and exec() on Unix? fork() creates a new process and copies the address space from the parent into the new child process. exec() stops executing the program in the process, overwrites it with a new program, and starts executing the program at the beginning; exec() does not create a new process. (d) What is the difference between a race condition and deadlock? A race condition is caused by more than one thread accessing shared state without synchronization. Threads continue to execute, but the program can have incorrect results. In a deadlock, threads cannot make any progress. They are all waiting to acquire resources that each other holds (circular wait) while the three other deadlock conditions hold. (e) What is the difference between Thread::Yield() and Thread::Sleep()? Yield() places the current thread on the end of the ready list, and context switches to another thread. Sleep() halts the current thread and context switches to another thread. In particular, Sleep() does not put a thread on a wait list (other code has to do that since Sleep() does not know which list the thread should wait on). 3 11 Question 3. (6 pts) Round-robin schedulers (e.g., the Nachos scheduler) maintain a ready list or run queue of all runnable threads (or processes), with each thread listed at most once in the list. What can happen if a thread is listed twice in the list? Briefly explain how this could cause programs that use synchronization primitives to break on a uniprocessor. The problem is that a thread on the ready list twice results in a spurious wakeup. Consider a thread executing the PingPong procedure in the lecture notes. If a thread is on the ready list twice, then the first time it runs on the CPU it will execute inside of PingPong and eventually Wait on the condition variable. But, since it is on the ready list twice, it will run again, without any other thread having called Signal on the condition variable. This could, for example, cause that thread to print twice in a row, violating the problem constraints. The most common error on this problem was to think of the thread on the list twice as two different threads, with two different stacks, etc. Although this is not accurate, I still gave partial credit when an answer with this interpretation demonstrated a synchronization problem. 4 12 Question 4. (15 pts) The table below lists five jobs, the time that they arrive in the system (when they are created), how long they take to execute, and their priority (higher values correspond to higher priorities). For example, job arrives at time “10”, requires “30” units of execution time to complete, and has priority “1”. _ Job Arrival Time Execution Time Priority A 10 30 1 B 20 50 5 C 30 10 3 D 40 40 2 E 50 20 0 For all jobs in each of the following scheduling algorithms, calculate (a) the Start Time, the time at which the job is first scheduled to run (it may have to wait when it arrives), and (b) the End Time, the time when it finishes executing. (a) First Come First Serve (FCFS) Job Start Time End Time A 10 40 B 40 90 C 90 100 D 100 140 E 140 160 (b) Shortest Job First (SJF) Job Start Time End Time A 10 50 B 110 160 C 30 40 D 70 110 E 50 70 (SRTF) Job Start Time End Time A 10 40 B 110 160 C 40 50 D 70 110 E 50 70 (c) Priority Job Start Time End Time A 10 140 B 20 70 C 70 80 D 80 120 E 140 160 5 13 Question 5. (15 pts) Consider the following test program for an implementation of locks and condition variables in Nachos. It begins when the “main” Nachos thread calls ThreadTest(). Trace the execution of this program until it prints out the message “STOP HERE” and (a) write down the sequence of context switches that occurred up this point, (b) the output of the program, and (c) list the queues that the threads are on at this point, and their relative order if more than one thread is on a queue (currentThread, the readyList, and any wait queues associated with synchronization primitives). For example, “A B” signifies that thread A context switches to thread B, and “readyList: A” signifies that A is on the ready list. Assume that the scheduler runs threads in FIFO order with no preemptive time-slicing (nonpreemptive scheduling), all threads have the same priority, and threads are placed on wait queues in FIFO order. _ Lock *pumpkin; Condition *cv; void A(int arg) { pumpkin->Acquire(); printf(‘‘giddy’’); cv->Wait(pumpkin); printf(‘‘gaddy’’); currentThread->Yield(); cv->Signal(pumpkin); pumpkin->Release(); } void B(int arg) { pumpkin->Acquire(); printf(‘‘goody’’); cv->Signal(pumpkin); currentThread->Yield(); printf(‘‘geddy’’); cv->Wait(pumpkin); pumpkin->Release(); } void ThreadTest() { Thread *t; pumpkin = new Lock("l"); cv = new Condition("cv"); t = new Thread("A"); t->Fork(A, 0); currentThread->Yield(); t = new Thread("B"); t->Fork(B, 0); currentThread->Yield(); currentThread->Yield(); printf(‘‘STOP HERE\n’’); } (a) Context switches: main Amain _ _ _ 14 Bmain ABmain (b) Output: giddy goody geddy (c) Thread queues at “STOP HERE”: currentThread: main readyList: A pumpkin: cv: B The one subtlety to this problem is at the end. When A is woken up from waiting on the condition variable, it does not immediately return. Instead, it first tries to reacquire the lock (that is held by B), gets placed on the lock’s wait queue, and finally placed on the ready list when B finally calls wait (but A never does run again). 6 6. (15 pts) Because his house is so popular on Halloween, Greg Ghoul likes to hand out Halloween candy in the following way. Each trick-or-treater coming to his door takes a single “ticket” with a number from a ticket machine on his porch. The ticket numbers dispensed are guaranteed to be unique and sequentially increasing. When Greg is ready to give candy to the next trick-or-treater, he calls out the “candycount”, the lowest unserved number previously dispensed from the ticket machine. Trick-or-treaters wait until the candycount reaches the number on their tickets. Greg waits until the trick-or-treater with the ticket he called comes forward with their bag held open before giving out candy. Show how to implement Greg() and trick-or-treater() procedures to solve this problem using locks and condition variables. Represent calling out the “candycount” by printing out its value in the appropriate place in Greg(). In addition, print out a message in trick-ortreater() when the trick-or-treater gets candy and print out a message in Greg() when Greg gives out candy. _ _ _ _ // shared variables Lock mutex; Condition candy, greg; int candycount = 0, ticketcount = 0; void Greg() { mutex->Acquire(); while (1) { printf("Candy for %d!\n", candycount); candycount++; candy->Broadcast(&mutex); greg->wait(&mutex); printf("Gave away the candy!\n"); } 15 mutex->Release(); } void trick-or-treater() { int myTicket; mutex->Acquire(&mutex); myTicket = ticketcount++; while (myTicket != candycount) { candy->Wait(&mutex); } printf("Treater %d got candy!\n", myTicket); greg->Signal(&mutex); mutex->Release(); } 7 16 CSE 120 Principles of Computer Operating Systems Fall Quarter, 2001 Midterm Exam Instructor: Geoffrey M. Voelker Name Student ID 1. (10 pts) Potpourri: Answer yes or no, or with a single term or short answer, as appropriate. You should go through these quickly, answering with the first answer that comes to mind — it probably is the correct one. Only dwell on ones you are unsure of after finishing the other questions. (a) Does the test-and-set instruction need to be a privileged instruction? No, it can be executed at user level. (b) What approach to dealing with deadlock does the Banker’s algorithm implement? Avoidance. (c) Which of the following scheduling algorithms can lead to starvation? FIFO, Shortest Job First, Priority, Round Robin SJF, Priority (d) A program containing a race condition will always/sometimes/never result in data corruption or some other incorrect behavior? Sometimes...just because a race condition exists in code does not mean that a particular execution will encounter it. (e) A system that meets the four deadlock conditions will always/sometimes/never result in deadlock? Sometimes. 2 17 2. (6 pts) Categorize the following as one of the following: (I) interrupt, (E) exception, or (N) neither. (a) Timer – (I) (b) Segmentation violation – (E) (c) Keyboard input – (I) (d) Divide by zero – (E) (e) Procedure call – (N) (f) System call – (E) 3 18 3. (9 pts) Discuss the tradeoffs between user and kernel threads. (a) What are the advantages and disadvantages of each? (b) Assume we can make system calls as fast as procedure calls using some new hardware mechanism. Would this make one kind of thread clearly preferable over the other? Explain briefly. (a) See slides 11-15 in Lecture 4. (b) Kernel threads would be preferable. The primary disadvantage of kernel threads is the overhead of trapping to the kernel to manipulate them, context switch, etc. Some people mentioned that kernel threads still have the problem of having to be generic to all application needs, which is a good observation and I gave points for this. 4 19 4. (15 pts) The Coronado Bridge is undergoing repairs and only one lane is open for traffic. To prevent accidents, traffic lights have been installed at either end of the bridge to synchronize the traffic going in different directions. A car can only cross the bridge if there are no cars going the opposite direction on the bridge. Sensors at either end of the bridge detect when cars arrive and depart from the bridge, and these sensors control the traffic lights. Below is a skeleton implementation of two routines, Arrive() and Depart(). You may assume that each car is represented by a thread, and threads call Arrive() when they arrive at the bridge and Depart() when the leave the bridge. Threads pass in their direction of travel as input to the routines. int num_cars = 0; enum dir = {open, north, south}; dir cur_dir = open; void Arrive (dir my_dir) { A.-1 lock->Acquire(); A.0 while (cur_dir != my_dir || cur_dir != open) { cv->Wait(lock); } A.1 num_cars++; A.2 cur_dir = my_dir; A.3 lock->Release(); } Lock *lock = new Lock(); Condition *cv = new Condition(); void Depart (dir my_dir) { D.-1 lock->Acquire(); D.0 num_cars--; D.1 if (num_cars == 0) { D.2 cur_dir = open; cv->Broadcast(lock); D.4 } D.5 lock->Release(); } (a) The code above does not have any synchronization statements. Outline an execution sequence (referring to the numbered statements) where two threads can cause two cars to travel on the bridge in opposite directions at the same time. Thread 1 (north): A.0, A.1 (context switch) Thread 2 (south): A.0, A.1 and now we have two threads on the bridge in opposite directions. (b) Show how a condition variable and lock could be used to correctly synchronize the cars by annotating the above routines with calls to Condition and Lock operations. See above. (c) Draw brackets around the sections of code that are critical sections. Lines A.-1 – A.3, D.-1 – D.5. (d) Can this solution lead to starvation? Briefly explain. Yes. Once cars start moving in one direction, they will starve out cars waiting to go in the other 20 direction indefinitely (as long as more cars continue to arrive in the first direction). (e) Can this solution lead to deadlock? Briefly explain. No, not all of the deadlock conditions are met (e.g., no circular wait). In specific terms, for example, there is no way for cars going in both directions to wait at the same time. 5 21 5. (15 pts) Consider the following test program for an implementation of Join in Nachos. It begins when the “main” Nachos thread calls ThreadTest(). You do not need to know the details of how Join is implemented. All you need to know is that when a “parent” thread calls Join on a “child” thread, the “parent” does one of two things: (1) if the “child” is still running, the “parent” blocks until the “child” finishes (at which point the “parent” is placed on the ready queue); (2) if the “child” has finished, the “parent” continues to execute without blocking. The semantics of Fork are exactly those of Nachos in Project 1. void ThreadTest() { Thread *t; t = new Thread("A", 1); t->setPriority(10); printf(‘‘fee ’’); t->Fork(A, 0); printf(‘‘foe ’’); t->Join(); printf(‘‘fun\n’’); } void A(int arg) { Thread *t2; t2 = new Thread(‘‘B’’, 1); t2->setPriority(20); printf(‘‘foo ’’); t2->Fork(B, 0); printf(‘‘far ’’); t2->Join(); printf(‘‘fum ’’); } void B(int arg) { printf(‘‘fie ’’); } (a) Assume that the scheduler runs threads in round-robin order with no implicit time-slicing (i.e., non-preemptive scheduling), priorities are ignored, and threads are placed on queues in FIFO order. What will this test program print out? fee foe foo far fie fum fun (b) Now assume that the scheduler runs threads according to priority. You should not need to worry about how priority is implemented. It is enough to know that (1) the highest priority thread on the ready queue runs first, and (2) when a thread is added to the ready queue, it will preempt the current thread if the new thread has higher priority. Assume that there is no priority donation, and that the priority of the “main” thread is 0. What will the test program print out now? fee foo fie far fum foe fun 6 GOOD LUCK 22