home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 4 / DATAFILE_PDCD4.iso / utilities / utilst / virtual / !Virtual / c / pager < prev    next >
Text File  |  1993-07-06  |  13KB  |  536 lines

  1. #include "swis.h"
  2. #include "swiv.h"
  3. #include "wimp.h"
  4.  
  5. #include "virtual.h"
  6. #include "lib.h"
  7. #include "output.h"
  8. #include "pager.h"
  9.  
  10. /* #define DEBUG */
  11.  
  12. void Initourmem(WKSP *w)
  13. {
  14.   int i;
  15.   w->stacktop = (char *)alloc(STACKSIZE)+STACKSIZE;
  16.  
  17.   swi(OS_ReadMemMapInfo, OUT(R0|R1), &w->pagesize, &w->numpages);
  18.  
  19. #ifndef FIXED_2MB
  20.   w->pageshift = w->pagesize == K32 ? 15 : 13;
  21. #else
  22.   w->pageshift = 15;
  23.   if (w->pagesize == K32/2) w->pageshift = 14;
  24.   if (w->pagesize == K32/4) w->pageshift = 13;
  25. #endif
  26.  
  27.   w->numplaces = PLACE(M24);
  28.   w->ourmem = alloc(sizeof(int) * w->numplaces);
  29.  
  30.   w->oldpages = alloc(sizeof(PAGEENTRY)*(w->numpages + 1));
  31.   w->newpages = alloc(sizeof(PAGEENTRY)*(w->numpages + 1));
  32.   FindPages(w);
  33.  
  34.   w->nslots = 0;        /* page file empty */
  35.   w->index = alloc(sizeof(int)*w->numplaces);
  36.  
  37.   for ( i=PLACE(K32); i<w->numplaces; i++)
  38.   { w->ourmem[i] = TAGLOC(ABORT, 0);
  39.   }
  40.   w->losepage = 0;
  41. }
  42.  
  43. void SetWimpMemMap(WKSP *w)
  44. {
  45.   int i;
  46. #ifdef DEBUG
  47.   printf("Places %d..%d match wimp map\n",PLACE(K32),w->numourpages+PLACE(K32));
  48. #endif
  49.   for ( i = 0; i<w->numourpages; i++ )
  50.   { w->newpages[i].addr = ADDR(i)+K32;
  51.     w->newpages[i].access = ACCESS_READWRITE;
  52.     w->ourmem[i+PLACE(K32)] = TAGLOC(DIRTY,i);
  53.   }
  54.   for ( i=w->numourpages+PLACE(K32); i<w->numplaces; i++ )
  55.     w->ourmem[i] = TAGLOC(ABORT, 0);
  56.   for (i=0;i<w->nslots;i++)
  57.     w->index[i] = -1;
  58. }
  59.  
  60. void Finishourmem(WKSP *w)
  61. {
  62.   free(w->oldpages);
  63.   free(w->newpages);
  64.   free(w->ourmem);
  65.   free(w->index);
  66. }
  67.  
  68. int SetVirtualSlot(WKSP *w, int size)
  69. { int i,m;
  70.   i = PLACE(K32);
  71.   m = i + PLACE(size);
  72. #ifdef DEBUG
  73.   printf("Places %d..%d abort->zerofill\n",i,m);
  74. #endif
  75.   for (;i<m;i++)
  76.     if (TAG(w->ourmem[i])==ABORT)
  77.       w->ourmem[i] = TAGLOC(ZERO,0);
  78.   return size;
  79. }
  80.  
  81.  
  82. void virtualmem(WKSP *w)
  83. {
  84.   swi(OS_SetMemMapEntries, IN(R0), w->newpages);
  85. }
  86.  
  87. void normalmem(WKSP *w)
  88. {
  89.   swi(OS_SetMemMapEntries, IN(R0), w->oldpages);
  90. }
  91.  
  92. /* Find us a set of pysical pages, preserving newpages[0..numourpages].addr,access */
  93.  
  94. void FindPages(WKSP *w)
  95. {
  96.   int i;
  97.   int appspace;
  98.   int a, b;
  99.   for (i = 0; i<w->numpages ; i++)
  100.     w->oldpages[i].pagenum = i;
  101.   w->oldpages[w->numpages].pagenum = -1;
  102.   swi(OS_ReadMemMapEntries, IN(R0), w->oldpages);
  103.   swi(OS_ChangeEnvironment, IN(R0|R1)|OUT(R1), 14, 0, &appspace);
  104.   w->numourpages = PLACE(appspace - K32);
  105.   b = w->numourpages;   /* We accumulate pages that must be moved out the way here */
  106.   for (i = 0; i<w->numpages; i++)
  107.   { if (w->oldpages[i].addr < K32)              /* OS workspace will get protected */
  108.       /*w->newpages[b++] = w->oldpages[i] */;
  109.     else if (w->oldpages[i].addr < appspace)    /* Useable page */
  110.     { a = PLACE(w->oldpages[i].addr-K32);       /* its current place */
  111.       w->newpages[a].pagenum = i;               /* it becomes our page */
  112.     }
  113.     else if (w->oldpages[i].addr < M24)         /* page needs moving */
  114.       w->newpages[b++] = w->oldpages[i];
  115.   }
  116.   for (i=0; i<w->numourpages; i++)
  117.   { w->oldpages[i].pagenum = w->newpages[i].pagenum;
  118.     w->oldpages[i].addr = ADDR(i)+K32;
  119.     w->oldpages[i].access = ACCESS_READWRITE;
  120.   }
  121.   for (i = w->numourpages; i<b; i++)
  122.   { w->oldpages[i] = w->newpages[i];
  123.     if (w->newpages[i].addr<K32)
  124.       w->newpages[i].access = ACCESS_READONLY;
  125.     else
  126.     { w->newpages[i].addr = DUMPADDR;
  127.       w->newpages[i].access = ACCESS_BAD;
  128.   } }
  129.   w->oldpages[b].pagenum = -1;
  130.   w->newpages[b].pagenum = -1;
  131. }
  132.  
  133. static int pageout(WKSP *w, int page, int addr)
  134. {
  135.   int place, Normaddr, slot;
  136.   place = PLACE(addr);
  137.   Normaddr = w->oldpages[page].addr;
  138.   slot = LOC(w->ourmem[place]);
  139.   switch (TAG(w->ourmem[place]))
  140.   { case DIRTY:
  141.       for (slot = 0; slot<w->nslots; slot++)
  142.         if (w->index[slot] == -1)
  143.           break;
  144.       if (slot>=w->nslots)
  145.       { w->nslots = slot+1;
  146. #ifdef DEBUG
  147.         printf("nslots = %d\n",w->nslots);
  148. #endif
  149.       }
  150.       swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 1, w->pagefile, Normaddr, w->pagesize, ADDR(slot));
  151.       /* FALL THROUGH */
  152.     case SAVED:
  153.       w->index[slot] = place;
  154.       w->ourmem[place] = TAGLOC(PAGED, slot);
  155.       break;
  156.     default:
  157.       printf("*** ILLEGAL page out tag page %d addr %d place %d Normaddr %d slot %d tag %d\n",
  158.                 page,addr,place,Normaddr,slot,TAG(w->ourmem[place]));
  159.       RealDoOff(w);
  160.       break;
  161.   }
  162. #ifdef DEBUG
  163.   printf("Paging place %d out from page %d to slot %d\n",place,page,slot);
  164. #endif
  165.   return page;
  166. }
  167.  
  168. static int findpageout(WKSP *w)
  169. {
  170.   int addr, page;
  171. loop:
  172.   page = w->losepage;
  173.   if (++w->losepage >= w->numourpages)
  174.     w->losepage = 0;
  175.   addr = w->newpages[page].addr;
  176.   if (addr == DUMPADDR)
  177.     return page;
  178.   if (addr & LOCKADDRBIT)
  179.     goto loop;
  180.   return pageout(w,page,addr);
  181. }
  182.  
  183. static void pagein(WKSP *w, int page, int place, int write)
  184. { int Normaddr = w->oldpages[page].addr;
  185.   int slot = LOC(w->ourmem[place]);
  186.   swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, w->pagefile, Normaddr, w->pagesize, ADDR(slot));
  187.   w->newpages[page].addr = ADDR(place);
  188.   if (write)
  189.   { w->newpages[page].access = ACCESS_READWRITE;
  190.     w->index[slot] = -1;
  191.     w->ourmem[place] = TAGLOC(DIRTY, page);
  192.   }
  193.   else
  194.   { w->newpages[page].access = ACCESS_READONLY;
  195.     w->index[slot] = page;
  196.     w->ourmem[place] = TAGLOC(SAVED, slot);
  197.   }
  198. #ifdef DEBUG
  199.   printf("Paging place %d in to page %d from slot %d %s",place,page,slot,write?"writeable":"readonly");
  200. #endif
  201. }
  202.  
  203. #ifdef FIXED_SYSTEMCALL_VERSION_FO
  204. /*
  205.  * First page out all DIRTY places whose address is not as RISC OS expects
  206.  * Then page in all place which should be in that page.
  207.  */
  208. void FixMemoryPages(WKSP *w)
  209. {
  210.   int i;
  211.   for (i = 0; i < w->numourpages; i++)
  212.     if (w->newpages[i].addr != ADDR(i) + K32 &&
  213.         w->newpages[i].access != ACCESS_BAD)
  214.       switch (TAG(w->ourmem[PLACE(w->newpages[i].addr)])) {
  215.         case DIRTY:
  216.           pageout(w, i, w->newpages[i].addr);
  217.           break;
  218.       } /* switch */
  219.   for (i = 0; i < w->numourpages; i++) {
  220.     if (w->newpages[i].addr != ADDR(i) + K32) {
  221.       switch (TAG(w->ourmem[i+PLACE(K32)])) {
  222.         case PAGED:
  223.           pagein(w, i, i + PLACE(K32), 1);
  224.           break;
  225.         case ZERO:
  226. /*
  227.  * This page was just recieved from the wimp by a wimplsot drag.
  228.  * I'm not really sure if the tag, the place recieves here 
  229.  * should be DIRTY; maybe ZERO is ok. But, to be consistent with Brian's
  230.  * code in SetWimpMemMap, all places paged in at the right page,
  231.  * get the DIRTY tag.
  232.  */
  233.           w->ourmem[i+PLACE(K32)] = TAGLOC(DIRTY, i);
  234.           w->newpages[i].addr = ADDR(i) + K32;
  235.           w->newpages[i].access = ACCESS_READWRITE;
  236.           break;
  237.       } /* switch */
  238.     }
  239.   }
  240. }
  241. #endif
  242.  
  243. void SetRealMem(WKSP*w, int size)
  244. {
  245.   int newnumourpages=PLACE(size);
  246.   int i,newslot;
  247.   if (newnumourpages<2)
  248.     newnumourpages=2;
  249.   if (newnumourpages!=w->numourpages)
  250.  
  251. #ifndef FIXED_SYSTEMCALL_VERSION_FO
  252.   { for (i = w->numourpages; i>newnumourpages; )
  253.     { --i;
  254.       if (w->newpages[i].addr!=DUMPADDR)
  255.         pageout(w, i, w->newpages[i].addr);
  256.     }
  257.     w->numourpages = i;
  258. #else
  259.   { for (i = newnumourpages; i < w->numourpages; i++)
  260.     {
  261.       if (w->newpages[i].addr!=DUMPADDR)
  262.         pageout(w, i, w->newpages[i].addr);
  263.     }
  264. #endif
  265.     swi(Wimp_SlotSize,IN(R0|R1)|OUT(R0),ADDR(newnumourpages),-1,&newslot);
  266.     newnumourpages = PLACE(newslot);
  267.     for (i = w->numourpages; i<newnumourpages; i++)
  268.     { w->newpages[i].addr=DUMPADDR;
  269.       w->newpages[i].access=ACCESS_BAD;
  270.     }
  271. #ifndef FIXED_SYSTEMCALL_VERSION_FO
  272.     w->losepage = w->numourpages<i?w->numourpages:0;
  273.     w->numourpages = i;
  274. #else
  275. /*
  276.  * When the user drags our slotbar, we often will receive more than one
  277.  * wimp_MSETSLOT message at once. In the old code, w->losepage would then
  278.  * be set at the *end* of a big block of DUMPADDR pages. This is a waste.
  279.  * The code below ensures w->losepage is always on the first DUMPADDR page.
  280.  */
  281.     if (w->numourpages < newnumourpages) {
  282.       for (i = 0; i < newnumourpages; i++)
  283.         if (w->newpages[i].addr == DUMPADDR) {
  284.            w->losepage = i;
  285.            break;
  286.         }
  287.     }
  288.     else
  289.       w->losepage = 0;
  290.     w->numourpages = newnumourpages;
  291. #endif
  292.  
  293.   #ifdef DEBUG
  294.     printf("numourpages=%d\n",newnumourpages);
  295.   #endif
  296. } }
  297.  
  298. static int GetPlace(WKSP *w, int pl