CS3013 Practice Mid-Term Exam

  1. Operating system structures:

    1. Which operating system structure is easiest to extend to a distributed system? Briefly explain why.
    2. Briefly explain why a monolithic operating systems (typical Unix) are "simple".

  2. Process control block:

    1. What are two main reasons an OS may be concerned about the size of a process control block (PCB)?
    2. Is a thread control block smaller or larger than a process control block? Why?

  3. Four processes are ready to run. Their CPU burst times are 2, 10, 2 and 6.

    1. In what order are they run under a SJF scheduling algorithm?
    2. What is the average waiting time?
    3. How close is this to the best average waiting time we could have had for these processes?
    4. What is the throughput for the SJF algorithm?
    5. If a context switch takes .1 units, how much additional overhead would a Round-Robin (quantum = 1) scheduling algorithm add to the FCFS scheduling algorithm?

  4. Consider the following SOS semaphore implementation of a wait call (additions to system.h shown on top):

       /* extra system.h stuff */
       #define NUM_SEMS 50
       /* semaphore data structures */
       struct semaphore {
         int allocated;
         int count;
         int use_count;
         int id;
         pid_queue queue;
       struct semaphore sema[NUM_SEMS];
        #include < stdio.h >
       /** wait **/
       int WaitSemaphore(int sid) {
       if (!sema[sid].allocated) return -1;  /* sid is invalid */
       if (sema[sid].count < 0) {
         insert(sema[sid].queue, current_process);
         pd[current_process].state = BLOCKED;
       return 0;

    Write the corresponding signal code for the below prototype:

       int SignalSemaphore(int sid);

  5. For the waitcode in previous problem, where might there be a race condition in the OS itself? What solutions might the OS use to avoid any race conditions in wait? Be specific.

  6. Consider running the following psuedo-code on a Unix system:

        /* global variable */
        int n=0
        main() { 
           n = n + 1
           printf("%d ", n)

    Assume all system calls succeed.

    1. What are the possible outputs?

    2. Assume the fork() call is replaced with a spawn() call that creates a new thread instead of a new process. Now, what are the possible outputs?

  7. Consider the test_and_set solution for a race condition we discussed in class:

      int lock /* shared */
      while (1) {
        while (test_and_set(lock)) /* no op */ ;
        /* critical region */
        lock = false
        /* remainder */
    1. While the above solution does satisfy mutual exclusion, what condition does it not satisfy and why?
    2. What is the major drawback the above code has over the use of semaphores

  8. Consider the dining philosopher's solution as discussed in class: Provide a solution that only allows N-1 philosophers to "sit" at the table (where N is the number of philosophers in the system). You may declare any additional variables or semaphores as needed.

Return to the CS3013 Home Page

Send all questions to the TA mailing list.