/** When the scheme is set to RR, called when the quantum timer has expired on a core. If any job should be scheduled to run on the core free'd up by the quantum expiration, return the job_number of the job that should be scheduled to run on core core_id. @param core_id the zero-based index of the core where the quantum has expired. @param time the current time of the simulator. @return job_number of the job that should be scheduled on core cord_id @return -1 if core should remain idle */ int scheduler_quantum_expired(int core_id, int time) { /** * The current assumption is that this function works similarly for * every scheme. Preemption occurs when a new job arrives. */ job_t *done; //the finished job job_t *next = NULL; //The core is now idle ugh->corelist[core_id] = 0; int index; for(index = 0; index < priqueue_size(ugh->thing); index++) if( ((job_t *) priqueue_at(ugh->thing, index))->core == core_id) { done = (job_t *) priqueue_at(ugh->thing, index); break; } priqueue_remove_at(ugh->thing, index); //temporal statistics are calculated only when a job is done // ugh->total_response_time += done->response_time; ugh->total_turnaround_time += time - done->time; // ugh->total_waiting_time += done->waiting_time; done->when_preempted = time; done->is_running = 0; done->core = -1; done->running_time = done->running_time - time + done->start_time; done->time = time; priqueue_offer(ugh->thing, done); for(index = 0; index < priqueue_size(ugh->thing); index++) if( !((job_t *) priqueue_at(ugh->thing, index))->is_running) { next = (job_t *) priqueue_at(ugh->thing, index); break; } if(next) { next->core = core_id; ugh->corelist[core_id] = 1; next->is_running = 1; next->waiting_time += time - next->when_preempted; if(!next->firsty) { next->firsty = 1; next->first_time = time; next->response_time = time - next->time; } next->start_time = time; return next->job_number; } //The core should remain idle, such as for instance when the queue is empty. return -1; }
/** Retrieves and removes the head of this queue, or NULL if this queue is empty. @param q a pointer to an instance of the priqueue_t data structure @return the head of this queue @return NULL if this queue is empty */ void *priqueue_poll(priqueue_t *q) { if (q->head == NULL){ return NULL; } return priqueue_remove_at(q,0); }
/** Removes all instances of ptr from the queue. This function should not use the comparer function, but check if the data contained in each element of the queue is equal (==) to ptr. @param q a pointer to an instance of the priqueue_t data structure @param ptr address of element to be removed @return the number of entries removed */ int priqueue_remove(priqueue_t *q, void *ptr) { struct node *tmp = q->head; int i = 0; int num = 0; while(tmp != NULL){ if(tmp->data == ptr){ tmp=tmp->next; priqueue_remove_at(q,i); num++; }else{ i++; tmp=tmp->next; } } return num; }
int main() { priqueue_t q, q2; priqueue_init(&q, compare1); priqueue_init(&q2, compare2); /* Pupulate some data... */ int *values = malloc(100 * sizeof(int)); int i; for (i = 0; i < 100; i++) values[i] = i; /* Add 5 values, 3 unique. */ priqueue_offer(&q, &values[12]); priqueue_offer(&q, &values[13]); priqueue_offer(&q, &values[14]); priqueue_offer(&q, &values[12]); priqueue_offer(&q, &values[12]); printf("Total elements: %d (expected 5).\n", priqueue_size(&q)); priqueue_print(&q); int val_removed = *((int *)priqueue_remove_at(&q, 4)); printf("Element removed: %d (expected 14).\n", val_removed); printf("Total elements: %d (expected 4).\n", priqueue_size(&q)); int val = *((int *)priqueue_poll(&q)); printf("Top element: %d (expected 12).\n", val); printf("Total elements: %d (expected 3).\n", priqueue_size(&q)); int vals_removed = priqueue_remove(&q, &values[12]); printf("Elements removed: %d (expected 2).\n", vals_removed); printf("Total elements: %d (expected 1).\n", priqueue_size(&q)); priqueue_print(&q); priqueue_offer(&q, &values[10]); priqueue_offer(&q, &values[30]); priqueue_offer(&q, &values[20]); printf("Total elements: %d (expected 4).\n", priqueue_size(&q)); priqueue_offer(&q2, &values[10]); priqueue_offer(&q2, &values[30]); priqueue_offer(&q2, &values[20]); printf("Total elements: %d (expected 3).\n", priqueue_size(&q2)); printf("Elements in order queue (expected 10 13 20 30): "); for (i = 0; i < priqueue_size(&q); i++) printf("%d ", *((int *)priqueue_at(&q, i)) ); printf("\n"); printf("Elements in reverse order queue (expected 30 20 10): "); for (i = 0; i < priqueue_size(&q2); i++) printf("%d ", *((int *)priqueue_at(&q2, i)) ); printf("\n"); priqueue_destroy(&q2); priqueue_destroy(&q); printf("Total elements q: %d (expected 0).\n", priqueue_size(&q)); printf("Total elements q2: %d (expected 0).\n", priqueue_size(&q2)); free(values); return 0; }
/** Destroys and frees all the memory associated with q. @param q a pointer to an instance of the priqueue_t data structure */ void priqueue_destroy(priqueue_t *q) { while(priqueue_remove_at(q,0) != NULL){ } //free(q); }
int scheduler_new_job(int job_number, int time, int running_time, int priority) { ugh->num_jobs++; job_t *job = (job_t *) malloc(sizeof(job_t)); job->job_number = job_number; job->priority = priority; job->running_time = running_time; job->time = time; job->start_time = -1; job->first_time = -1; job->is_running = job->firsty = job->response_time = job->waiting_time = 0; job->when_preempted = time; job->core = -1; //no core has been assigned to it yet priqueue_offer(ugh->thing, job); //Look for an idle core int i; for(i=0; i<ugh->num_cores; i++) if(!ugh->corelist[i]) { ugh->corelist[i] = 1; //The core is now in use job->is_running = 1; //is being performed job->firsty = 1; job->start_time = time; job->first_time = time; job->response_time = 0;//time - job->time + 1; return job->core = i; //The id of the core to which job has been assigned. } if(ugh->sch/3 + ugh->sch%3 < 2 || ugh->sch == RR) return -1; //returns if nonpreemptive or RR /** * If there be no idle cores, use the power of preemption. * (Nonpreemptive jobs return -1 at the end of this function.) */ //rt = REMAINING time, not running time; pt = priority int index, rt, lrt = -1, thindex = -1, pt, mpt = -1; job_t *curr; /** * PREEMPTIVE SHORTEST JOB FIRST: * This will preempt the job that is running with the largest * remaining time, if that time be greteater than the running * time for this job. It will additionally reschedule the * preempted job with updated running time. * * One must remember that these schemes are like the nonpreemptive * ones insomuch as there be no conflicts with jobs that are running. */ if(ugh->sch == PSJF) { /** * Finding the largest remaining time of a running job and the index of the job * to which it belongs. */ for(index = 0; index < priqueue_size(ugh->thing); index++) if( ((job_t *) priqueue_at(ugh->thing, index))->is_running) { curr = (job_t *) priqueue_at(ugh->thing, index); if(lrt < (rt = curr->running_time - time + curr->start_time)) { lrt = rt; thindex = index; } } } /** * PREEMPTIVE PRIORITY THING: * Similar to PSJF, except the basis for preemption is priority. */ else if(ugh->sch == PPRI) { /** * Finding the largest priority number or lowest priority of a running job * and the index of the job to which it belongs. */ for(index = 0; index < priqueue_size(ugh->thing); index++) if( ((job_t *) priqueue_at(ugh->thing, index))->is_running) { curr = (job_t *) priqueue_at(ugh->thing, index); if(mpt <= (pt = curr->priority)) { lrt = curr->running_time - time + curr->start_time; mpt = pt; thindex = index; } } } /** * thindex is the index of the job with the largest remaining time/priority number * that is currently running. It is this job that the new job must * attempt to preempt. */ curr = priqueue_at(ugh->thing, thindex); if( (ugh->sch == PSJF && job->running_time < lrt) || (ugh->sch == PPRI && job->priority < mpt) ) { job->core = curr->core; //assign job to run on the preempted job's core priqueue_remove_at(ugh->thing, thindex); //remove curr from the queue in order to fix its stats curr->running_time = lrt; //change its running time to be the remaining time curr->is_running = 0; //remember that it is no longer running job->is_running = job->firsty = 1; job->response_time = 0; //time - job->time + 1; curr->core = -1; //it is not running on any cores curr->when_preempted = time; if(curr->first_time == time) { curr->start_time = -1; curr->firsty = 0; } job->start_time = time; priqueue_offer(ugh->thing, curr); //put it back into the priority queue return job->core; //return the core on which job is to be run } return -1; //job needs to wait in line like everyone else }