Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields  

ToyMemPage.c

00001 /***************************************************************************
00002                           ToyMemPage.c  -  Implements the extra commands
00003     available in Paged mode.
00004                              -------------------
00005     begin                : Thu Feb 20 2003
00006     copyright            : (C) 2003 by Tyler Montbriand
00007     student #            : 200200370
00008     class                : CS330
00009     email                : monttyle@heavyspace.ca
00010  ***************************************************************************/
00011 #include<malloc.h>
00012 #include<string.h>
00013 #include<stdio.h>
00014 
00015 #include "ToySegment.h"
00016 #include "ToySegmentList.h"
00017 #include "ToyProcess.h"
00018 #include "ToyMemType.h"
00019 #include "ToyMem.h"
00020 #include "ToyMem_Internal.h"
00021 #include "ToyLoad.h"
00022 #include "ToyMemPage.h"
00023 #include "ToyVirtualMem.h"
00024 #include "ToySwap.h"
00025 
00026 
00027 /* Glue functions */
00028 void TMM_PrintInvPage(ToyMM *tmm, int frame, int show_framestatus);
00029 ErrMessage_t TMM_FindNextSegPos(ToyMM *,int,int *, int *, int *);
00030 
00032 ErrMessage_t TMM_PrintPages(ToyMM *tm, int process)
00033 {
00034   int n=-1;
00035   int numpages;
00036   Process *proc=NULL;
00037 
00038   if(tm==NULL)                                  return(ERR_UNKNOWN);
00039   else if((process<0)||(process>=MAX_PROCESSES))return(ERR_UNKNOWN);
00040   else if(tm->processList[process]==NULL)       return(ERR_NOPROCESS);
00041   if(TMM_PagingEnabled(tm)<0)                   return(ERR_NOPAGING);
00042 
00043   printf(LINE_RULE);
00044   printf(LINE_PREFIX"Page Table for Process P%d:\n",process);
00045   printf(LINE_PREFIX"PAGE#  FRAME# PageStatus\n");
00046   printf(LINE_PREFIX"-----  ------ ----------\n");
00047 
00048   proc=tm->processList[process];
00049 
00050   numpages=TMM_GetNumPages(tm);
00051 
00052   for(n=0; n<numpages; n++)
00053   {
00054     PageTable ptable=proc->pagetable[n];
00055     if(TMM_PageFree(tm,process,n)<0)    
00056     {
00057       if(TMM_PageSwappedOut(tm,process,n)>=0)
00058       {
00059         printf(LINE_PREFIX"%5d  %6s   %s\n",n,"-","Disk");
00060       }
00061       else
00062       {
00063         printf(LINE_PREFIX"%5d  %6d   %s\n",n,ptable.frame,"Memory");        
00064       }
00065     }
00066   }
00067 
00068   printf(LINE_RULE);
00069 
00070   return(ERR_NONE);
00071 }
00072 
00074 ErrMessage_t TMM_PrintFrames(ToyMM *tmm)
00075 {
00076   int n;
00077   if(tmm==NULL)               return(ERR_UNKNOWN);
00078   if(TMM_PagingEnabled(tmm)<0)return(ERR_NOPAGING);
00079 
00080   printf(LINE_RULE);
00081   printf(LINE_PREFIX"Inverted Page Table:\n");
00082   printf(LINE_PREFIX"FRAME#  PID PAGE# FrameStatus\n");
00083   printf(LINE_PREFIX"------  --- ----- -----------\n");
00084 
00085   for(n=0; n<TMM_GetNumPages(tmm); n++)
00086   {
00087     TMM_PrintInvPage(tmm,n,1);
00088   }
00089 
00090   printf(LINE_RULE);
00091   return(ERR_NONE);
00092 }
00093 
00095 ErrMessage_t TMM_WatchPaging(ToyMM *tmm, int process, int enable)
00096 {
00097   if(tmm==NULL)        return(ERR_UNKNOWN);
00098   else if(process!=0)  return(ERR_UNKNOWN);
00099 
00100   if(enable==0)  /* turn off page watching */
00101   {
00102     tmm->watchPaging=0;
00103     return(ERR_NONE);
00104   }
00105   else if(enable==1)  /* turn on page watching */
00106   {
00107     tmm->watchPaging=1;
00108     return(ERR_NONE);
00109   }
00110   else  /* Only 0 or 1 are valid. */
00111   {
00112     return(ERR_INVALIDINPUT);
00113   }
00114 }
00115 
00116 
00118 ErrMessage_t TMM_EnablePaging(ToyMM *tm, int process, int pagesize)
00119 {
00120   int n;
00121 
00122   if(tm==NULL)        return(ERR_UNKNOWN);
00123   else if(process!=0) return(ERR_NOENABLEPAGEPRIVELEGE);
00124   else if((tm->memSize%pagesize!=0)||(pagesize>=tm->memSize))
00125   { /*  Memory must be evenly divisible by page size  */
00126     return(ERR_INVALIDPAGESIZE);
00127   }
00128 
00129   /*  Kill all processes */
00130   for(n=1; n<MAX_PROCESSES; n++)  
00131   if(tm->processList[n]!=NULL)
00132   {
00133     TMM_TerminateProcess(tm,n);
00134   }
00135 
00136   /* We don't use the global free-list in Paged mode */
00137   if(tm->memFree!=NULL)  TMM_FreeSegList(tm->memFree);
00138   tm->memFree=NULL;  
00139 
00140   /*  Create inverted page table  */
00141   tm->invPageTable=(InvPageTable *)malloc(sizeof(InvPageTable)*(tm->memSize/pagesize));
00142 
00143   /*  Couldn't allocate memory  */
00144   if(tm->invPageTable==NULL)
00145   {
00146     return(ERR_UNKNOWN);
00147   }
00148 
00149   /*  Set page size */
00150   tm->pageSize=pagesize;
00151 
00152   /*  Mark all pages as free. */
00153   for(n=0; n<TMM_GetNumPages(tm); n++)
00154   {
00155     tm->invPageTable[n].ID=-1;
00156     tm->invPageTable[n].status=0;
00157     tm->invPageTable[n].page=-1;    
00158   }
00159 
00160   /* Create swap file LAST */
00161   if(TMM_SwapCreate(tm)<0)
00162   {
00163     return(ERR_UNKNOWN);
00164   }
00165 
00166   tm->page=0;
00167 
00168   
00169   return(ERR_NONE);
00170 }
00171 
00172 ErrMessage_t TMM_PrintInvertedPageTable(ToyMM *tmm, int process)
00173 {
00174   int n;
00175   if(tmm==NULL)       return(ERR_UNKNOWN);
00176 
00177   printf(LINE_RULE);
00178   printf(LINE_PREFIX"Inverted Page Table:\n");
00179   printf(LINE_PREFIX"FRAME#  PID PAGE#\n");
00180   printf(LINE_PREFIX"------  --- -----\n");
00181 
00182   for(n=0; n<TMM_GetNumPages(tmm); n++)
00183   {
00184     TMM_PrintInvPage(tmm,n,0);
00185   }
00186 
00187   printf(LINE_RULE);
00188   return(ERR_NONE);  
00189 }
00190 
00192 ErrMessage_t TMM_PagedAllocateSegment(ToyMM *tmm, int process, int size)
00193 {
00194   SegList *newnode=NULL;
00195 
00196   int pages=-1;  
00197   int page=0;
00198   int seg=SEG_CODE;
00199   Process *proc=NULL;
00200   
00201   if(tmm==NULL)                             return(ERR_UNKNOWN);
00202   else if(tmm->processList[process]==NULL)  return(ERR_NOPROCESS);
00203 
00204   proc=tmm->processList[process];
00205 
00206   if(TMM_FindNextSegPos(tmm,process,&seg,&page,&size)!=ERR_NONE)
00207   {
00208     return(ERR_UNKNOWN);
00209   }
00210 
00211   pages=TMM_GetNumFrames(tmm,size);
00212 
00213   /* Loop through frames in segment, assigning frames to the new process */
00214   while(pages>0)
00215   {
00216     /* Commented out because we don't want to load frames in
00217        TMM_PagedAllocateSegment, but TMM_Load */
00218 /*    n=TMM_FindFreeFrame(tmm);
00219     if(n<0) break;
00220     TMM_AssignFrame(tmm,process,n,page);*/
00221     page++;
00222     pages--;    
00223   }
00224 
00225   page-=TMM_GetNumFrames(tmm,size);
00226 
00227   if(pages!=0)
00228   {
00229     /* Couldn't allocate every page */
00230     return(ERR_INSUFFICIENTMEM);
00231   }
00232 
00233   /* Create node representing new segment in ToyMM */
00234   newnode=TMM_CreateSegList(page*tmm->pageSize,size,NULL,NULL);
00235   if(newnode==NULL) return(ERR_UNKNOWN);
00236   /* Add new segment to list */
00237   proc->segments=TMM_AppendSegList(proc->segments,newnode);
00238   
00239   return(ERR_NONE);
00240 }
00241 
00243 ErrMessage_t TMM_PagedAllocateProcess(ToyMM *tmm, int ID, int nSegs, int sizes[])
00244 {
00245   int n=-1;
00246   int newsizes[]={1,1,1,1};
00247   int numpages;
00248   Process *proc=NULL;
00249   SegList *list=NULL;
00250   
00251   /*  Can't allocate process in nonexistent TMM */
00252   if(tmm==NULL) return(ERR_UNKNOWN);
00253   /*  Can't allocate negative or out-of-bounds processes  */
00254   else if((ID<0)||(ID>=MAX_PROCESSES))  return(ERR_UNKNOWN);
00255   else if(tmm->processList[ID]!=NULL)
00256   { /*  Can't replace existing process */
00257     return(ERR_PROCESSEXISTS);
00258   }
00259 
00260   /*  Create empty process  */  
00261   proc=(Process *)malloc(sizeof(Process));
00262   if(proc==NULL)  return(ERR_UNKNOWN);
00263 
00264   numpages=TMM_GetNumPages(tmm);
00265 
00266   proc->ID=ID;
00267   proc->freeheap=proc->usedheap=proc->ptr=NULL;
00268   proc->segments=NULL;
00269   proc->pagetable=(PageTable *)malloc(sizeof(PageTable)*numpages);
00270   
00271   for(n=0; n<numpages; n++)
00272   {
00273     proc->pagetable[n].frame=-1;
00274     proc->pagetable[n].paged=0;
00275   }  
00276 
00277   /*  Put the process in the Toy Memory Manager.  */
00278   tmm->processList[ID]=proc;
00279 
00280   for(n=0; n<nSegs; n++)
00281   {
00282     newsizes[n]=sizes[n];
00283   }
00284 
00285   /*  For each segment  */
00286   for(n=0; n<=SEG_STACK; n++)
00287   {
00288     if(TMM_PagedAllocateSegment(tmm,ID,newsizes[n])!=ERR_NONE)
00289     {
00290       TMM_PagedTerminateProcess(tmm,ID);
00291       return(ERR_INSUFFICIENTMEM);
00292     }        
00293   }
00294 
00295   /* Get the Heap segment */
00296   list=TMM_GetSegmentNode(tmm,ID,SEG_HEAP);
00297 
00298   /* Make a copy of it and put it in the freeheap */
00299   proc->freeheap=TMM_CreateSegList(list->seg.pos,list->seg.len,NULL,NULL);
00300   proc->ptr=proc->freeheap;
00301   proc->usedheap=NULL;
00302 
00303   return(ERR_NONE);  
00304 }
00305 
00307 ErrMessage_t TMM_PrintPageTable(ToyMM *tm, int process)
00308 {
00309   int n=-1;
00310   int numpages;
00311   Process *proc=NULL;
00312   if(tm==NULL)                                  return(ERR_UNKNOWN);
00313   else if((process<0)||(process>=MAX_PROCESSES))return(ERR_UNKNOWN);
00314   else if(tm->processList[process]==NULL)       return(ERR_NOPROCESS);
00315 
00316   printf(LINE_RULE);
00317   printf(LINE_PREFIX"Page Table for Process P%d:\n",process);
00318   printf(LINE_PREFIX"PAGE#  FRAME#\n");
00319   printf(LINE_PREFIX"-----  ------\n");
00320 
00321   proc=tm->processList[process];
00322 
00323   numpages=TMM_GetNumPages(tm);
00324 
00325   for(n=0; n<numpages; n++)
00326   {
00327     if(proc->pagetable[n].frame!=-1)
00328     {
00329       printf(LINE_PREFIX"%5d  %6d\n",n,proc->pagetable[n].frame);
00330     }
00331   }
00332   
00333   printf(LINE_RULE);
00334   
00335   return(ERR_NONE);
00336 }
00337 
00339 ErrMessage_t TMM_PagedTerminateProcess(ToyMM *tm, int process)
00340 {
00341   int n=-1;
00342   int numpages;
00343   
00344   Process *proc=NULL;
00345 
00346   if(tm==NULL)                             return(ERR_UNKNOWN);
00347   else if(tm->processList[process]==NULL)  return(ERR_NOPROCESS);
00348   
00349   proc=tm->processList[process];
00350 
00351   /*  Free list of segments */
00352   if(proc->segments!=NULL)
00353   {
00354     TMM_FreeSegList(proc->segments);
00355     proc->segments=NULL;
00356   }
00357 
00358   if(proc->freeheap!=NULL)
00359   {
00360     TMM_FreeSegList(proc->freeheap);
00361     proc->freeheap=NULL;
00362   }
00363 
00364   if(proc->usedheap!=NULL)
00365   {
00366     TMM_FreeSegList(proc->usedheap);
00367     proc->usedheap=NULL;
00368   }
00369 
00370   numpages=TMM_GetNumPages(tm);
00371 
00372   /*  Mark frames as free */
00373   for(n=0; n<numpages; n++)
00374   {
00375     if((proc->pagetable[n].frame!=-1)&&(proc->pagetable[n].paged==0))
00376     {
00377       TMM_FreeFrame(tm,process,n);
00378     }
00379     else
00380     {
00381       proc->pagetable[n].frame=-1;
00382       proc->pagetable[n].paged=0;
00383     }
00384   }
00385   
00386   /* Remove from process list */
00387   tm->processList[process]=NULL;
00388 
00389   if(proc->pagetable!=NULL)
00390   {
00391     free(proc->pagetable);
00392   }  
00393 
00394   /* Free the process struct itself */
00395   free(proc);
00396   
00397   return(ERR_NONE);
00398 }
00399 
00401 void TMM_PrintInvPage(ToyMM *tmm, int frame, int show_framestatus)
00402 {
00403   /* Special case - printing unused page when scanning pointer matches */
00404   if((tmm->invPageTable[frame].ID<0)  &&
00405      (frame==tmm->page)              &&
00406      (show_framestatus)                   )
00407   {
00408     printf(LINE_PREFIX"%6d  %3d %5d %11d *\n",frame,0,0,0);
00409     return;
00410   }
00411   else if(show_framestatus)
00412   {
00413     if((frame!=tmm->page)&&(tmm->invPageTable[frame].ID==-1))  return;
00414     printf(LINE_PREFIX"%6d  %3d %5d %11d",frame,
00415                                           tmm->invPageTable[frame].ID,
00416                                           tmm->invPageTable[frame].page,
00417                                           tmm->invPageTable[frame].status
00418                                           );
00419 
00420     if(frame==tmm->page)  printf(" *");
00421     printf("\n");
00422   }
00423   else
00424   {
00425     if(tmm->invPageTable[frame].ID==-1) return;
00426 
00427     printf(LINE_PREFIX"%6d  %3d %5d\n",frame,tmm->invPageTable[frame].ID,
00428                                        tmm->invPageTable[frame].page);
00429   }
00430 }
00431 
00432 
00434 ErrMessage_t TMM_PagedAddSegment(ToyMM *tmm, int process, int pos, int len)
00435 {
00436   SegList *node=NULL;
00437   if(tmm==NULL)                             return(ERR_UNKNOWN);
00438   else if(TMM_PagingEnabled(tmm)<0)         return(ERR_UNKNOWN);
00439   else if((pos<0)||(len<=0))      return(ERR_UNKNOWN);
00440   else if(tmm->processList[process]==NULL)  return(ERR_NOPROCESS);
00441 
00442   node=TMM_CreateSegList(pos,len,NULL,NULL);
00443   tmm->processList[process]->segments=TMM_AppendSegList(tmm->processList[process]->segments,node);
00444 
00445   return(ERR_NONE);
00446 }
00447 
00448 /* \brief Returns the page #, segment #, and size of what the next segment should be. */
00449 ErrMessage_t TMM_FindNextSegPos(ToyMM *tmm, int process, int *seg, int *page, int *size)
00450 {
00451   SegList *list=NULL;
00452   (*seg)=SEG_CODE;
00453 
00454   if((tmm==NULL)||(page==NULL)||(size==NULL)||(seg==NULL)) return(ERR_UNKNOWN);
00455   else if(tmm->processList[process]==NULL)                 return(ERR_NOPROCESS);
00456 
00457   (*page)=0;
00458   (*seg)=0;
00459 
00460   list=tmm->processList[process]->segments;
00461   while(list!=NULL)
00462   {
00463     (*page)=(list->seg.pos/tmm->pageSize)+TMM_GetFramedSize(tmm,list->seg.len)/(tmm->pageSize);
00464     list=list->next;
00465     (*seg)++;
00466   }
00467 
00468   switch(*seg)
00469   { /*  Don't do anything special for code/data segs  */
00470   case SEG_CODE:
00471   case SEG_DATA:
00472     break;
00473 
00474   /*  Stack segment must be bottom-up and one page in size */
00475   case SEG_STACK:
00476     (*page)=(TMM_GetNumPages(tmm))-1;
00477     (*size)=tmm->pageSize;
00478     break;
00479 
00480   /*  Heap segment must be one page in size */
00481   case SEG_HEAP:
00482     (*size)=tmm->pageSize;
00483     break;
00484 
00485   /*  Can't have more than 4 segments */
00486   default:
00487     return(ERR_UNKNOWN);
00488   }
00489 
00490   return(ERR_NONE);
00491 }

Generated on Fri Apr 4 14:29:07 2003 for ToyMem by doxygen1.3-rc3