CMPSCI 377: Operating Systems

Solutions to Homework 2: Threads, Scheduling, and Synchonization


  1. (10 pts.) Threads. What are the differences between user-level and kernel-level threads? Under what circumstances is one type better than the other?



  2. (10 pts.) Scheduling. Given the following mix of jobs, job lengths, and arrival times, assume a time slice of 10 and compute the completion and average response time of each job for FIFO, RR, and SRTF algorithms.

    Scheduling Algorithms
    Job length arrival time FIFO RR SRTF
    0 75 0 75 205 205
    1 40 10 115 125 75
    2 25 10 140 105 35
    3 20 80 160 135 100
    4 45 85 205 200 145
    Avg. RT 102 119 75
    Assumption: newly-arriving jobs were added to the head of the queue.
    Under FIFO, the order of execution was 0, 1, 2, 3, 4.
    Under RR, the order of execution was 0, 1, 2, 0, 1, 2, 0, 1, 3, 4, 2, 0, 1, 3, 4, 0, 4, 0, 4, 0, 4, 0.
    Under SRTF, the order of execution was 0, 2, 1, 0, 3, 4, 0.


  3. (10 pts.) Scheduling Given 3 jobs of length 10, 30, and 25 seconds with the same arrival time, schedule them in job number order. The 10 sec job has 1 sec of I/O every other sec starting at 1 second (assume the I/O happens just before the time slice ends). The context switch time is 0 sec, and there are 2 queues. The first has 1 sec time slice; the second has a 2 sec time slice. Using the Multilevel Feedback Queues Algorithm, fill in the following tables with the average response, execution, and completion times of these jobs (assume that a higher priority job that wakes up does not preempt a currently running lower-priority task). Use the notation from class: make the superscript on the job number the progress of the job, and the subscript on the job number the system time. For comparison, also compute the job completion and average response times for the RR algorithm.

    Job length Completion Time
    RR MLFB
    1 10 28 28
    2 30 65 65
    3 25 60 60
    Avg. RT 51 (?*) 51 (?*)
    Under RR, the order of execution was 1, 2, 3, 1, 2, 3, ..., 1, 2, 3, 2, 3, ..., 2, 3, 2, 2, ..., 2.

    *Response time is calculated as "...the time between when a process is ready to run and its next I/O request." With the exeception of timeslice #1, job 1 must always wait 2 secs between when it is ready (i.e. when its 1 sec of I/O ends) and when it makes its next I/O request. How should this be factored into the average?


    Queue Time Slice Job
    1 1 111, 212, 313, 124, 137, 1410, 1513, 1616, 1719, 1822, 1925, 11028
    2 2 236, 339, 2512, 3515, 2718, 3721, 2924, 3927, 21130, 31132, 21334, 31336, 21538, 31540, 21742, 31744, 21946, 31948, 22150, 32152, 22354, 32356, 22558, 32560, 22762, 22964, 23065


  4. (10 pts.) Semaphores Suppose a building has a limit on the number of people that may be in the building at one time due to a fire code. Suppose this is a very popular place to visit, so the number of people inside must be monitored closely. Further, suppose that this building has more than one entrance and exit. Construct an algorithm that could be used to control a set of turnstiles that would ensure that the room was allowed to be filled but was never allowed to exceed its legal capacity.
    class TurnstileController
    {
        public:
            void Enter();
            void Exit();
            int PrintCurrentOccupants();
            
        private:
            // The number of occupants in the room
            int       occupants;
            
            // A counting semaphore used to track the remaining
            // capacity of the room
            Semaphore capacityRemaining;
            
            // A mutex that only allows one person to enter the room
            // at a time
            Semaphore entranceMutex;
            
            // A mutex that only allows one person to exit the room
            // at a time
            Semaphore exitMutex;
    } 
    
    TurnstileController::TurnstileController()
    {
        occupants = 0;
        capacityRemaing->value = MAX_CAPACITY;
        entranceMutex->value = 1;
        exitMutex->value = 1;
    }
    
    TurnstileController::Enter()
    {
        entranceMutex->Wait();
        capacityRemaining->Wait();
        occupants = occupants + 1;
        entranceMutex->Signal();
        
    }
    
    TurnstileController::Exit()
    {
        exitMutex->Wait();
        occupants = occupants - 1;
        capacityRemaining->Signal();
        exitMutex->Signal();
    }
    
    


  5. (10 pts.) Locks If you were an OS designer implementing locks, would you implement them using test&set or by disabling interrupts? Why?