// File: LOOKDiskMonitor.C // Author: W. R. Carithers // Mike Rooney // Description: Implementation of the SSTF disk head scheduling monitor. // #include #include #include "LOOKDiskMonitor.h" // // Constructor // // Must initialize all monitor variables, and allocate the request queue. // // LOOKDiskMonitor::LOOKDiskMonitor( int procs, int cyls, DiskMonitor::motor_t mot ) : in_use( false ), curr_cyl( 0 ), waiting( 0 ), direction( 1 ), next_in( procs - 1 ), next_out( 0 ), DiskMonitor(procs,cyls,mot) { // // We can't have more than 'procs' waiting processes, so we // are safe in dimensioning the request queue to that number. // (Note that the DiskMonitor variable is n_procs, initialize // by the subconstructor above). // available = new Condition[ cyls ]; } // // Destructor // LOOKDiskMonitor::~LOOKDiskMonitor( void ) { // release our dynamically allocated request queue delete [ ] available; } // // Name: Acquire(n,cyl) // // Description: Initiate a request from process 'n' for cylinder 'cyl'. // void LOOKDiskMonitor::Acquire( int n, int cyl ) { double entry_time; double serve_time; enter(); // // Arrival time for this request. // entry_time = vtime; if( debugging ) { cout << "<<< acq: " << n << " wants " << cyl; cout << (in_use ? ", IN USE" : ", AVAIL"); cout << ", curr_cyl " << curr_cyl; cout << ", waiting " << waiting; } // // If the disk is in use, we must wait. // // Wait on the current cylinder. // if( in_use ) { waiting += 1; // one more in the queue //next_in = (next_in + 1) % n_procs; // circular increment wait( available[cyl] ); // block this process waiting -= 1; // we're back! } // // At this point, we know that we can access the disk. // Simulate moving the heads to our desired cylinder position. // busy( abs(curr_cyl - cyl) ); curr_cyl = cyl; // // Record our service time. // serve_time = vtime; req_count[n] += 1; req_wait[n] += serve_time - entry_time; // // Mark the disk as in use. // in_use = true; if( debugging ) { cout << endl; } leave(); } // // Name: Release(n) // // Description: Release the disk so that another process can use it. // void LOOKDiskMonitor::Release( int n ) { enter(); if( debugging ) { cout << ">>> rel: " << n << ", dir "; cout << ", curr_cyl " << curr_cyl; cout << ", waiting " << waiting; } // // No longer busy. // in_use = false; // // If someone is waiting, wake up the next process. // // Check in the current direction to see if anyone is // waiting. If so, satisfy their request and continue // in the same direction. Otherwise, change direction if( waiting > 0 ) { bool found = false; if (direction == 1) { for (int i = curr_cyl; i < n_cyls; i++) { if ( queue(available[i]) ) { signal( available[i] ); found = true; break; } } if (!found) { direction = -1; } } else { for (int i = curr_cyl; i >= 0; i--) { if ( queue(available[i]) ) { signal( available[i] ); found = true; break; } } if (!found) { direction = 1; } } } if( debugging ) { cout << endl; } leave(); }