/** makeing progress: increase one step for each running process in the cpus * increase one step for each i/o burst in device_queue * increase one waiting time for each process in ready_queue * */ void nextUnitTime(void) { int i; int ioSize = device_queue.size; /* increase step for processes in device queue */ for(i = 0; i < ioSize; i++) { process *dequeuedProcess = device_queue.front->data; dequeueProcess(&device_queue); (dequeuedProcess->bursts[dequeuedProcess->currentBurst].step)++; enqueueProcess(&device_queue, dequeuedProcess); } /* increase waiting time for processes in ready_queue */ for(i = 0; i < ready_queue.size; i++) { process *dequeuedProcess = ready_queue.front->data; dequeueProcess(&ready_queue); dequeuedProcess->waitingTime++; enqueueProcess(&ready_queue, dequeuedProcess); } /* increase step in running cpus */ for(i = 0; i < NUMBER_OF_PROCESSORS; i++) { if(cpus[i] != NULL) { ((cpus[i]->bursts[cpus[i]->currentBurst]).step)++; /* decrease the cpu running time by 1 */ cpus[i]->quantumRemaining--; } } }
// go through the qwaiting queue and deqeue that front FIFO burst // complete it's value // and then enqueue it eitehr back into the qaiting queue if it is not finished, or into the preReadyQueue to be placed in the ready queue void dequeueEnqueueWaitingBusts(int waitingIndex, int waitingQueueSize) { //check the front of queue process *front = waitingQueue.front->data; if (front->bursts[front->currentBurst].length == front->bursts[front->currentBurst].step) { // switch to cpu burst that is current at front front->currentBurst++; dequeueProcess(&waitingQueue); preReadyQueue[preReadyQueueSize++] = front; } else { //I/O burst not finished front->bursts[front->currentBurst].step++; dequeueProcess(&waitingQueue); enqueueProcess(&waitingQueue, front); } }
/* move any waiting processes that are finished their I/O bursts to ready */ void moveWaitingProcesses(void) { int i; int size = waitingQueue.size; /* place processes finished their I/O bursts into an intermediate array so that they will be sorted by priority and added to the ready queue */ for (i=0;i<size;i++) { process *front = waitingQueue.front->data; /* get process at front */ dequeueProcess(&waitingQueue); /* dequeue it */ assert(front->bursts[front->currentBurst].step <= front->bursts[front->currentBurst].length); /* if process' current (I/O) burst is finished, move it to the ready queue, else return it to the waiting queue */ if (front->bursts[front->currentBurst].step == front->bursts[front->currentBurst].length) { /* switch to next (CPU) burst and place in ready queue */ front->currentBurst++; preReadyQueue[preReadyQueueSize++] = front; } else { enqueueProcess(&waitingQueue, front); } } }
/* update processes in the waiting queue */ void waiting_to_ready() { int i = 0; int waiting_size = waitingQueue.size; for (i = 0; i < waiting_size; i++) { process *ready = waitingQueue.front->data; dequeueProcess(&waitingQueue); if (ready->bursts[ready->currentBurst].step == ready->bursts[ready->currentBurst].length) { ready->currentBurst++; if (ready->bursts[ready->currentBurst].length < time_slice) { //defaults to fcfs ready->quantumRemaining = INT32_MAX; } else if (ready->bursts[ready->currentBurst].length < time_slice_1) { //defaults to fcfs ready->quantumRemaining = INT32_MAX; } if (ready->currentQueue == 0) { ready->quantumRemaining = time_slice; //context_switches++; } else if (ready->currentQueue == 1) { ready->quantumRemaining = time_slice_1; //context_switches++; } else { ready->quantumRemaining = INT32_MAX; context_switches++; // processes time didnt not expire so context switches comes from I/O(waiting queue) instead } tmp_ready_process[tmp_ready_process_size++] = ready; } else { enqueueProcess(&waitingQueue, ready); } } }
/** based on nextUnitProcess, we have the process(es) that are ready to be added to ready_queue * and for processes in the ready_queue, we find any available cpus to allocate the processes. * Note: we need to sort the array by process id if they have the same scheduling criterion. */ void readyQtoCPU(void) { int i; /* reorder the temp array based on their pid, only happen when two arrival time is the same */ qsort(tempArray, tempArrayIndex, sizeof(process *), compareByPid); /* enqueue the elements in the temp to ready_queue */ for(i = 0; i < tempArrayIndex; i++) { enqueueProcess(&ready_queue, tempArray[i]); } /** reset tempArrayIndex to the front of array * since we need to restore process into it later on add io to ready_queue */ tempArrayIndex = 0; /* find some cpus to allocate them from ready_queue */ for(i = 0; i < NUMBER_OF_PROCESSORS; i++) { if(cpus[i] == NULL) { /* allocate process from ready_queue to cpu(if applicable) */ if(ready_queue.size == 0) { cpus[i] = NULL; } else { cpus[i] = ready_queue.front->data; dequeueProcess(&ready_queue); } } } }
/** from i/o to ready_queue. * Since we have device queue that hold numbers of processes with i/o bursting. * Now we want to detect any finished i/o burst process and enqueue it to tempArray again, * since the device_queue is not ordered to dequeue, So before we add it back to ready_queue, * we need to sort the tempArray again and add it back to ready_queue */ void ioToReadyQ(void) { int i; int ioSize = device_queue.size; for(i = 0; i < ioSize; i++) { /* the out element of the queue */ process *dequeuedProcess = (device_queue.front)->data; dequeueProcess(&device_queue); /** if i/o finish add it to tempArray, otherwise enqueue back to device_queue again and * try next element in device queue */ if(isBurstFinished(dequeuedProcess)) { /* move forward for burst */ (dequeuedProcess->currentBurst)++; /* since the i/o burst is finised, hence, we need to reset the timeSlice for next cpu burst */ dequeuedProcess->quantumRemaining = timeSlice; /* use temp array to temporarily store the dequeued processes */ tempArray[tempArrayIndex] = dequeuedProcess; tempArrayIndex++; } /* enqueue it back to device_queue and try next one */ else { enqueueProcess(&device_queue, dequeuedProcess); } } }
// updates the queue to coincide with FIFO structure of RR // if it is at front of the queue, dequeue that, and then enqueue the next process at the front void updateQueues() { //check front of queue process *front = readyQueue.front->data; dequeueProcess(&readyQueue); front->waitingTime++; // increment waiting time of each process in waiting queue enqueueProcess(&readyQueue, front); }
/** * Gets the next ready process to be fed into the Cpu */ process *get_next_sch_process() { if (readyQueue.size == 0) { return NULL; } process *cpu_ready = readyQueue.front->data; dequeueProcess(&readyQueue); return cpu_ready; }
/** * Gets the next ready process to be fed into the Cpu */ process *get_next_sch_process() { process *cpu_ready; if (readyQueue.size > 0) { cpu_ready = readyQueue.front->data; dequeueProcess(&readyQueue); return cpu_ready; } else if (level_one.size > 0) { cpu_ready = level_one.front->data; dequeueProcess(&level_one); return cpu_ready; } else if (second_level.size > 0) { cpu_ready = second_level.front->data; dequeueProcess(&second_level); return cpu_ready; } else { return NULL; } }
/* increment waiting time for each process in the ready queue */ void updateReadyProcesses(void) { int i; for (i=0;i<readyQueue.size;i++) { process *front = readyQueue.front->data; /* get process at front */ dequeueProcess(&readyQueue); /* dequeue it */ front->waitingTime++; /* increment waiting time */ enqueueProcess(&readyQueue, front); /* enqueue it again */ } }
/* updates the waiting time of the CPU */ void refresh_processes() { int j; // update CPU BOUND waiting process for (j = 0; j < readyQueue.size; j++) { process *CPU_BOUND = readyQueue.front->data; dequeueProcess(&readyQueue); CPU_BOUND->waitingTime++; enqueueProcess(&readyQueue, CPU_BOUND); } }
void increase_io_work() { int j; int size = waitingQueue.size; // update waiting state I\O burst for (j = 0; j < size; j++) { process *I_O = waitingQueue.front->data; dequeueProcess(&waitingQueue); I_O->bursts[I_O->currentBurst].step++; enqueueProcess(&waitingQueue, I_O); } }
/* increment each waiting process' current I/O burst's progress */ void updateWaitingProcesses(void) { int i; int size = waitingQueue.size; for (i=0;i<size;i++) { process *front = waitingQueue.front->data; /* get process at front */ dequeueProcess(&waitingQueue); /* dequeue it */ /* increment the current (I/O) burst's step (progress) */ front->bursts[front->currentBurst].step++; enqueueProcess(&waitingQueue, front); /* enqueue it again */ } }
void refresh_processes() { int j; int size = waitingQueue.size; // update waiting state I\O burst for (j = 0; j < size; j++) { process *I_O = waitingQueue.front->data; dequeueProcess(&waitingQueue); I_O->bursts[I_O->currentBurst].step++; enqueueProcess(&waitingQueue, I_O); } // update CPU BOUND process for (j = 0; j < readyQueue.size; j++) { process *CPU_BOUND = readyQueue.front->data; dequeueProcess(&readyQueue); CPU_BOUND->waitingTime++; enqueueProcess(&readyQueue, CPU_BOUND); } // increases work done by either I/O or CPU bound processes for (j = 0; j < NUMBER_OF_PROCESSORS; j++) { if (CPU[j] != NULL) { CPU[j]->bursts[CPU[j]->currentBurst].step++; } } }
void waiting_to_ready() { int i = 0; ; int waitingQueueSize = waitingQueue.size; for (i = 0; i < waitingQueueSize; i++) { process *ready = waitingQueue.front->data; dequeueProcess(&waitingQueue); if (ready->bursts[ready->currentBurst].step == ready->bursts[ready->currentBurst].length) { ready->currentBurst++; tmp_ready_process[tmp_ready_process_size++] = ready; } else { enqueueProcess(&waitingQueue, ready); } } }
// goes through everything in the ready queue and sets up the actual quantum time allocated to process // this then dequeues out the ready queue and bursts the current burst of the step void conditionalCPUProcessQueue(int cpuIndex, int preReadyQueueSize, int tempProcessSize) { if (cpus[cpuIndex] == NULL) { if (readyQueue.size == 0) { cpus[cpuIndex] = NULL; } else { //set quantum time, subtract one for current step if (readyQueue.front->data->startTime == 0) { readyQueue.front->data->startTime = timer; } readyQueue.front->data->quantumRemaining = quantum - 1; cpus[cpuIndex] = readyQueue.front->data; dequeueProcess(&readyQueue); cpus[cpuIndex]->bursts[cpus[cpuIndex]->currentBurst].step++; cpuUse++; cpuUseTotal++; } } }
// Simulates one processing cycle // @par: int current time (quantum) // @par: int flag if real time queue updated // @ret: none void doProcessing(int time, int rtUpdated) { printf("------------------------------------------------------- PROCESSOR CYCLE -------------------------------------------------------\n"); // Check if current process in a queue if (host.currentProcess != NULL) { // If current process not zero then not realtime if (host.currentProcess->priority != 0) { // If realtime queue was updated, move current process back to its queue and keep the remaining timesplice on it if (rtUpdated) { host.currentProcess->state = SUSPENDED; printf("* SUSPENDED pid: %d\n", host.currentProcess->pid); enqueueToPriority(host.currentProcess); // Enqueue the realtime process if (realTimeQueue->process != NULL) { host.currentProcess = realTimeQueue->process; host.currentProcess->timeSpliceLeft = host.currentProcess->remainingTime; dequeueProcess(&realTimeQueue); } } } } else { // Processor does not have a process currently printf("NO PROCESS RUNNING, SEARCHING FOR ANOTHER...\n"); if (rtUpdated) { // Enqueue the realtime process if (realTimeQueue) { if (realTimeQueue->process != NULL) { host.currentProcess = realTimeQueue->process; host.currentProcess->timeSpliceLeft = host.currentProcess->remainingTime; dequeueProcess(&realTimeQueue); } } } else if (p1Queue) { if (p1Queue->process != NULL) { host.currentProcess = p1Queue->process; dequeueProcess(&p1Queue); host.currentProcess->timeSpliceLeft = P1_TIMEQUANTUM; } } else if (p2Queue) { if (p2Queue->process != NULL) { host.currentProcess = p2Queue->process; dequeueProcess(&p2Queue); host.currentProcess->timeSpliceLeft = P2_TIMEQUANTUM; } } else if (p3Queue) { if (p3Queue->process != NULL) { host.currentProcess = p3Queue->process; dequeueProcess(&p3Queue); host.currentProcess->timeSpliceLeft = P3_TIMEQUANTUM; } } else { return; } } // Actual processing goes here if (host.currentProcess != NULL) { host.currentProcess->state = RUNNING; host.currentProcess->timeSpliceLeft--; host.currentProcess->remainingTime--; printf("* RUNNING pid: %d\n", host.currentProcess->pid); if (VERBOSE) printf("Time splice left in this queue: %d, total remaining time: %d\n", host.currentProcess->timeSpliceLeft, host.currentProcess->remainingTime); if (host.currentProcess->remainingTime == 0) { // Process has no time splice left in this queue, terminate the process freeHostResources(host.currentProcess); host.currentProcess->state = TERMINATED; printf("* TERMINATED pid: %d, process completed!\n", host.currentProcess->pid); free(host.currentProcess); host.currentProcess = NULL; } else if (host.currentProcess->timeSpliceLeft == 0) { // Round robin queuing if (host.currentProcess->priority < 3 && host.currentProcess->priority >= 1) { host.currentProcess->priority++; enqueueToPriority(host.currentProcess); host.currentProcess = NULL; } else if (host.currentProcess->priority >= 3) { host.currentProcess->timeSpliceLeft = P3_TIMEQUANTUM; host.currentProcess->priority = 1; enqueueToPriority(host.currentProcess); host.currentProcess = NULL; } } } }
// Updates the dispatcher // @par: int current time (quantum) // @ret: int 1 for process put into real time queue // @ret: int 0 otherwise int updateDispatcher(int time) { // Create a pointer to the dispatcher so we don't modify dispatcher directly unless we need to Queue *queuePtr = dispatcher; // Create a new queue for elements that weren't able to be added Queue *newDispatcher = initializeQueue(); int rtQUpdated = 0; // Checks if dispatcher is empty if (!(queuePtr)) { printf("The queue is empty!\n\n"); return 0; } // Iterate through each element in the queue int i = 0; int count = numElems(queuePtr); // If the first process is NULL, we don't want to iterate through them // Double check that there are elements in queue if (queuePtr->process == NULL) { i = count; } // Keep an indicator to see if anything breaks int broken = 0; // Iterate through each element in the dispatcher while (i < count) { // Dequeue the next process from the queue PCB *currentProcess = dequeueProcess(&queuePtr)->process; // Queue is empty // Triple check if (currentProcess == NULL) { printf("BROKEN!\n"); broken = 1; break; } // If the process has "arrived", attempt to allocate resources to it if (time >= currentProcess->arrivalTime) { // Attempt to allocate resources to the process. int allocResult = allocateResources(currentProcess); if (allocResult) { // Resources were allocated successfully printf("* INITIALIZED pid: %d", currentProcess->pid); if (currentProcess->priority == 0) { rtQUpdated = 1; printf(", a real time process"); } printf("\n\n"); // Send the process to join the appropriate priority queue enqueueToPriority(currentProcess); } else { // Resources could not be allocated, move the process back on the dispatcher queue enqueueProcess(newDispatcher, currentProcess); } } else { // The time has not come for this process, add it to the new dispatcher enqueueProcess(newDispatcher, currentProcess); } i++; } // If the queue wasn't broken if (!broken) { if (dispatcher == NULL) { cleanQueue(dispatcher); } dispatcher = newDispatcher; } return rtQUpdated; }
/* simulates the CPU scheduler, fetching and dequeuing the next scheduled process from the ready queue. it then returns a pointer to this process, or NULL if no suitable next process exists. */ process *nextScheduledProcess(void) { if (readyQueue.size == 0) return NULL; process *result = readyQueue.front->data; dequeueProcess(&readyQueue); return result; }