Review Problems for CS 302 Exam 1 Spring 2005 The exam will be over the first five chapters (up to Section 5.4) of the textbook, "Operating Systems: Internals and Design Principles", Fifth Edition, by Williams Stallings. 1. Chapter 3, Problems 3.1, 3.2, 3.3, and 3.4. 2. Chapter 4, Problems 4.1, 4.2, 4.4, 4.5, and 4.7. 3. Chapter 5, Problems 5.2, 5.3, 5.4, 5.8, 5.9, 5.12 and 5.14. 4. If you can only run one program at a time, is it still useful to have an operating system? Why or why not? 5. Name three major resources controlled by an operating system. 6. Which of the following machine instructions should be privileged? Explain why. a) Set value of timer b) Read system clock c) Turn off interrupts d) Switch from user to supervisor mode 7. How do I/O-bound and CPU-bound programs differ? 8. What is a context switch? Why is it important that context switching be fast? 9. What is the time quantum used for? How should the time quantum be related to the context switch time? 10. The kernel keeps a record for each process, called the Process Control Block (PCB). When a process is not running, its PCB contains the information that is necessary to restart the process on the CPU. List two pieces of information that the PCB must have. 11. How does creating a thread differ from creating a process? How does context switching for threads differ from context switching for processes. 12. What are the different states a process can be in? What are the possible transitions between states? (Draw a picture.) What events can cause each of those transitions to happen? 13.Give four causes for a running process to relinquish the CPU. 14. List three things that a running process might do that would cause the scheduler not to move it to the ready state when it stops running. 15. Use process states to describe the difference between the two function calls Sleep(0) and Sleep(1). 16. Use process states to explain the difference between busy waiting and blocking. 17. Here is an easy-to-implement approach to scheduling that works pretty well: put the I/O-bound processes at the top of the priority list and the CPU-bound processes at the bottom. What makes this approach work? 18. a) In general, blocking is better than busy waiting. Explain why. b) If it is known in advance that a wait will be very short, then busy waiting can be better than blocking. Explain why. 19. What is a race condition? 20. What is a critical section? 21. Suppose that an operating system has the policy that scheduling decisions are only made whenever a process terminates or a running process blocks. How does this policy affect the problem of critical sections? 22. The following code outlines a certain kind of synchronization pattern. In what way are the two threads synchronized? How might this pattern get used? int main() { //thread function prototypes DWORD WINAPI thread1(LPVOID); DWORD WINAPI thread2(LPVOID); semaphore = CreateSemaphore(NULL, 0, 1, NULL); // not signaled CreateThread(NULL, 0, thread1, 0, 0, NULL); CreateThread(NULL, 0, thread2, 0, 0, NULL); while(1){ Sleep(1000); } return 0; }//main DWORD WINAPI thread1(LPVOID threadParam) { for (int i = 0; i < N; i++;) { < do a calculation > ReleaseSemaphore(semaphore, 1, NULL); < do a long calculation > ReleaseSemaphore(semaphore, 1, NULL); < do another long calculation > } return 0; }//thread1 DWORD WINAPI thread2(LPVOID threadParam) { while(1) { WaitForSingleObject(semaphore, INFINITE); < do a very short calculation > } return 0; }//thread2 23. The following code outlines a certain kind of synchronization pattern. In what way are the two threads synchronized? How might this pattern get used? int main() { //thread function prototypes DWORD WINAPI thread1(LPVOID); DWORD WINAPI thread2(LPVOID); semaphore1 = CreateSemaphore(NULL, 0, 1, NULL); // not signaled semaphore2 = CreateSemaphore(NULL, 0, 1, NULL); // not signaled CreateThread(NULL, 0, thread1, 0, 0, NULL); CreateThread(NULL, 0, thread2, 0, 0, NULL); while(1){ Sleep(1000); } return 0; }//main DWORD WINAPI thread1(LPVOID threadParam) { for (int i = 0; i < N; i++;) { ReleaseSemaphore(semaphore2, 1, NULL); WaitForSingleObject(semaphore1, INFINITE); < do first calculation > ReleaseSemaphore(semaphore2, 1, NULL); WaitForSingleObject(semaphore1, INFINITE); < do second calculation > } return 0; }//thread1 DWORD WINAPI thread2(LPVOID threadParam) { while(1) { ReleaseSemaphore(semaphore1, 1, NULL); WaitForSingleObject(semaphore2, INFINITE); < do a calculation > } return 0; }//thread2 24. In the last example, what would happen if the second ReleaseSemaphore(semaphore2, 1, NULL); in Thread1 was deleted? 25. The following code outlines a certain kind of synchronization pattern. In what way are the two threads synchronized? How might this pattern get used? int main() { //thread function prototypes DWORD WINAPI thread1(LPVOID); DWORD WINAPI thread2(LPVOID); semaphore1 = CreateSemaphore(NULL, 1, 1, NULL); // signaled semaphore2 = CreateSemaphore(NULL, 0, 1, NULL); // not signaled CreateThread(NULL, 0, thread1, 0, 0, NULL); CreateThread(NULL, 0, thread2, 0, 0, NULL); while(1){ Sleep(1000); } return 0; }//main DWORD WINAPI thread1(LPVOID threadParam) { for (int i = 0; i < N; i++;) { WaitForSingleObject(semaphore1, INFINITE); < do first calculation > ReleaseSemaphore(semaphore2, 1, NULL); WaitForSingleObject(semaphore1, INFINITE); < do second calculation > ReleaseSemaphore(semaphore2, 1, NULL); } return 0; }//thread1 DWORD WINAPI thread2(LPVOID threadParam) { while(1) { WaitForSingleObject(semaphore2, INFINITE); < do a calculation > ReleaseSemaphore(semaphore1, 1, NULL); } return 0; }//thread2