Advertisement
Guest User

Untitled

a guest
Oct 20th, 2014
225
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.17 KB | None | 0 0
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <map>
  5. #include <stdlib.h>
  6. #include <cstdlib>
  7. #include <algorithm>
  8. #include <iomanip>
  9.  
  10. #define SJFNP 0
  11. #define SJFP 1
  12. #define RR 2
  13. #define PP 3
  14.  
  15. int n = 12; //num processes
  16.  
  17. class Process {
  18. public:
  19. Process() : id(0), cpu(false), burstTime(0), cpuBursts(0), t(0), b(0), userMode(false), turnaround(0), wait(0), priority(0), totalTurnaround(0), totalWait(0) {
  20. }
  21. //constant
  22. int id; //process id
  23. bool cpu; //false for interactive process, true for cpu process
  24. int burstTime; //burst time needed from the cpu
  25. int userTime; //time needed from i/o
  26. int cpuBursts; //num bursts before terminating (for cpu processes)
  27. int initialPriority;
  28. //varying
  29. int t; //time (starting at 0)
  30. int b; //count of cpu bursts
  31. bool userMode; //if waiting for i/o
  32. int turnaround; //turnaround time counter
  33. int wait; //wait time counter
  34. int priority;
  35. int totalTurnaround;
  36. int totalWait;
  37.  
  38. //increment time
  39. void timeInc(bool active) {
  40. if (active){
  41. t++;
  42. turnaround++;
  43. } else {
  44. t++;
  45. wait++;
  46. }
  47. }
  48.  
  49. void reset(){
  50. t = 0;
  51. b = 0;
  52. userMode = false;
  53. turnaround = 0;
  54. wait = 0;
  55. priority = initialPriority;
  56. totalTurnaround = 0;
  57. totalWait = 0;
  58. }
  59.  
  60. };
  61.  
  62. class CPU {
  63. public:
  64. CPU() : process(NULL), processOut(NULL), useTime(0), notUseTime(0), contextSwitchTime(0), inContextSwitch(false) {
  65. }
  66. Process* process;
  67. Process* processOut; //process leaving during a context switch
  68. int useTime;
  69. int notUseTime;
  70. int contextSwitchTime;
  71. bool inContextSwitch;
  72. std::map<int, int> processesTime;
  73. void reset() {
  74. process = NULL;
  75. processOut = NULL;
  76. useTime = 0;
  77. notUseTime = 0;
  78. contextSwitchTime = 0;
  79. inContextSwitch = false;
  80. for (int i=0; i<n; i++){
  81. processesTime[i+1] = 0;
  82. }
  83. }
  84. };
  85.  
  86. std::vector<CPU*> cpus;
  87. std::vector<Process*> readyQueue;
  88. std::vector<Process*> terminatedProcesses;
  89. double pInt = .8; //percent of interactive processes
  90. int iBMin = 20; //min burst time for interactive processes
  91. int iBMax = 200; //max burst time for interactive processes
  92. int uMin = 1000; //min user time
  93. int uMax = 4500; //max user time
  94. int cBMin = 200; //min burst time for cpu processes
  95. int cBMax = 3000; //max burst time for cpu processes
  96. int b = 8; //num burst for cpu processes before terminating
  97. int ioMin = 1200; //min i/o block time
  98. int ioMax = 3200; //max i/o block time
  99. int m = 4; //num cpu's
  100. int tSlice = 100; //time slice for RR
  101. int tAging = 1200; //aging will cause lower-priority processes to increment after this time passes
  102. int tCS = 2; //overhead time for completing a context switch
  103.  
  104. int t = 0; //time
  105. int algorithm = SJFNP; //the algorithm currently simulated
  106. int rrTimer = 0; //time counter for RR
  107. int minTurnaround = 99999999;
  108. int maxTurnaround = 0;
  109. int totalTurnaround = 0;
  110. int minWait = 99999999;
  111. int maxWait = 0;
  112. int totalWait = 0;
  113.  
  114. int randomVal(int low, int high) {
  115. return low + (high - low) * (rand() * 1.0 / RAND_MAX);
  116. }
  117.  
  118. void addToReadyQueue(Process* proc, bool canPreempt = false);
  119. void contextSwitch(Process* proc, CPU* cpu);
  120.  
  121. void makeProcesses() {
  122. for (int i=0; i<n; i++){
  123. Process* proc = new Process();
  124. proc->id = i+1;
  125. if (i < pInt*n){
  126. //interactive process
  127. proc->cpu = false;
  128. proc->burstTime = randomVal(iBMin, iBMax);
  129. proc->userTime = randomVal(uMin, uMax);
  130. } else {
  131. //cpu process
  132. proc->cpu = true;
  133. proc->burstTime = randomVal(cBMin, cBMax);
  134. proc->cpuBursts = b;
  135. proc->userTime = randomVal(ioMin, ioMax);
  136. }
  137. proc->initialPriority = rand() % 5;
  138. proc->priority = proc->initialPriority;
  139. addToReadyQueue(proc);
  140. for (int j=0; j<int(cpus.size()); j++){
  141. cpus[j]->processesTime[proc->id] = 0;
  142. }
  143. }
  144.  
  145. }
  146. bool shorterProcess(Process* p1, Process* p2) { return p1->burstTime - p1->t < p2->burstTime - p2->t; }
  147. int indexOfShortestProcess(std::vector<Process*> queue){
  148. int ret = 0;
  149. if (queue.empty()) return -1;
  150. Process* proc = queue[0];
  151. for (int i=1; i<int(queue.size()); i++){
  152. if (shorterProcess(queue[i], proc)){
  153. ret = i;
  154. proc = queue[i];
  155. }
  156. }
  157. return ret;
  158. }
  159. int indexOfHighestPriority(std::vector<Process*> queue){
  160. int ret = 0;
  161. if (queue.empty()) return -1;
  162. Process* proc = queue[0];
  163. for (int i=1; i<int(queue.size()); i++){
  164. if (queue[i]->priority < proc->priority){
  165. ret = i;
  166. proc = queue[i];
  167. }
  168. }
  169. return ret;
  170. }
  171.  
  172. void resetCPUs(){
  173. for (int i=0; i<int(cpus.size()); i++){
  174. CPU* cpu = cpus[i];
  175. cpu->process = NULL;
  176. cpu->useTime = 0;
  177. cpu->notUseTime = 0;
  178. }
  179. }
  180.  
  181. void addToReadyQueue(Process* proc, bool canPreempt){
  182. readyQueue.push_back(proc);
  183.  
  184. std::cout << "[time " << int(t) << "ms] ";
  185. if (proc->cpu){
  186. std::cout << "CPU-bound";
  187. } else {
  188. std::cout << "Interactive";
  189. }
  190. std::cout << " process ID " << proc->id;
  191. std::cout << " entered ready queue (";
  192. std::cout << "requires " << int(proc->burstTime) << "ms CPU time; ";
  193. std::cout << "priority " << proc->priority << ")";
  194. std::cout << std::endl;
  195.  
  196. //if can preempt, check if other job should be interrupted
  197. if (canPreempt &&
  198. algorithm == SJFP){
  199. for (int i=0; i<int(cpus.size()); i++){
  200. CPU* cpu = cpus[i];
  201. if (cpu->process != NULL && !cpu->inContextSwitch
  202. && !cpu->process->userMode){
  203. if (proc->burstTime < cpu->process->burstTime - cpu->process->t){
  204. contextSwitch(proc, cpu);
  205. break;
  206. }
  207. }
  208. }
  209. }
  210. if (canPreempt &&
  211. algorithm == PP){
  212. for (int i=0; i<int(cpus.size()); i++){
  213. CPU* cpu = cpus[i];
  214. if (cpu->process != NULL && !cpu->inContextSwitch
  215. && !cpu->process->userMode){
  216. if (proc->priority < cpu->process->priority){
  217. contextSwitch(proc, cpu);
  218. break;
  219. }
  220. }
  221. }
  222. }
  223. }
  224.  
  225. void removeFromReadyQueue(Process* proc) {
  226. int index = -1;
  227. for (int i=0; i<int(readyQueue.size()); i++){
  228. if (readyQueue[i] == proc){
  229. index = i;
  230. break;
  231. }
  232. }
  233. if (index == -1) return;
  234. readyQueue.erase(readyQueue.begin()+index);
  235. }
  236.  
  237. void contextSwitch(Process* proc, CPU* cpu) {
  238. Process* cpuProc = cpu->process;
  239. if (proc != NULL){
  240. removeFromReadyQueue(proc);
  241. }
  242. std::cout << "[time " << t << "ms] Context switch (";
  243. if (cpuProc == NULL){
  244. } else {
  245. std::cout << "swapping out process ID " << cpuProc->id;
  246. if (proc == NULL){
  247. std::cout << ")";
  248. } else {
  249. std::cout << " for ";
  250. }
  251. cpu->processOut = cpuProc;
  252. }
  253. if (proc != NULL){
  254. std::cout << "process ID " << proc->id << ")";
  255. }
  256. std::cout << std::endl;
  257. cpu->process = proc;
  258. cpu->inContextSwitch = true;
  259. cpu->contextSwitchTime = 0;
  260.  
  261. }
  262.  
  263. void increasePriority(Process* proc) {
  264. if (proc->priority <= 0)
  265. return;
  266. proc->priority--;
  267. std::cout << "[time " << t << "ms] Increased priority of ";
  268. if (proc->cpu) std::cout << "CPU-bound ";
  269. else std::cout << "Interactive ";
  270. std::cout << "process ID " << proc->id << " to " << proc->priority << " due to aging";
  271. std::cout << std::endl;
  272. }
  273.  
  274. void terminateProcess(Process* proc) {
  275. std::cout << "[time " << t << "ms] CPU-bound process ID " << proc->id << " terminated ";
  276. std::cout << "(avg turnaround time " << (proc->totalTurnaround / proc->cpuBursts);
  277. std::cout << ", avg total wait time " << (proc->totalWait / proc->cpuBursts) << ")";
  278. std::cout << std::endl;
  279. terminatedProcesses.push_back(proc);
  280. }
  281.  
  282. //does all actions that takes place in 1 ms
  283. void step() {
  284.  
  285. //finish context switches
  286. for (int i=0; i<int(cpus.size()); i++){
  287. CPU* cpu = cpus[i];
  288. if (cpu->inContextSwitch && cpu->contextSwitchTime >= tCS){
  289. if (cpu->processOut != NULL){
  290. addToReadyQueue(cpu->processOut, true);
  291. }
  292. cpu->processOut = NULL;
  293. cpu->inContextSwitch = false;
  294. }
  295. }
  296.  
  297. //processes completing
  298. for (int i=0; i<int(cpus.size()); i++){
  299. CPU* cpu = cpus[i];
  300. if (cpu->process == NULL || cpu->inContextSwitch) continue;
  301. Process* proc = cpu->process;
  302. if (proc->userMode){ //i/o completed
  303. if (proc->t >= proc->userTime){
  304. //user i/o completed, go back to ready queue
  305. proc->turnaround = 0;
  306. proc->wait = 0;
  307. proc->priority = proc->initialPriority;
  308. proc->userMode = false;
  309. proc->t = 0;
  310. contextSwitch(NULL, cpu);
  311. }
  312. } else { //cpu burst completed
  313. std::cout << "[time " << t << "ms] ";
  314. if (proc->cpu) std::cout << "CPU-bound";
  315. else std::cout << "Interactive";
  316. std::cout << " process ID " << proc->id << " CPU burst done (turnaround time ";
  317. std::cout << proc->turnaround << "ms, total wait time ";
  318. std::cout << proc->wait << "ms)";
  319. std::cout << std::endl;
  320.  
  321. if (proc->turnaround < minTurnaround) minTurnaround = proc->turnaround;
  322. if (proc->turnaround > maxTurnaround) maxTurnaround = proc->turnaround;
  323. totalTurnaround += proc->turnaround;
  324. if (proc->wait < minWait) minWait = proc->wait;
  325. if (proc->wait > maxWait) maxWait = proc->wait;
  326. totalWait += proc->wait;
  327.  
  328. proc->totalTurnaround += proc->turnaround;
  329. proc->totalWait += proc->wait;
  330.  
  331. if (proc->t >= proc->burstTime){
  332. if (proc->cpu){ //cpu-bound, keep track of cpu bursts
  333. proc->b++;
  334. if (proc->b >= proc->cpuBursts){
  335. //process done, should be terminated
  336. cpu->process = NULL;
  337. terminateProcess(proc);
  338. } else {
  339. //enter user mode
  340. proc->userMode = true;
  341. proc->t = 0;
  342. }
  343. } else { //interactive process
  344. //enter user mode
  345. proc->userMode = true;
  346. proc->t = 0;
  347. }
  348.  
  349. }
  350. }
  351. }
  352.  
  353.  
  354.  
  355. int index;
  356. Process* proc;
  357. switch (algorithm){
  358. case SJFNP:
  359. case SJFP:
  360. for (int i=0; i<int(cpus.size()); i++){
  361. CPU* cpu = cpus[i];
  362. if (cpu->process == NULL && !cpu->inContextSwitch){
  363. //process with shortest job enters CPU
  364. if (!readyQueue.empty()){
  365. index = indexOfShortestProcess(readyQueue);
  366. proc = readyQueue[index];
  367. contextSwitch(proc, cpu);
  368. }
  369. }
  370. }
  371. break;
  372. case RR:
  373. for (int i=0; i<int(cpus.size()); i++){
  374. CPU* cpu = cpus[i];
  375. //fill all cpus' with a process
  376. if (cpu->process == NULL && !cpu->inContextSwitch){
  377. if (!readyQueue.empty()){
  378. index = 0; //since processes are pushed to the back of the readyQueue
  379. proc = readyQueue[index];
  380. contextSwitch(proc, cpu);
  381. }
  382. }
  383. }
  384.  
  385. rrTimer++;
  386. if (rrTimer >= tSlice){
  387. //preform round robin
  388. for (int i=0; i<int(cpus.size()); i++){
  389. CPU* cpu = cpus[i];
  390. if (cpu->inContextSwitch) continue; //would prevent cpu from RR, not sure how to fix
  391. if (readyQueue.empty()) break;
  392. proc = readyQueue[0];
  393. contextSwitch(proc, cpu);
  394. }
  395.  
  396. rrTimer = 0;
  397. }
  398. break;
  399. case PP:
  400. for (int i=0; i<int(cpus.size()); i++){
  401. CPU* cpu = cpus[i];
  402. if (cpu->process == NULL && !cpu->inContextSwitch){
  403. //process with highest priority enters CPU
  404. if (!readyQueue.empty()){
  405. index = indexOfHighestPriority(readyQueue);
  406. proc = readyQueue[index];
  407. contextSwitch(proc, cpu);
  408. }
  409. }
  410. }
  411. break;
  412. }
  413.  
  414.  
  415.  
  416.  
  417. //increment time values
  418. for (int i=0; i<int(cpus.size()); i++){
  419. CPU* cpu = cpus[i];
  420. if (cpu->inContextSwitch){
  421. cpu->contextSwitchTime++;
  422. cpu->useTime++;
  423. if (cpu->process != NULL){
  424. cpu->process->timeInc(true);
  425. }
  426. if (cpu->processOut != NULL){
  427. cpu->processOut->timeInc(true);
  428. }
  429. } else if (cpu->process != NULL){
  430. cpu->useTime++;
  431. if (cpu->process != NULL){
  432. cpu->processesTime[cpu->process->id]++;
  433. cpu->process->timeInc(true);
  434. }
  435. } else {
  436. cpu->notUseTime++;
  437. }
  438. }
  439. for (int i=0; i<int(readyQueue.size()); i++){
  440. Process* proc = readyQueue[i];
  441. proc->timeInc(false);
  442. if (algorithm == PP){ //detect changing priority
  443. if (proc->wait % tAging == 0){
  444. increasePriority(proc);
  445. }
  446. }
  447. }
  448.  
  449. t++;
  450. }
  451.  
  452. //prints data after simulation
  453. void analysis(){
  454.  
  455. int cpuUseTime = 0;
  456. int cpuTotalTime = 0;
  457. std::vector<int> cpuProcessesTime(n);
  458. for (int i=0; i<int(cpus.size()); i++){
  459. CPU* cpu = cpus[i];
  460. cpuUseTime += cpu->useTime;
  461. cpuTotalTime += cpu->useTime + cpu->notUseTime;// + cpu->contextSwitchTime;
  462. for (int j=0; j<n; j++){
  463. cpuProcessesTime[j] += cpu->processesTime[j+1];
  464. }
  465. }
  466.  
  467. std::cout << std::endl;
  468. std::cout << "Turnaround time: min " << minTurnaround << " ms; ";
  469. std::cout << "avg " << std::setprecision(12) << (totalTurnaround*1.0 / n) << " ms; ";
  470. std::cout << "max " << maxTurnaround << " ms\n";
  471. std::cout << "Total wait time: min " << minWait << " ms; ";
  472. std::cout << "avg " << std::setprecision(12) << (totalWait*1.0 / n) << " ms; ";
  473. std::cout << "max " << maxWait << " ms\n";
  474. std::cout << "Average CPU utilization: " << std::setprecision(12) << (100.0*cpuUseTime / cpuTotalTime) << "%\n\n";
  475. std::cout << "Average CPU utilization per process: \n";
  476. for (int i=0; i<int(cpuProcessesTime.size()); i++){
  477. std::cout << (i+1) << ": " << std::setprecision(12) << (100.0*cpuProcessesTime[i] / cpuTotalTime) << "%\n";
  478. }
  479. }
  480.  
  481. void reset() {
  482. t = 0;
  483. rrTimer = 0;
  484. minTurnaround = 99999999;
  485. maxTurnaround = 0;
  486. totalTurnaround = 0;
  487. minWait = 99999999;
  488. maxWait = 0;
  489. totalWait = 0;
  490.  
  491. for (int i=0; i<int(cpus.size()); i++){
  492. CPU* cpu = cpus[i];
  493. if (cpu->process != NULL)
  494. terminatedProcesses.push_back(cpu->process);
  495. if (cpu->processOut != NULL)
  496. terminatedProcesses.push_back(cpu->processOut);
  497. cpu->reset();
  498. }
  499.  
  500. for(int i=0; i<int(readyQueue.size()); i++){
  501. terminatedProcesses.push_back(readyQueue[i]);
  502. }
  503. readyQueue.clear();
  504. for(int i=0; i<int(terminatedProcesses.size()); i++){
  505. terminatedProcesses[i]->reset();
  506. addToReadyQueue(terminatedProcesses[i]);
  507. }
  508. terminatedProcesses.clear();
  509.  
  510.  
  511. }
  512.  
  513. void run(){
  514. while (int(terminatedProcesses.size()) < int((1-pInt) * n)){
  515. step();
  516. }
  517. }
  518.  
  519. int main(int argc, const char* argv[]) {
  520.  
  521. //parse argv
  522. for (int i=1; i<argc; i++) {
  523. //example: pInt=.7 (variable = value)
  524. std::string arg(argv[i]);
  525. int index = (int) arg.find('=');
  526. if (index == -1) continue;
  527. std::string varStr = arg.substr(0, index);
  528. const char* c = arg.substr(index+1).c_str();
  529. if (varStr == "n") n = atoi(c);
  530. else if (varStr == "pInt") pInt = atof(c);
  531. else if (varStr == "iBMin") iBMin = atoi(c);
  532. else if (varStr == "iBMax") iBMax = atoi(c);
  533. else if (varStr == "uMin") uMin = atoi(c);
  534. else if (varStr == "uMax") uMax = atoi(c);
  535. else if (varStr == "cBMin") cBMin = atoi(c);
  536. else if (varStr == "cBMax") cBMax = atoi(c);
  537. else if (varStr == "b") b = atoi(c);
  538. else if (varStr == "ioMin") ioMin = atoi(c);
  539. else if (varStr == "ioMax") ioMax = atoi(c);
  540. else if (varStr == "m") m = atoi(c);
  541. else if (varStr == "tSlice") tSlice = atoi(c);
  542. else if (varStr == "tAging") tAging = atoi(c);
  543. else if (varStr == "tCS") tCS = atoi(c);
  544. }
  545.  
  546. //make cpu's
  547. for (int i=0; i<m; i++){
  548. CPU* cpu = new CPU();
  549. cpus.push_back(cpu);
  550. }
  551.  
  552. //run
  553. algorithm = SJFNP;
  554. std::cout << "Shortest-Job-First with no preemption:\n\n";
  555. makeProcesses();
  556. run();
  557. analysis();
  558.  
  559. algorithm = SJFP;
  560. std::cout << "\n\nShortest-Job-First with preemption:\n\n";
  561. reset();
  562. run();
  563. analysis();
  564.  
  565. algorithm = RR;
  566. std::cout << "\n\nRound-Robin:\n\n";
  567. reset();
  568. run();
  569. analysis();
  570.  
  571. algorithm = PP;
  572. std::cout << "\n\nPreemptive Priority:\n\n";
  573. reset();
  574. run();
  575. analysis();
  576.  
  577. //cleanup
  578. for (int i=0; i<(int) cpus.size(); i++){
  579. delete cpus[i];
  580. }
  581. cpus.clear();
  582. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement