Advertisement
dusanrs

Untitled

Jun 5th, 2022
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 42.04 KB | None | 0 0
  1. //PR 85/2020 Dejan Dobrilovic, Termin vezbi: Pon 10:30. Radjeno: SOV-A. Komentari: ...
  2. //SOV pripremni zadatak, molim pogledajte detalje u priloženim uputstvima
  3. #include <iostream>
  4. #include <cstdlib>
  5. #include <thread>
  6. #include <mutex>
  7. #include <condition_variable>
  8. #include <vector>
  9. #include <list>
  10. #include <random>
  11. #include <chrono>
  12. #include <map>
  13. #include <cstring>
  14. #include <cstdio>
  15. #include <fcntl.h>
  16. #include <sys/stat.h>
  17. #include <sys/types.h>
  18. #include <unistd.h>
  19. #include <csignal>
  20.  
  21. using namespace std;
  22.  
  23. typedef chrono::high_resolution_clock hrc_t;//Radi seed-a PRNG-a.  
  24. typedef uint32_t u32;//Radi kompaktnosti pisanja
  25.  
  26. const size_t MEMORY_CAPACITY = (1 << 22); //4MiB
  27. const hrc_t::time_point start = hrc_t::now();
  28. const chrono::milliseconds stepInterval(100);
  29. const int PROCESSES = 4;
  30.  
  31. const char* outputName = "stateFifo";
  32. const char* inputName = "commandFifo";
  33.  
  34. const int EF_FIRSTFIT = 0;
  35. const int EF_LASTFIT = 1;
  36. const int EF_BESTFIT = 2;
  37. const int EF_WORSTFIT = 3;
  38. const int EF_LENGTH = 4;
  39.  
  40. const int F_ALLOCATING = 1;
  41. const int F_COMPACTING = 2;
  42. const int F_CULLING = 4;
  43.  
  44. bool allocationEnabled = true;
  45. bool compactingActive = false;
  46. bool lruActive = false;
  47.  
  48. int type = EF_FIRSTFIT;
  49.  
  50. void onAllocationChanged();
  51. void onCompactionChanged();
  52. void onLRUChanged();
  53. void onTypeChanged();
  54.  
  55. void intHandler(int sig);
  56.  
  57. mutex mCompaction;
  58. condition_variable cvCompaction;
  59.  
  60. struct Fragment{ //Jedan fragment slobodne memorije
  61.     u32 loc;
  62.     u32 len;
  63. };
  64.  
  65.  
  66. class Diagnostics{ //Pomoćna klasa, slobodno je proširiti
  67.     private:
  68.         mutex m;
  69.         int fdOutput;
  70.         int fdInput;
  71.         int waiting;
  72.         char outBuffer[8192];
  73.         bool visual;
  74.         char unit;
  75.         u32 pages;
  76.         u32 size;
  77.         u32 contiguous;
  78.     public:
  79.         Diagnostics(bool v) : waiting(0), visual(v) {
  80.             if(visual){
  81.                 fdInput = open(inputName, O_RDONLY);
  82.                 fdOutput = open(outputName, O_WRONLY);
  83.                 *((int*)(outBuffer)) = 3072 + 16;
  84.                 outBuffer[4] = type;
  85.                 outBuffer[5] = waiting;
  86.                 outBuffer[6] = F_ALLOCATING;
  87.                 outBuffer[7] = unit;
  88.                 *((u32*)(outBuffer + 8)) = pages;
  89.                 *((u32*)(outBuffer + 12)) = size;
  90.                 *((u32*)(outBuffer + 16)) = contiguous;
  91.                 for(int i = 20; i < 3092;i++){
  92.                     outBuffer[i] = 0;
  93.                 }
  94.                 unit = 'b';
  95.                 pages = 0;
  96.                 size = 0;
  97.                 contiguous = 0;
  98.             }
  99.         }
  100.  
  101.  
  102.  
  103.  
  104.  
  105.         void reportFreeSpace(u32 newPages, u32 newSize, char newUnit, u32 newContiguous){
  106.             pages = newPages;
  107.             size = newSize;
  108.             unit = newUnit;
  109.             contiguous = newContiguous;
  110.         }
  111.  
  112.         void incWaiting() {
  113.             unique_lock<mutex> l(m);
  114.             waiting++;
  115.         }
  116.         void decWaiting() {
  117.             unique_lock<mutex> l(m);
  118.             waiting--;
  119.         }
  120.         void allocateMessage(int pid, u32 loc, u32 len, u32 seg){
  121.             unique_lock<mutex> l(m);
  122.             cout << "Process " << pid << " allocating from " << loc << " to " << loc + len << endl;
  123.             if(visual){
  124.                 int x = loc / 4096;
  125.                 int ll = len / 4096;
  126.                 for(int i = 0;i < ll;i++){
  127.                     outBuffer[20 + (x + i)*3 + 0] = 1;
  128.                     outBuffer[20 + (x + i)*3 + 1] = (char)pid;
  129.                     outBuffer[20 + (x + i)*3 + 2] = (char)seg;
  130.                 }
  131.             }
  132.         }
  133.         void deallocateMessage(int pid, u32 oLoc, u32 oLen, u32 loc, u32 len){
  134.             unique_lock<mutex> l(m);
  135.             cout << "Process " << pid << " asked to deallocate from " << oLoc << " to " << oLoc + oLen << endl;
  136.             cout << "Process " << pid << " deallocated from " << loc << " to " << loc + len << endl;
  137.  
  138.             if(visual){
  139.                 int x = loc / 4096;
  140.                 int ll = len / 4096;
  141.                 for(int i = 0;i < ll;i++){
  142.                     outBuffer[20 + (x + i)*3 + 0] = 0;
  143.                     outBuffer[20 + (x + i)*3 + 1] = 0;
  144.                     outBuffer[20 + (x + i)*3 + 2] = 0;
  145.                 }
  146.             }
  147.         }
  148.  
  149.         void compactionDeallocateMessage(u32 oLoc, u32 oLen, u32 loc, u32 len){
  150.             unique_lock<mutex> l(m);
  151.             cout << "The compacter asked to deallocate from " << oLoc << " to " << oLoc + oLen << endl;
  152.             cout << "The compacter deallocated from " << loc << " to " << loc + len << endl;
  153.  
  154.             if(visual){
  155.                 int x = loc / 4096;
  156.                 int ll = len / 4096;
  157.                 for(int i = 0;i < ll;i++){
  158.                     outBuffer[20 + (x + i)*3 + 0] = 0;
  159.                     outBuffer[20 + (x + i)*3 + 1] = 0;
  160.                     outBuffer[20 + (x + i)*3 + 2] = 0;
  161.                 }
  162.             }
  163.         }
  164.  
  165.         void readMessage(int pid, u32 loc, int seg){
  166.             unique_lock<mutex> l(m);
  167.             cout << "Process " << pid << " reading from location " << loc << " in segment " << seg << endl;
  168.         }
  169.  
  170.         void writeMessage(int pid, u32 loc, int seg){
  171.             unique_lock<mutex> l(m);
  172.             cout << "Process " << pid << " writing to location " << loc << " in segment " << seg << endl;
  173.         }
  174.  
  175.         void processStatusMessage(int pid, int seg){
  176.             unique_lock<mutex> l(m);
  177.             cout << "Process " << pid << " has " << seg << " segments." << endl;
  178.         }
  179.  
  180.         void printFreeMemoryMap(int pid, u32 amount, list<Fragment>& fm){
  181.             unique_lock<mutex> l(m);
  182.             cout << "Process " << pid << " is waiting for " << amount << " bytes, which is " << amount / 4096 << " 4K pages." << endl;
  183.         }
  184.  
  185.         void compactionMessage(int pid, int seg, u32 oBase, u32 len, u32 nBase){
  186.             unique_lock<mutex> l(m);
  187.             cout << "Process " << pid << " and segment " << seg << "of length " << len << " bytes is a compaction candidate. To be moved from " << oBase << " to " << nBase << endl;
  188.             if(visual){
  189.                 int x = nBase / 4096;
  190.                 int ll = len / 4096;
  191.                 for(int i = 0;i < ll;i++){
  192.                     outBuffer[20 + (x + i)*3 + 0] = 1;
  193.                     outBuffer[20 + (x + i)*3 + 1] = (char)pid;
  194.                     outBuffer[20 + (x + i)*3 + 2] = (char)seg;
  195.                 }
  196.             }
  197.         }
  198.  
  199.         void runOutput(){
  200.             while(1 && visual){                
  201.                 this_thread::sleep_for(stepInterval / 2);
  202.                 outBuffer[4] = type;
  203.                 outBuffer[5] = waiting;
  204.                 outBuffer[6] = 0;
  205.                 outBuffer[7] = unit;
  206.                 *((u32*)(outBuffer + 8)) = pages;
  207.                 *((u32*)(outBuffer + 12)) = size;
  208.                 *((u32*)(outBuffer + 16)) = contiguous;
  209.                 if(allocationEnabled) outBuffer[6] |= F_ALLOCATING;
  210.                 if(compactingActive) outBuffer[6] |= F_COMPACTING;
  211.                 if(lruActive) outBuffer[6] |= F_CULLING;
  212.                 write(fdOutput, outBuffer, 3092);
  213.             }
  214.         }
  215.  
  216.         void runInput(){
  217.             if(visual){
  218.                 while(1){
  219.                     char inbuf[2];
  220.                     read(fdInput, inbuf, 2);
  221.                     if(inbuf[0] == 'q' && inbuf[1] == 'q'){
  222.                         intHandler(0);
  223.                         return;
  224.                     }else if(inbuf[0] == 'c'){
  225.                         type = (int)inbuf[1];
  226.                         onTypeChanged();
  227.                     }else if(inbuf[0] == 'a'){
  228.                         if(inbuf[1] == 0){
  229.                             allocationEnabled = false;
  230.                         }else if(inbuf[2] == 1){
  231.                             allocationEnabled = true;
  232.                         }else{
  233.                             allocationEnabled = !allocationEnabled;
  234.                         }
  235.                         onAllocationChanged();
  236.                     }else if(inbuf[0] == 'd'){
  237.                         if(inbuf[1] == 0){
  238.                             compactingActive = false;
  239.                         }else if(inbuf[2] == 1){
  240.                             compactingActive = true;
  241.                         }else{
  242.                             compactingActive = !compactingActive;
  243.                         }
  244.                         onCompactionChanged();
  245.                     }else if(inbuf[0] == 'n'){
  246.                         if(inbuf[1] == 0){
  247.                             lruActive = false;
  248.                         }else if(inbuf[2] == 1){
  249.                             lruActive = true;
  250.                         }else{
  251.                             lruActive = !lruActive;
  252.                         }
  253.                         onLRUChanged();
  254.                     }
  255.                 }      
  256.             }else{
  257.                 //Rezervna ne-vizuelna tehnika kontrole
  258.                 while(1){
  259.                     char c;
  260.                     cin >> c;
  261.                     if(c == 'q'){
  262.                         intHandler(0);
  263.                         return;
  264.                     }else if(c == 'c'){
  265.                         type = (type + 1) % EF_LENGTH;
  266.                         {
  267.                             unique_lock<mutex> l(m);
  268.                             cout << "Mod je sada: " << type << endl;
  269.                         }
  270.                         onTypeChanged();
  271.                     }else if(c == 'a'){
  272.                         allocationEnabled = !allocationEnabled;
  273.                         {
  274.                             unique_lock<mutex> l(m);
  275.                             cout << "Alokacije je sada: " << ((allocationEnabled) ? "ON" : "OFF") << endl;
  276.                         }
  277.                         onAllocationChanged();
  278.                     }else if(c == 'd'){
  279.                         compactingActive = !compactingActive;
  280.                         {
  281.                             unique_lock<mutex> l(m);
  282.                             cout << "Kompakcija je sada: " << ((compactingActive) ? "ON" : "OFF") << endl;
  283.                         }
  284.                         onCompactionChanged();
  285.                     }else if(c == 'n'){
  286.                         lruActive = !lruActive;
  287.                         {
  288.                             unique_lock<mutex> l(m);
  289.                             cout << "LRU je sada: " << ((compactingActive) ? "ON" : "OFF") << endl;
  290.                         }
  291.                         onLRUChanged();
  292.                     }
  293.                 }
  294.             }
  295.  
  296.         }
  297. };
  298.  
  299. struct TableEntry{ //Jedna stavka u tabeli segmenta
  300.     u32 base = 0;
  301.     u32 len = 0;
  302.     int m = -1;
  303. };
  304.  
  305. struct ReusableMutex{
  306.     bool taken = false;
  307.     mutex m;
  308. };
  309.  
  310. class SegmentTable{ //Tabela segmenata za neki proces
  311.     public:
  312.         SegmentTable() {}
  313.         int insertSegment(TableEntry tableEntry){
  314.             int id = getNewID();
  315.             table.insert(pair<int, TableEntry>(id, tableEntry));
  316.             return id;
  317.         }
  318.         void deleteSegment(int id){
  319.             table.erase(id);
  320.         }
  321.         TableEntry& getEntry(int id){
  322.             return table[id];
  323.         }
  324.         /*
  325.             Vraća nasumični validni ID iz date tabele. Nije ključno za rešenje
  326.             ali čini programiranje procesa lakšim. Prosleđujemo random_engine zato
  327.             što je njegovo generisanje jako sporo, i stoga ne treba da se pravi tokom
  328.             izvršavanja programa. Naša arhitektura ovde ima poseban generator za
  329.             svaki proces budući da generisanje slučajnih brojeva predstavlja operaciju
  330.             pisanja (menja interno stanje) te stoga se mora ili sinhronizovati ili
  331.             obezbediti jedan takav po niti. Mi smo uradili ovo drugo, zbog brzine.
  332.         */
  333.         int getRandomID(default_random_engine& gen){
  334.             uniform_int_distribution<int> d(0, table.size() - 1);
  335.             int x = d(gen);
  336.             int i = 0;
  337.             for(pair<int, TableEntry> p : table){
  338.                 if(i == x){
  339.                     return p.first;
  340.                 }
  341.                 i++;
  342.             }
  343.             cerr << "Random segment generation failed" << endl;
  344.             return 0;
  345.         }
  346.     private:
  347.         map<int, TableEntry> table;
  348.         /*
  349.             Kod nađe najveći ID date tabele i vrati tu vrednost uvećanu za 1. To
  350.             garantuje jedinstven ID.
  351.         */
  352.         int getNewID(){
  353.             if(table.empty()) return 0;
  354.             int id = 0;
  355.             for(pair<int, TableEntry> p : table){
  356.                 if(p.first > id) id = p.first;
  357.             }
  358.             return ++id;
  359.         }
  360.         friend class SystemMemory;
  361. };
  362.  
  363.  
  364. //SKOKPOD1
  365.  
  366.  
  367. typedef struct Podatak_struct{
  368.     char jedinica;
  369.     u32 velicina;
  370.     u32 broj_stranica;
  371.     u32 duzina;
  372. }Podatak;
  373.  
  374. enum alocTip{ALOK, DEALOK};
  375.  
  376.     Podatak podatak;
  377.  
  378. u32 slobodne_memorije = MEMORY_CAPACITY;
  379.  
  380.  
  381.  
  382.  
  383.  
  384.  
  385.  
  386.  
  387. //Klasa koja simulira OS
  388. class SystemMemory{
  389.     public:
  390.         SystemMemory(size_t capacity, Diagnostics& d) : terminal(false), cadh(d) {
  391.             mem = (char*)malloc(capacity);
  392.             if(mem == NULL){
  393.                 perror("Could not initialize memory.");
  394.                 exit(1);
  395.             }
  396.             //Na početku je sva memorija slobodna što znači da se naša evidencija
  397.             //slobodne memorije od 1 odsečka koji počinje od 0 i veliki je
  398.             //koliko uopšte ima memorije.
  399.             freeMemory.push_back((Fragment) {.loc=0, .len=(u32)capacity});
  400.         }
  401.         ~SystemMemory(){
  402.             free(mem);//Moramo osloboditi zauzeto
  403.         }
  404.  
  405.         //Operacija čitanja. Primetite adresu koja je segment + logička adresa
  406.         char read(int processID, int segmentID, u32 logicalAddress){
  407.             unique_lock<mutex> l(mSegments[segmentTables[processID].getEntry(segmentID).m].m);
  408.             cadh.readMessage(processID, logicalAddress, segmentID);//Ispisuje na ekran
  409.             int loc = segmentTables[processID].getEntry(segmentID).base;
  410.             if(logicalAddress >= segmentTables[processID].getEntry(segmentID).len){ //Provera prava pristupa
  411.                 cerr << "Internal segmentation violation." << endl;
  412.                 exit(2);
  413.             }
  414.             return mem[loc + logicalAddress]; //Očitavanje vrednosti uz translaciju
  415.         }
  416.         void write(int processID, int segmentID, u32 logicalAddress, char value){
  417.             unique_lock<mutex> l(mSegments[segmentTables[processID].getEntry(segmentID).m].m);
  418.             cadh.writeMessage(processID, logicalAddress, segmentID);
  419.             int loc = segmentTables[processID].getEntry(segmentID).base;
  420.             if(logicalAddress >= segmentTables[processID].getEntry(segmentID).len){
  421.                 cerr << "Internal segmentation violation." << endl;
  422.                 exit(2);
  423.             }
  424.             mem[loc + logicalAddress] = value;
  425.         }
  426.        
  427.         int allocate(int processID, u32 amount){
  428.             if(!segmentTables.count(processID)){ //U slučaju da ovo zovemo prvi put za dati proces, ubacujemo novu tabelu
  429.                 {
  430.                     unique_lock<mutex> l(mAllocate);
  431.                     segmentTables.insert(pair<int, SegmentTable>(processID, SegmentTable()));
  432.                 }//Ubacivanje menja deljenu klasu te je stavljamo u isključiv region.
  433.                 int loc = -1;
  434.                 {
  435.                     unique_lock<mutex> l(mAllocate);//I ovde zaključavamo: rad sa evidencijom slobodne memorije je takođe rad sa deljenim resursom
  436.                     while((loc = findFree(amount)) < 0){
  437.                         cadh.printFreeMemoryMap(processID, amount, freeMemory); //U slučaju čekanja pišemo kako trenutno izgleda memorija.
  438.                         cadh.incWaiting();
  439.                         cvFree.wait(l);
  440.                         cadh.decWaiting();
  441.                         if(terminal) return -1; //Proveravamo da li nas je probudio ne uspeh u alokaciji, no proces gašenja.
  442.                     }
  443.                 }
  444.                 //Sada kada imamo odakle počinje naša slobodna memorija (u loc) napravimo segment i stavimo ga u evidenciju
  445.                 int ret = segmentTables[processID].insertSegment((TableEntry) {.base = (u32)loc, .len  = amount, .m = getFreeMutex()});
  446.                 cadh.allocateMessage(processID, (u32)loc, amount, ret);
  447.  
  448.                 if(loc!= -1)
  449.                 oduzmi_memoriju(&slobodne_memorije, amount,&podatak, ALOK);
  450.  
  451.  
  452.                 return ret; //Vraćamo indeks segmenta koji smo alocirali
  453.             }else{
  454.                 //Isto kao gore, ali bez potrebe da ubacijemo tabelu budući da već postoji
  455.                 int loc = -1;
  456.                 {
  457.                     unique_lock<mutex> l(mAllocate);
  458.                     while((loc = findFree(amount)) < 0){
  459.                         cadh.printFreeMemoryMap(processID, amount, freeMemory);
  460.                         cadh.incWaiting();
  461.                         cvFree.wait(l);
  462.                         cadh.decWaiting();
  463.                         if(terminal) return -1;
  464.                     }                    
  465.                 }
  466.                 int ret = segmentTables[processID].insertSegment((TableEntry) {.base = (u32)loc, .len  = amount, .m = getFreeMutex()});
  467.                 cadh.allocateMessage(processID, (u32)loc, amount, ret);
  468.  
  469.                 if(loc!= -1)
  470.                 oduzmi_memoriju(&slobodne_memorije, amount,&podatak, ALOK);
  471.  
  472.                 return ret;
  473.             }
  474.  
  475.         }
  476.         void deallocate(int processID, int segmentID){
  477.             int loc = segmentTables[processID].getEntry(segmentID).base;
  478.             int len = segmentTables[processID].getEntry(segmentID).len;
  479.             {
  480.                 unique_lock<mutex> l(mAllocate);
  481.                 unique_lock<mutex> ll(mSegments[segmentTables[processID].getEntry(segmentID).m].m);
  482.                 list<Fragment>::iterator it;
  483.                 /*
  484.                     Ovde se implementira algoritam koji smo diskutovali
  485.                     na času. Ako oslobađamo regione fizičke memorije
  486.                     bitno je detektovati situaciju gde imamo fizičke regione
  487.                     koji se dodiruju, budući da njih treba spojiti.
  488.                     Ako je novoslobođeni segment *, a stari slobodni segmenti
  489.                     #, dok su zauzeti delovi predstavljeni praznim prostorom
  490.                     naše opcije su
  491.                     ###### **** ######## prelazi u ###### **** ########
  492.                     ######****  ######## prelazi u ##########  ########
  493.                     ######  ****######## prelazi u ######  ************
  494.                     ######******######## prelazi u ####################
  495.                 */
  496.                 for(it = freeMemory.begin(); it != freeMemory.end();it++){
  497.                     if(it->loc > loc) break;
  498.                 }
  499.                 if(it == freeMemory.begin()){
  500.                     freeMemory.push_front((Fragment) {.loc = (u32)loc, .len = (u32)len});
  501.                     it = freeMemory.begin();
  502.                     list<Fragment>::iterator next = it;
  503.                     next++;
  504.                     if(next != freeMemory.end()){
  505.                         if(it->loc + it->len == next->loc){
  506.                             it->len = it->len + next->len;
  507.                             freeMemory.erase(next);
  508.                             cadh.deallocateMessage(processID, (u32)loc, len, (u32)loc, it->len);
  509.                             cvFree.notify_all();                                  
  510.                         }else{
  511.                             cadh.deallocateMessage(processID, (u32)loc, len, (u32)loc, len);
  512.                             cvFree.notify_all();                                  
  513.                         }
  514.                     }else{
  515.                         cadh.deallocateMessage(processID, (u32)loc, len, (u32)loc, len);
  516.                         cvFree.notify_all();
  517.                     }
  518.                 }else{
  519.                     it--;
  520.                     if((it->loc + it->len) == loc){
  521.                         it->len = it->len + len;
  522.                         list<Fragment>::iterator next = it;
  523.                         next++;
  524.                         if(next != freeMemory.end()){
  525.                             if(it->loc + it->len == next->loc){
  526.                                 it->len = it->len + next->len;
  527.                                 freeMemory.erase(next);
  528.                                 cadh.deallocateMessage(processID, loc, len, it->loc, it->len);
  529.                                 cvFree.notify_all();
  530.                             }else{
  531.                                 cadh.deallocateMessage(processID, loc, len, it->loc, it->len);
  532.                                 cvFree.notify_all();
  533.                             }
  534.                         }else{
  535.                             cadh.deallocateMessage(processID, loc, len, it->loc, it->len);
  536.                             cvFree.notify_all();
  537.                         }
  538.                     }else{
  539.                         it++;
  540.                         it = freeMemory.insert(it, (Fragment) {.loc = (u32)loc, .len = (u32)len});
  541.                         list<Fragment>::iterator next = it;
  542.                         next++;
  543.                         if(next != freeMemory.end()){
  544.                             if(it->loc + it->len == next->loc){
  545.                                 it->len = it->len + next->len;
  546.                                 freeMemory.erase(next);
  547.                                 cadh.deallocateMessage(processID, loc, len, it->loc, it->len);
  548.                                 cvFree.notify_all();                                    
  549.                             }else{
  550.                                 cadh.deallocateMessage(processID, loc, len, it->loc, it->len);
  551.                                 cvFree.notify_all();
  552.                             }
  553.                         }else{
  554.                             cadh.deallocateMessage(processID, loc, len, it->loc, it->len);
  555.                             cvFree.notify_all();
  556.                         }
  557.                     }
  558.                 }
  559.                 mSegments[segmentTables[processID].getEntry(segmentID).m].taken = false;
  560.                 segmentTables[processID].deleteSegment(segmentID);
  561.  
  562.  
  563.                 oduzmi_memoriju(&slobodne_memorije, len, &podatak, DEALOK);
  564.             }
  565.         }
  566.         //Ovo je ono što u stvari zove proces, ovo ga samo usmeri gde treba
  567.         int getRandomID(int processID, default_random_engine& gen){
  568.             return segmentTables[processID].getRandomID(gen);
  569.         }
  570.         //Ovim zaustavljamo niti koje čekaju u okviru OS.
  571.         void terminate(){
  572.             terminal = true;
  573.             cvFree.notify_all();
  574.             cvCompaction.notify_all();
  575.         }
  576.         void compactionProcess(){
  577.             bool foundCandidate = false;
  578.             int cProcess = -1;
  579.             int cSegment = -1;
  580.             int cSegmentM = -1;
  581.             Fragment target;
  582.             {
  583.                 unique_lock<mutex> l(mAllocate);
  584.                 for(pair<int, SegmentTable> p : segmentTables){
  585.                     for(pair<int, TableEntry> pp : p.second.table){
  586.                         int inefficiency = 0;
  587.                         int gapBack = 0;
  588.                         int gapForward = 0;
  589.                         int targetInefficiency = MEMORY_CAPACITY;
  590.                         list<Fragment>::iterator it = freeMemory.begin();
  591.                         list<Fragment>::iterator targetFragment = freeMemory.begin();
  592.                         for(Fragment f : freeMemory){
  593.                             if(((int)f.len - (int)pp.second.len) < targetInefficiency && ((int)f.len - (int)pp.second.len) > 0){
  594.                                 targetInefficiency = (int)f.len - (int)pp.second.len;
  595.                                 targetFragment = it;
  596.                             }
  597.                             if(f.loc + f.len == pp.second.base){
  598.                                 gapBack = f.len;
  599.                             }else if(f.loc + f.len == pp.second.base + pp.second.len){
  600.                                 gapForward = f.len;
  601.                             }
  602.                             it++;
  603.                         }
  604.                         inefficiency = gapBack + gapForward;
  605.                         if(inefficiency > targetInefficiency + 8192){
  606.                             if(targetFragment->len == pp.second.len){
  607.                                 target = *targetFragment;
  608.                                 freeMemory.erase(targetFragment);
  609.                                 foundCandidate = true;
  610.                                 cProcess = p.first;
  611.                                 cSegment = pp.first;
  612.                                 cSegmentM = pp.second.m;
  613.                                 mSegments[pp.second.m].m.lock();
  614.                                 break;
  615.                             }else{
  616.                                 target = *targetFragment;
  617.                                 target.len = pp.second.len;
  618.                                 targetFragment->len -= pp.second.len;
  619.                                 targetFragment->loc += pp.second.len;
  620.                                 foundCandidate = true;
  621.                                 cProcess = p.first;
  622.                                 cSegment = pp.first;
  623.                                 cSegmentM = pp.second.m;
  624.                                 mSegments[pp.second.m].m.lock();
  625.                                 break;
  626.                             }
  627.  
  628.                         }
  629.                         if(foundCandidate) break;
  630.                     }
  631.                     if(foundCandidate) break;
  632.                 }
  633.             }
  634.             if(foundCandidate){
  635.                 this_thread::sleep_for(chrono::milliseconds(50));
  636.                 TableEntry* te = &((segmentTables[cProcess]).table[cSegment]);
  637.                 cadh.compactionMessage(cProcess, cSegment, te->base, te->len, target.loc);
  638.                 for(int i = 0;i < te->len;i++){
  639.                     mem[target.loc + i] = mem[te->base + i];
  640.                 }
  641.                 int loc = te->base;
  642.                 int len = te->len;
  643.                 te->base = target.loc;
  644.                 mSegments[cSegmentM].m.unlock();
  645.                 {
  646.                     unique_lock<mutex> l(mAllocate);
  647.                     list<Fragment>::iterator it;
  648.                 /*
  649.                     Ovde se implementira algoritam koji smo diskutovali
  650.                     na času. Ako oslobađamo regione fizičke memorije
  651.                     bitno je detektovati situaciju gde imamo fizičke regione
  652.                     koji se dodiruju, budući da njih treba spojiti.
  653.                     Ako je novoslobođeni segment *, a stari slobodni segmenti
  654.                     #, dok su zauzeti delovi predstavljeni praznim prostorom
  655.                     naše opcije su
  656.                     ###### **** ######## prelazi u ###### **** ########
  657.                     ######****  ######## prelazi u ##########  ########
  658.                     ######  ****######## prelazi u ######  ************
  659.                     ######******######## prelazi u ####################
  660.                 */
  661.                     for(it = freeMemory.begin(); it != freeMemory.end();it++){
  662.                         if(it->loc > loc) break;
  663.                     }
  664.                     if(it == freeMemory.begin()){
  665.                         freeMemory.push_front((Fragment) {.loc = (u32)loc, .len = (u32)len});
  666.                         it = freeMemory.begin();
  667.                         list<Fragment>::iterator next = it;
  668.                         next++;
  669.                         if(next != freeMemory.end()){
  670.                             if(it->loc + it->len == next->loc){
  671.                                 it->len = it->len + next->len;
  672.                                 freeMemory.erase(next);
  673.                                 cadh.compactionDeallocateMessage((u32)loc, len, (u32)loc, it->len);
  674.                                 cvFree.notify_all();                                  
  675.                             }else{
  676.                                 cadh.compactionDeallocateMessage((u32)loc, len, (u32)loc, len);
  677.                                 cvFree.notify_all();                                  
  678.                             }
  679.                         }else{
  680.                             cadh.compactionDeallocateMessage((u32)loc, len, (u32)loc, len);
  681.                             cvFree.notify_all();
  682.                         }
  683.                     }else{
  684.                         it--;
  685.                         if((it->loc + it->len) == loc){
  686.                             it->len = it->len + len;
  687.                             list<Fragment>::iterator next = it;
  688.                             next++;
  689.                             if(next != freeMemory.end()){
  690.                                 if(it->loc + it->len == next->loc){
  691.                                     it->len = it->len + next->len;
  692.                                     freeMemory.erase(next);
  693.                                     cadh.compactionDeallocateMessage(loc, len, it->loc, it->len);
  694.                                     cvFree.notify_all();
  695.                                 }else{
  696.                                     cadh.compactionDeallocateMessage(loc, len, it->loc, it->len);
  697.                                     cvFree.notify_all();
  698.                                 }
  699.                             }else{
  700.                                 cadh.compactionDeallocateMessage(loc, len, it->loc, it->len);
  701.                                 cvFree.notify_all();
  702.                             }
  703.                         }else{
  704.                             it++;
  705.                             it = freeMemory.insert(it, (Fragment) {.loc = (u32)loc, .len = (u32)len});
  706.                             list<Fragment>::iterator next = it;
  707.                             next++;
  708.                             if(next != freeMemory.end()){
  709.                                 if(it->loc + it->len == next->loc){
  710.                                     it->len = it->len + next->len;
  711.                                     freeMemory.erase(next);
  712.                                     cadh.compactionDeallocateMessage(loc, len, it->loc, it->len);
  713.                                     cvFree.notify_all();                                    
  714.                                 }else{
  715.                                     cadh.compactionDeallocateMessage(loc, len, it->loc, it->len);
  716.                                     cvFree.notify_all();
  717.                                 }
  718.                             }else{
  719.                                 cadh.compactionDeallocateMessage(loc, len, it->loc, it->len);
  720.                                 cvFree.notify_all();
  721.                             }
  722.                         }
  723.                     }
  724.                 }
  725.             }
  726.         }
  727.  
  728.         void compactionRunner(){
  729.             while(1){
  730.                 {
  731.                     unique_lock<mutex> l(mCompaction);
  732.                     while(!compactingActive){
  733.                         cvCompaction.wait(l);
  734.                     }
  735.                     if(terminal) return;            
  736.                 }
  737.                 compactionProcess();
  738.                 this_thread::sleep_for(chrono::milliseconds(10));
  739.             }
  740.         }
  741.     private:
  742.         char *mem;
  743.         bool terminal;
  744.         Diagnostics& cadh;
  745.         map<int, SegmentTable> segmentTables;
  746.         list<Fragment> freeMemory;
  747.         mutex mAllocate;
  748.         condition_variable cvFree;
  749.         ReusableMutex mSegments[1024];
  750.        
  751.         int getFreeMutex(){
  752.             for(int i = 0; i < 1024; i++){
  753.                 if(!mSegments[i].taken) return i;
  754.             }
  755.             return -1;
  756.         }
  757.  
  758.  
  759.  
  760. u32 najduzi(){
  761.  
  762.     auto iterator = freeMemory.begin();
  763.         u32 dug = iterator->len;
  764.  
  765.     while(iterator != freeMemory.end()){
  766.         ++iterator;
  767.         if(iterator->len > dug)
  768.             dug = iterator->len;
  769.     }
  770.  
  771.     return dug/4096;
  772. }
  773.  
  774.  
  775.  
  776. void oduzmi_memoriju(u32* slobodno, u32 amount, Podatak* pod, alocTip tip){
  777.  
  778.     u32 slobodno_safe = *slobodno;
  779.  
  780.     if(tip == ALOK){
  781.     *slobodno -= amount;
  782.     pod->broj_stranica = *slobodno / 4096;
  783.     }
  784.  
  785.     if(tip == DEALOK){
  786.     *slobodno += amount;
  787.     pod->broj_stranica = *slobodno / 4096;
  788.     }
  789.  
  790.     pod->jedinica = 'B';
  791.     if((slobodno_safe / 1024) > 0){
  792.         pod->jedinica = 'K';
  793.         slobodno_safe /= 1024;
  794.         if((slobodno_safe / 1024) > 0){
  795.             pod->jedinica = 'M';
  796.             slobodno_safe /= 1024;
  797.         }
  798.     }
  799.  
  800.     pod->velicina = slobodno_safe;
  801.     pod->duzina = najduzi();
  802. }
  803.  
  804.  
  805.  
  806.  
  807.  
  808.  
  809.         /*
  810.             Implementacija first fit algoritma. Prvi odsečak koji je dovoljno veliki
  811.             se odabira. Ako je taman veličine ceo se izvozi. Ako je veći, mrvi se
  812.             tako što se početak odsečka pomera unapred za zauzet prostor i dužina
  813.             se adekvatno smanjuje, a kao povratna vrednost se daje pređašnja adresa
  814.             početka tog odsečka.
  815.         */
  816.         int findFree(u32 amount){
  817.             if(type == EF_FIRSTFIT){
  818.                 for(list<Fragment>::iterator it = freeMemory.begin();it != freeMemory.end();it++){
  819.                     if(it->len == amount){
  820.                         int ret = (int)it->loc;
  821.                         freeMemory.erase(it);
  822.                         return ret;
  823.                     }else if(it->len > amount){
  824.                         int ret = (int)it->loc;
  825.                         it->loc = it->loc + amount;
  826.                         it->len = it->len - amount;
  827.                         return ret;
  828.                     }
  829.                 }
  830.             }else if(type == EF_LASTFIT){
  831.                 for(list<Fragment>::reverse_iterator it = freeMemory.rbegin();it != freeMemory.rend();it++){
  832.                     if(it->len == amount){
  833.                         int ret = (int)it->loc;
  834.                         freeMemory.erase(std::next(it).base());
  835.                         return ret;
  836.                     }else if(it->len > amount){
  837.                         int ret = (int)it->loc;
  838.                         it->loc = it->loc + amount;
  839.                         it->len = it->len - amount;
  840.                         return ret;
  841.                     }
  842.                 }
  843.             }else if(type == EF_BESTFIT){
  844.                 list<Fragment>::iterator best = freeMemory.begin();
  845.                 for(list<Fragment>::iterator it = freeMemory.begin();it != freeMemory.end();it++){
  846.                     long odiff = (long)best->len - (long)amount;
  847.                     long diff = (long)it->len - (long)amount;
  848.                     if((diff < odiff) && (diff >= 0)){
  849.                         best = it;
  850.                     }else if((odiff < 0) && (diff >= 0)){
  851.                         best = it;
  852.                     }
  853.                 }
  854.                 if(best->len == amount){
  855.                     int ret = (int)best->loc;
  856.                     freeMemory.erase(best);
  857.                     return ret;
  858.                 }else if(best->len > amount){
  859.                     int ret = (int)best->loc;
  860.                     best->loc = best->loc + amount;
  861.                     best->len = best->len - amount;
  862.                     return ret;
  863.                 }
  864.             }else if(type == EF_WORSTFIT){
  865.                 list<Fragment>::iterator best = freeMemory.begin();
  866.                 for(list<Fragment>::iterator it = freeMemory.begin();it != freeMemory.end();it++){
  867.                     long odiff = (long)best->len - (long)amount;
  868.                     long diff = (long)it->len - (long)amount;
  869.                     if((diff > odiff) && (diff >= 0)){
  870.                         best = it;
  871.                     }
  872.                 }
  873.                 if(best->len == amount){
  874.                     int ret = (int)best->loc;
  875.                     freeMemory.erase(best);
  876.                     return ret;
  877.                 }else if(best->len > amount){
  878.                     int ret = (int)best->loc;
  879.                     best->loc = best->loc + amount;
  880.                     best->len = best->len - amount;
  881.                     return ret;
  882.                 }
  883.             }
  884.             return -1;
  885.         }  
  886. };
  887.  
  888. //Sinhronizovani brojač da bi procesi dobili ID brojeve koji su jedinstveni
  889. class IDManager{
  890.     private:
  891.         int process;
  892.         mutex m;
  893.     public:
  894.         IDManager() : process(0) {}
  895.         int getProcessID(){
  896.             unique_lock<mutex> l(m);
  897.             return process++;
  898.         }
  899. };
  900.  
  901. class Process{
  902.     public:
  903.         Process(IDManager& idm, SystemMemory& sm, Diagnostics& dd) : systemMemory(sm), segmentSizeDistribution(1,25), stepDistribution(1,100), terminate(false), cadh(dd){
  904.                id = idm.getProcessID();
  905.                hrc_t::duration d = hrc_t::now() - start;
  906.                auto x = d.count();
  907.                x = x ^ (id << 7);//Dozvoljavamo bitovima id-a da utiču na seed vrednost
  908.                //generatora slučajnih brojeva ovog procesa. Ovo omogućava da slučajne
  909.                //vrednosti budu maksimalno različite čak i ako su početna vremena veoma
  910.                //bliska.
  911.                generator.seed(x);
  912.         }
  913.  
  914.  
  915. //SKOKRUN
  916.  
  917.         void run(){
  918.             cout << "Running process with ID" << id << endl;
  919.             //Pravljenje početnog, permanentnog segmenta.
  920.             u32 amount = segmentSizeDistribution(generator) * 4096;
  921.             int permanentSegment = systemMemory.allocate(id, amount);
  922.             localTable.insert(pair<int, u32>(permanentSegment, amount));
  923.             while(1){
  924.  
  925.  
  926.             cadh.reportFreeSpace(podatak.broj_stranica, podatak.velicina, podatak.jedinica, podatak.duzina);
  927.  
  928.                 if(terminate) return;
  929.                 int step = stepDistribution(generator);//Vrednost od 1 do 100
  930.                 //Što nam omogućava da precizno definišemo šanse za različite
  931.                 //korake simulacije.
  932.                 if(step < 7){
  933.                     if(!allocationEnabled) continue;
  934.                     //Veličina za alokaciju koja je umnožak 4096.
  935.                     u32 amount = segmentSizeDistribution(generator) * 4096;
  936.                     int seg = systemMemory.allocate(id, amount);
  937.                     if(seg < 0){ //Dobijamo -1 samo ako je neko pozvao terminate dok
  938.                     //smo mi čekali.
  939.                         terminate = true;
  940.                         continue;
  941.                     }
  942.                     localTable.insert(pair<int, u32>(seg, amount));
  943.                 }else if(step >= 7 && step < 10){
  944.                     int seg = systemMemory.getRandomID(id, generator);
  945.                     if(seg == permanentSegment) continue; //Ne dozvoljavamo
  946.                     //da se oslobodi permanentni segment
  947.                     systemMemory.deallocate(id, seg);
  948.                     localTable.erase(seg);                    
  949.                 }else if(step >= 10 && step < 80){
  950.                     int seg = systemMemory.getRandomID(id, generator);
  951.                     uniform_int_distribution<u32> sd(0, localTable[seg] - 1);
  952.                     u32 logicalAddress = sd(generator);
  953.                     systemMemory.read(id, seg, logicalAddress);
  954.                 }else if(step >= 80 && step < 101){
  955.                     int seg = systemMemory.getRandomID(id, generator);
  956.                     uniform_int_distribution<u32> sd(0, localTable[seg] - 1);
  957.                     uniform_int_distribution<int> dd(-1000000, 1000000);
  958.                     u32 logicalAddress = sd(generator);
  959.                     int data = dd(generator);
  960.                     systemMemory.write(id, seg, logicalAddress, data);
  961.                 }
  962.                 else{
  963.                     cerr << "Impossible step value" << endl;
  964.                     exit(3);
  965.                 }
  966.                 cadh.processStatusMessage(id, localTable.size());
  967.                 this_thread::sleep_for(stepInterval);
  968.             }
  969.         }
  970.         void doTerminate(){
  971.             terminate = true;
  972.         }
  973.     private:
  974.         int id;
  975.         Diagnostics& cadh;
  976.         default_random_engine generator;
  977.         SystemMemory& systemMemory;
  978.         map<int, u32> localTable;
  979.         uniform_int_distribution<int> segmentSizeDistribution;
  980.         uniform_int_distribution<int> stepDistribution;
  981.         bool terminate;
  982. };
  983.  
  984. //Nit koja omogućava da se proces izvršava
  985. void processRunner(Process& p){
  986.     p.run();
  987. }
  988.  
  989. void inputRunner(Diagnostics& d){
  990.     d.runInput();
  991. }
  992.  
  993. void outputRunner(Diagnostics& d){
  994.     d.runOutput();
  995. }
  996.  
  997. //Globalni pokazivači da bi mogli da pristupimo ključnim strukturama programa iz
  998. //Obrađivača signala.
  999. SystemMemory* pMem = NULL;
  1000. Process* processes = NULL;
  1001.  
  1002. //Obrađivač signala koji se poziva kada se pritisne CTRL+C
  1003. void intHandler(int sig){
  1004.     cout << "Terminating all threads... " << endl;
  1005.     if(pMem == NULL) exit(10);
  1006.     if(processes == NULL) exit(11);
  1007.     pMem->terminate();
  1008.     for(int i = 0; i < PROCESSES;i++){
  1009.         processes[i].doTerminate();
  1010.     }
  1011. }
  1012.  
  1013. void onAllocationChanged(){
  1014. }
  1015.  
  1016. void onCompactionChanged(){
  1017.     unique_lock<mutex> l(mCompaction);
  1018.     cvCompaction.notify_one();
  1019. }
  1020.  
  1021. void onTypeChanged(){
  1022.  
  1023. }
  1024.  
  1025. void onLRUChanged(){
  1026.  
  1027. }
  1028.  
  1029. void compactionRunner(SystemMemory& sysmem){
  1030.     sysmem.compactionRunner();
  1031. }
  1032.  
  1033. int main(int argc, char** argv){
  1034.     bool visual = true;
  1035.     if(argc == 2){
  1036.         if(argv[1][0] == 't'){
  1037.             visual = false;
  1038.         }
  1039.     }
  1040.     Diagnostics d(visual);
  1041.     SystemMemory mem(MEMORY_CAPACITY, d);
  1042.     pMem = &mem;
  1043.     signal(SIGINT, intHandler);
  1044.     IDManager idm;
  1045.     thread inThread(inputRunner, ref(d));
  1046.     thread outThread(outputRunner, ref(d));
  1047.     thread compactionThread(compactionRunner, ref(mem));
  1048.     compactionThread.detach();
  1049.     inThread.detach();
  1050.     outThread.detach();
  1051.     Process processList[PROCESSES] {Process(idm, mem, d), Process(idm, mem, d), Process(idm, mem, d), Process(idm, mem, d)};
  1052.     thread threadList[PROCESSES];
  1053.     for(int i = 0; i < PROCESSES;i++){
  1054.         threadList[i] = thread(processRunner, ref(processList[i]));
  1055.     }
  1056.     processes = processList;
  1057.     for(int i = 0; i < PROCESSES;i++){
  1058.         threadList[i].join();
  1059.     }
  1060.     return 0;
  1061. }
  1062.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement