home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / utilities / virtual / !Virtual / c / pager < prev    next >
Encoding:
Text File  |  1992-07-27  |  10.9 KB  |  458 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.   w->pageshift = w->pagesize == K32 ? 15 : 13;
  19.   w->numplaces = PLACE(M24);
  20.   w->ourmem = alloc(sizeof(int) * w->numplaces);
  21.  
  22.   w->oldpages = alloc(sizeof(PAGEENTRY)*(w->numpages + 1));
  23.   w->newpages = alloc(sizeof(PAGEENTRY)*(w->numpages + 1));
  24.   FindPages(w);
  25.  
  26.   w->nslots = 0;        /* page file empty */
  27.   w->index = alloc(sizeof(int)*w->numplaces);
  28.  
  29.   for ( i=PLACE(K32); i<w->numplaces; i++)
  30.   { w->ourmem[i] = TAGLOC(ABORT, 0);
  31.   }
  32.   w->losepage = 0;
  33. }
  34.  
  35. void SetWimpMemMap(WKSP *w)
  36. {
  37.   int i;
  38. #ifdef DEBUG
  39.   printf("Places %d..%d match wimp map\n",PLACE(K32),w->numourpages+PLACE(K32));
  40. #endif
  41.   for ( i = 0; i<w->numourpages; i++ )
  42.   { w->newpages[i].addr = ADDR(i)+K32;
  43.     w->newpages[i].access = ACCESS_READWRITE;
  44.     w->ourmem[i+PLACE(K32)] = TAGLOC(DIRTY,i);
  45.   }
  46.   for ( i=w->numourpages+PLACE(K32); i<w->numplaces; i++ )
  47.     w->ourmem[i] = TAGLOC(ABORT, 0);
  48.   for (i=0;i<w->nslots;i++)
  49.     w->index[i] = -1;
  50. }
  51.  
  52. void Finishourmem(WKSP *w)
  53. {
  54.   free(w->oldpages);
  55.   free(w->newpages);
  56.   free(w->ourmem);
  57.   free(w->index);
  58. }
  59.  
  60. int SetVirtualSlot(WKSP *w, int size)
  61. { int i,m;
  62.   i = PLACE(K32);
  63.   m = i + PLACE(size);
  64. #ifdef DEBUG
  65.   printf("Places %d..%d abort->zerofill\n",i,m);
  66. #endif
  67.   for (;i<m;i++)
  68.     if (TAG(w->ourmem[i])==ABORT)
  69.       w->ourmem[i] = TAGLOC(ZERO,0);
  70.   return size;
  71. }
  72.  
  73. void virtualmem(WKSP *w)
  74. {
  75.   swi(OS_SetMemMapEntries, IN(R0), w->newpages);
  76. }
  77.  
  78. void normalmem(WKSP *w)
  79. {
  80.   swi(OS_SetMemMapEntries, IN(R0), w->oldpages);
  81. }
  82.  
  83. /* Find us a set of pysical pages, preserving newpages[0..numourpages].addr,access */
  84.  
  85. void FindPages(WKSP *w)
  86. {
  87.   int i;
  88.   int appspace;
  89.   int a, b;
  90.   for (i = 0; i<w->numpages ; i++)
  91.     w->oldpages[i].pagenum = i;
  92.   w->oldpages[w->numpages].pagenum = -1;
  93.   swi(OS_ReadMemMapEntries, IN(R0), w->oldpages);
  94.   swi(OS_ChangeEnvironment, IN(R0|R1)|OUT(R1), 14, 0, &appspace);
  95.   w->numourpages = PLACE(appspace - K32);
  96.   b = w->numourpages;   /* We accumulate pages that must be moved out the way here */
  97.   for (i = 0; i<w->numpages; i++)
  98.   { if (w->oldpages[i].addr < K32)              /* OS workspace will get protected */
  99.       /*w->newpages[b++] = w->oldpages[i] */;
  100.     else if (w->oldpages[i].addr < appspace)    /* Useable page */
  101.     { a = PLACE(w->oldpages[i].addr-K32);       /* its current place */
  102.       w->newpages[a].pagenum = i;               /* it becomes our page */
  103.     }
  104.     else if (w->oldpages[i].addr < M24)         /* page needs moving */
  105.       w->newpages[b++] = w->oldpages[i];
  106.   }
  107.   for (i=0; i<w->numourpages; i++)
  108.   { w->oldpages[i].pagenum = w->newpages[i].pagenum;
  109.     w->oldpages[i].addr = ADDR(i)+K32;
  110.     w->oldpages[i].access = ACCESS_READWRITE;
  111.   }
  112.   for (i = w->numourpages; i<b; i++)
  113.   { w->oldpages[i] = w->newpages[i];
  114.     if (w->newpages[i].addr<K32)
  115.       w->newpages[i].access = ACCESS_READONLY;
  116.     else
  117.     { w->newpages[i].addr = DUMPADDR;
  118.       w->newpages[i].access = ACCESS_BAD;
  119.   } }
  120.   w->oldpages[b].pagenum = -1;
  121.   w->newpages[b].pagenum = -1;
  122. }
  123.  
  124. static int pageout(WKSP *w, int page, int addr)
  125. {
  126.   int place, Normaddr, slot;
  127.   place = PLACE(addr);
  128.   Normaddr = w->oldpages[page].addr;
  129.   slot = LOC(w->ourmem[place]);
  130.   switch (TAG(w->ourmem[place]))
  131.   { case DIRTY:
  132.       for (slot = 0; slot<w->nslots; slot++)
  133.         if (w->index[slot] == -1)
  134.           break;
  135.       if (slot>=w->nslots)
  136.       { w->nslots = slot+1;
  137. #ifdef DEBUG
  138.         printf("nslots = %d\n",w->nslots);
  139. #endif
  140.       }
  141.       swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 1, w->pagefile, Normaddr, w->pagesize, ADDR(slot));
  142.       /* FALL THROUGH */
  143.     case SAVED:
  144.       w->index[slot] = place;
  145.       w->ourmem[place] = TAGLOC(PAGED, slot);
  146.       break;
  147.     default:
  148.       printf("*** ILLEGAL page out tag page %d addr %d place %d Normaddr %d slot %d tag %d\n",
  149.                 page,addr,place,Normaddr,slot,TAG(w->ourmem[place]));
  150.       RealDoOff(w);
  151.       break;
  152.   }
  153. #ifdef DEBUG
  154.   printf("Paging place %d out from page %d to slot %d\n",place,page,slot);
  155. #endif
  156.   return page;
  157. }
  158.  
  159. static int findpageout(WKSP *w)
  160. {
  161.   int addr, page;
  162. loop:
  163.   page = w->losepage;
  164.   if (++w->losepage >= w->numourpages)
  165.     w->losepage = 0;
  166.   addr = w->newpages[page].addr;
  167.   if (addr == DUMPADDR)
  168.     return page;
  169.   if (addr & LOCKADDRBIT)
  170.     goto loop;
  171.   return pageout(w,page,addr);
  172. }
  173.  
  174. static void pagein(WKSP *w, int page, int place, int write)
  175. { int Normaddr = w->oldpages[page].addr;
  176.   int slot = LOC(w->ourmem[place]);
  177.   swi(OS_GBPB, IN(R0|R1|R2|R3|R4), 3, w->pagefile, Normaddr, w->pagesize, ADDR(slot));
  178.   w->newpages[page].addr = ADDR(place);
  179.   if (write)
  180.   { w->newpages[page].access = ACCESS_READWRITE;
  181.     w->index[slot] = -1;
  182.     w->ourmem[place] = TAGLOC(DIRTY, page);
  183.   }
  184.   else
  185.   { w->newpages[page].access = ACCESS_READONLY;
  186.     w->index[slot] = page;
  187.     w->ourmem[place] = TAGLOC(SAVED, slot);
  188.   }
  189. #ifdef DEBUG
  190.   printf("Paging place %d in to page %d from slot %d %s",place,page,slot,write?"writeable":"readonly");
  191. #endif
  192. }
  193.  
  194. void SetRealMem(WKSP*w, int size)
  195. {
  196.   int newnumourpages=PLACE(size);
  197.   int i,newslot;
  198.   if (newnumourpages<2)
  199.     newnumourpages=2;
  200.   if (newnumourpages!=w->numourpages)
  201.   { for (i = w->numourpages; i>newnumourpages; )
  202.     { --i;
  203.       if (w->newpages[i].addr!=DUMPADDR)
  204.         pageout(w, i, w->newpages[i].addr);
  205.     }
  206.     w->numourpages = i;
  207.     swi(Wimp_SlotSize,IN(R0|R1)|OUT(R0),ADDR(newnumourpages),-1,&newslot);
  208.     newnumourpages = PLACE(newslot);
  209.     for (i = w->numourpages; i<newnumourpages; i++)
  210.     { w->newpages[i].addr=DUMPADDR;
  211.       w->newpages[i].access=ACCESS_BAD;
  212.     }
  213.     w->losepage = w->numourpages<i?w->numourpages:0;
  214.     w->numourpages = i;
  215.   #ifdef DEBUG
  216.     printf("numourpages=%d\n",i);
  217.   #endif
  218. } }
  219.  
  220. static int GetPlace(WKSP *w, int place, int write)
  221. { int page,slot;
  222.   page = LOC(w->ourmem[place]);
  223.   switch (TAG(w->ourmem[place]))
  224.   {
  225.     case SAVED:
  226.       slot = page;
  227.       page = w->index[slot];
  228.       if (!write)
  229.         return page;
  230.       w->newpages[page].access = ACCESS_READWRITE;
  231.       w->index[slot] = -1;
  232.       w->ourmem[place]=TAGLOC(DIRTY,page);
  233. #ifdef DEBUG
  234. printf("Dirtying place %d in page %d free slot %d\n",place,page,slot);
  235. #endif
  236.       if ( slot == w->nslots-1 ) /* last slot in file freed */
  237.       { while (slot>=0 && w->index[slot]==-1)
  238.           slot--;
  239.         w->nslots = slot+1;
  240.         swi(OS_Args,IN(R0|R1|R2),3,w->pagefile,ADDR(w->nslots));
  241. #ifdef DEBUG
  242.         printf("nslots down = %d\n",w->nslots);
  243. #endif
  244.       }
  245.       return page;
  246.     case PAGED:
  247.       page=findpageout(w);
  248.       pagein(w, page, place, write);
  249.       return page;
  250.     case ZERO:
  251.       page=findpageout(w);
  252.       w->ourmem[place] = TAGLOC(DIRTY, page);
  253.       w->newpages[page].addr = ADDR(place);
  254.       w->newpages[page].access = ACCESS_READWRITE;
  255. #ifdef DEBUG
  256. printf("Place %d gets page %d zeroed",place,page);
  257. #endif
  258.       return page;
  259.     case DIRTY:
  260.       return page;
  261.     case ABORT:
  262.       printf("***ABORT: place %d\n",place);
  263.       return -1;
  264.     default:
  265.       printf("***ILLEGAL tag: place %d in page %d tag %d\n",place,page,TAG(w->ourmem[place]));
  266.       RealDoOff(w);
  267.       return -1;
  268.   }
  269. }
  270.  
  271. static int VGetPlace(WKSP *w, int place, int write)
  272. { int page;
  273.   switch (TAG(w->ourmem[place]))
  274.   { case DIRTY:
  275.       return LOC(w->ourmem[place]);
  276.     case SAVED:
  277.       if (!write)
  278.         return LOC(w->ourmem[place]);
  279.     default:
  280.       Normal(w);
  281.       page = GetPlace(w,place,write);
  282.       Virtual(w);
  283.       return page;
  284.   }
  285. }
  286.  
  287. RANGE Locate(WKSP *w, int start, int end)
  288. { int place,page;
  289.   RANGE r;
  290. #ifdef DEBUG
  291.   printf("Locate: %x-%x",start,end);
  292. #endif
  293.   if (start<K32)
  294.     return r.start=start,r.end=end<K32?end:K32,r;
  295.   if (start>=M24)
  296.     return r.start=start,r.end=end,r;
  297.   place=PLACE(start);
  298.   page=LOC(w->ourmem[place]);
  299.   switch (TAG(w->ourmem[place]))
  300.   {
  301.     case DIRTY:
  302.     case SAVED:
  303.       r.start=w->oldpages[page].addr+SHUFT(start);
  304.       break;
  305.     case ZERO:
  306.       r.start = 0;
  307.       break;
  308.     case ABORT:
  309.       r.start = -1;
  310.       break;
  311.     case PAGED:
  312.       r.start = (1u<<31) + ADDR(page) + SHUFT(start);
  313.       break;
  314.   }
  315.   r.end = r.start + w->pagesize - SHUFT(start);
  316.   if (r.end>r.start+end-start)
  317.     r.end = r.start+end-start;
  318. #ifdef DEBUG
  319.   printf("==>%x-%x\n",r.start,r.end);
  320. #endif
  321.   return r;
  322. }
  323.  
  324. RANGE Physical(WKSP *w, int start, int end)
  325. { int place,page;
  326.   RANGE r;
  327. #ifdef DEBUG
  328.   printf("Physical: %x-%x",start,end);printflush(w);
  329. #endif
  330.   if (end<start)
  331.     RealDoOff(w);
  332.   if (start<K32)
  333.     return r.start=start,r.end=end<K32?end:K32,r;
  334.   if (start>=M24)
  335.     return r.start=start,r.end=end,r;
  336.   place=PLACE(start);
  337.   page=GetPlace(w,place,1);
  338.   if (page==-1)
  339.     return r.start=0,r.end=0,r;
  340.   r.start=w->oldpages[page].addr+SHUFT(start);
  341.   r.end = w->oldpages[page].addr+w->pagesize;
  342.   if (r.end>r.start+end-start)
  343.     r.end = r.start+end-start;
  344. #ifdef DEBUG
  345.   printf("==>%x-%x\n",r.start,r.end); printflush(w);
  346. #endif
  347.   return r;
  348. }
  349.  
  350. int ToMem(WKSP *w, void *src, int dest, int size)
  351. { RANGE r;
  352.   int l;
  353.   while (size>0)
  354.   { r = Physical(w, dest, dest+size);
  355.     if (!r.end)
  356.       return 0;
  357.     l=r.end-r.start;
  358.     memcpy((void*)r.start,src,l);
  359.     src=(char*)src+l;
  360.     dest+=l;
  361.     size-=l;
  362.   }
  363.   return 1;
  364. }
  365.  
  366. int FromMem(WKSP *w, int src, void *dest, int size)
  367. { RANGE r;
  368.   int l;
  369.   while (size>0)
  370.   { r = Physical(w, src, src+size);
  371.     if (!r.end)
  372.       return 0;
  373.     l=r.end-r.start;
  374.     memcpy(dest,(void *)r.start,l);
  375.     src+=l;
  376.     dest=(char*)dest+l;
  377.     size-=l;
  378.   }
  379.   return 1;
  380. }
  381.  
  382.  
  383. /* Called in virtual, svc mode to ensure range all accessable */
  384.  
  385. int ReadRange(WKSP *w, int start, int end)
  386. {
  387.   int place1,place2,page1,page2;
  388.   if (start<K32)
  389.     return 0;
  390.   if (start>=M24)
  391.     return 1;
  392.   if (end>M24)
  393.     end=M24;
  394.   place1 = PLACE(start);
  395.   place2 = PLACE(end-1);
  396.   page1=VGetPlace(w,place1,0);
  397.   if (page1==-1)
  398.     return 0;
  399.   if (place2!=place1)
  400.   { w->newpages[page1].addr |= LOCKADDRBIT;
  401.     page2 = VGetPlace(w,place2,0);
  402.     w->newpages[page1].addr &= ~LOCKADDRBIT;
  403.     if (page2==-1)
  404.       return 0;
  405.   }
  406.   return 1;
  407. }
  408.  
  409. int WriteRange(WKSP *w, int start, int end)
  410. {
  411.   int place1,place2,page1,page2;
  412.   if (start<K32)
  413.     return 0;
  414.   if (start>=M24)
  415.     return 1;
  416.   if (end>M24)
  417.     end=M24;
  418.   place1 = PLACE(start);
  419.   place2 = PLACE(end-1);
  420.   page1=VGetPlace(w,place1,1);
  421.   if (page1==-1)
  422.     return 0;
  423.   if (place2!=place1)
  424.   { w->newpages[page1].addr |= LOCKADDRBIT;
  425.     page2 = VGetPlace(w,place2,1);
  426.     w->newpages[page1].addr &= ~LOCKADDRBIT;
  427.     if (page2==-1)
  428.       return 0;
  429.   }
  430.   return 1;
  431. }
  432.  
  433. int ReadPtr(WKSP *w, int start)
  434. { int place,page;
  435.   if (start<K32)
  436.     return 0;
  437.   if (start>=M24)
  438.     return 1;
  439.   place = PLACE(start);
  440.   page=VGetPlace(w,place,0);
  441.   if (page==-1)
  442.     return 0;
  443.   return 1;
  444. }
  445.  
  446. int WritePtr(WKSP *w, int start)
  447. { int place,page;
  448.   if (start<K32)
  449.     return 0;
  450.   if (start>=M24)
  451.     return 1;
  452.   place = PLACE(start);
  453.   page=VGetPlace(w,place,1);
  454.   if (page==-1)
  455.     return 0;
  456.   return 1;
  457. }
  458.