void * pq_dequeue(pq_t * pq) { void * h = pq_peek(pq); list_t * tmp = pq->list; pq->list = list_tail(pq->list); free(tmp); pq->sz_lst--; return h; }
/** * rr simulation */ void s_rr(priority_queue q, v_memory vm, int num, int cs_t, float *a_wait_t, int *total_cs, int *total_t, int *total_d, int t_memmove, int t_slice) { int cur_t = 0; // current time int cur_cs_t = cs_t + 1; // current context switch time (-1 when not switching) int cur_s_t = 0; // current time-slice time int in_use = 0; // boolean for processor usage int procs_t[num]; // processor countdowns process *procs[num]; // processes in use process *tmp; // process to pop from waiting queue int active; // active processor in use int pri = 0; // rr priority (fcfs) char *algo; // fitting algorithm priority_queue pq; // processes queue // zero arrays int i; for(i = 0; i < num; ++i) { procs_t[i] = 0; procs[i] = 0; } // initialize stuff pq = pq_new(0); // print vm algorithm switch(vm.algo) { case 'f': algo = "First-Fit"; break; case 'n': algo = "Next-Fit"; break; case 'b': algo = "Best-Fit"; break; default: break; } printf("time 0ms: Simulator started for RR (t_slice %d) and %s\n", t_slice, algo); while(1) { // check process arrival times tmp = NULL; while(tmp == NULL) { tmp = pq_peek(q, NULL); if(tmp && tmp->a_t == cur_t) { int rc; // add process to system tmp = pq_pop(q, NULL); pq_push(pq, tmp, ++pri); rc = vm_add(&vm, *tmp); if(rc != 1) { // (defrag) event_call("", cur_t, tmp->num, 'a', NULL); event_call("", cur_t, 0, 'b', NULL); event_call("", cur_t, 0, '9', NULL); vm_print(vm); *total_d += vm_defrag(&vm, 10); event_call("", cur_t, 0, 'c', NULL); event_call("", cur_t, 0, '9', NULL); vm_print(vm); vm_add(&vm, *tmp); } // print event_call("", cur_t, tmp->num, '8', pq); event_call("", cur_t, 0, '9', NULL); vm_print(vm); tmp = NULL; } else { tmp = NULL; break; } } // switching context if(cur_cs_t > 0) --cur_cs_t; // switched context if(cur_cs_t == 0) { --cur_cs_t; // check if open process available and run it if possible if((pq_size(pq) != 0) && !in_use) { int procs_u = 0; while(procs[procs_u] != 0) ++procs_u; // get next open index in_use = 1; procs[procs_u] = pq_pop(pq, NULL); // pop the next open process change_status(procs[procs_u], 1); // set status to using cpu procs_t[procs_u] = procs[procs_u]->b_t + 1; // start process timer cur_s_t = t_slice + 1; // start t_slice timer if(procs[procs_u]->cur_t > 0) procs_t[procs_u] = procs[procs_u]->cur_t; active = procs_u; --procs[procs_u]->b_n; event_call("", cur_t, procs[procs_u]->num, '1', pq); } } // process timers for(i = 0; i < num; ++i) { if(procs[i] != 0) { // check timers if(procs_t[i] > 0) { --procs_t[i]; if(cur_s_t > 0) --cur_s_t; // handle timers if(procs_t[i] == 0) { // completed cpu burst if(procs[i]->status == 1) { change_status(procs[i], 2); procs_t[i] = procs[i]->io_t; if(procs[i]->cur_t > 0) procs[i]->cur_t = 0; // reset cur_t in_use = 0; cur_cs_t = cs_t; ++*total_cs; // if process does not require i/o if(procs_t[i] == 0) { if(procs[i]->b_n <= 0) { vm_del(&vm, procs[i]->num); event_call("", cur_t, procs[i]->num, '5', pq); event_call("", cur_t, procs[i]->num, 'd', NULL); event_call("", cur_t, procs[i]->num, '9', NULL); vm_print(vm); change_status(procs[i], 3); // terminate } else { change_status(procs[i], 0); pq_push(pq, procs[i], ++pri); event_call("", cur_t, procs[i]->num, '2', pq); procs[i] = 0; } } else { if(procs[i]->b_n != 0) { event_call("", cur_t, procs[i]->num, '2', pq); event_call("", cur_t, procs[i]->num, '3', pq); } // terminate process else { procs_t[i] = 0; change_status(procs[i], 3); vm_del(&vm, procs[i]->num); event_call("", cur_t, procs[i]->num, '5', pq); event_call("", cur_t, procs[i]->num, 'd', NULL); event_call("", cur_t, procs[i]->num, '9', NULL); vm_print(vm); } } } // completed i/o else if(procs[i]->status == 2) { change_status(procs[i], 0); if(!in_use) cur_cs_t = cs_t; // finished burst if(procs[i]->b_n <= 0) { // terminate on last burst if(pq_size(pq) != 0) { vm_del(&vm, procs[i]->num); event_call("", cur_t, procs[i]->num, '5', pq); event_call("", cur_t, procs[i]->num, 'd', NULL); event_call("", cur_t, procs[i]->num, '9', NULL); vm_print(vm); } change_status(procs[i], 3); } else { pq_push(pq, procs[i], ++pri); event_call("", cur_t, procs[i]->num, '4', pq); procs[i] = 0; } } } // check time slice expiration else if(cur_s_t == 0 && procs[i]->status == 1) { if(pq_size(pq) != 0) { procs[active]->cur_t = procs_t[active]; // store the current processing time ++procs[active]->b_n; // restore burst number since it hasnt finished change_status(procs[active], 0); // reset status pq_push(pq, procs[active], ++pri); // push back into queue preempt_call(cur_t, procs[active]->num, '0', pq); // print cur_cs_t = cs_t; // switch contexts ++*total_cs; // void existing processors procs_t[active] = 0; procs[active] = 0; in_use = 0; cur_s_t = -1; } } } } } // get statistics from all processes for(i = 1; i <= pq_size(pq); ++i) { if(((process*)(pq->buf[i].data))->status == 0) { ++*a_wait_t; } } if(pq_size(pq) == 0 && !in_use && done(procs_t, sizeof(procs_t) / sizeof(int))) { *total_t = cur_t; event_call("RR", cur_t, 0, '7', pq); return; } ++cur_t; } }