Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields  

ToyMemHeap.c

00001 /***************************************************************************
00002                           ToyMemHeap.c  -  Heap allocation code for the
00003     toy memory manager
00004                              -------------------
00005     begin                : Mon Feb 3 2003
00006     copyright            : (C) 2003 by Tyler Montbriand
00007     student #            : 200200370
00008     class                : CS330
00009     email                : monttyle@heavyspace.ca
00010 ***************************************************************************/
00011 
00012 #include <malloc.h>
00013 #include <string.h>
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 
00017 #include "ToySegment.h"
00018 #include "ToySegmentList.h"
00019 #include "ToyProcess.h"
00020 #include "ToyMemType.h"
00021 #include "ToyMem.h"
00022 #include "ToyMem_Internal.h"
00023 #include "ToyLoad.h"
00024 #include "ToyVirtualMem.h"
00025 
00026 #define MIN_SIZE 1
00027 
00028 #define WRAP_LEN strlen("-> [140 9] -> [149 0 (1)] -> [154 2] -> [156 9] -> ")
00029 
00030 /*  Glue functions */
00031 
00032 /* Inserts a space hole into the process' free list */
00033 SegList *TMM_InsertSpaceHole(Process *proc, SegList *hole);
00034 /*  Lie ptr=ptr->next, except rewinds to head when it hits the end  */
00035 SegList *TMM_CircularNext(Process *proc);
00036 /*  Deletes a space hole from the list, ensuring proc->ptr is still valid */
00037 SegList *TMM_DeleteSpaceHole(Process *proc, SegList *hole);
00038 /*  Attempts to find a block of 'size' length in the process' free list */
00039 SegList *TMM_FindInFreeList(ToyMM *tmm, Process *proc, int size);
00040 /*  Attempts to find a segment beginning at 'address' in the list */
00041 SegList *TMM_FindAddressInList(SegList *list, int address);
00042 /*  Merges segment with segment below, ensuring proc->ptr is still valid  */
00043 void TMM_MergeAt(Process *proc, SegList *list);
00044 /*  Prints a properly formatted and linewrapped list of segments  */
00045 int PrintSegList(SegList *list, const char *title, char *prefix);
00046 int PrintFreeHeap(Process *proc);
00047 int TMM_FindProcess(ToyMM *tmm, Process *proc);
00048 int TMM_MinSize(int size);
00049 SegList *TMM_EnlargeHeap(ToyMM *tmm, int process, int size);
00050 
00051 
00052 
00057 ErrMessage_t TMM_StoreHeapString(ToyMM *tm, int process, int addr, const char *str)
00058 {
00059   SegList *list=NULL;
00060   Process *proc=NULL;
00061   int raddr=-1;
00062   if(tm==NULL)  return(ERR_UNKNOWN);
00063   if((process<0)||(process>=MAX_PROCESSES)) return(ERR_UNKNOWN);
00064 
00065   /*  Get our process */
00066   proc=tm->processList[process];
00067   if(proc==NULL)  return(ERR_NOPROCESS);
00068 
00069   list=proc->usedheap;
00070 
00071   while(list!=NULL)
00072   {
00073     if((list->seg.pos<=addr)&&(list->seg.pos+list->seg.len>addr))
00074     {
00075       raddr=TMM_GetRealAddress(tm,process,addr);
00076       if(raddr<0)
00077       {
00078         printf("wtf!?\n");
00079         return(ERR_UNKNOWN);
00080       }
00081       
00082       tm->mem[raddr].type=DATA_STRING;
00083       strcpy(tm->mem[raddr].string.value,str);
00084       return(ERR_NONE);
00085     }
00086     list=list->next;
00087   }
00088 
00089   return(ERR_INVALIDADDRESS);
00090 }
00091 
00096 ErrMessage_t TMM_StoreHeapInteger(ToyMM *tm, int process, int addr, int value)
00097 {
00098   SegList *list=NULL;
00099   Process *proc=NULL;
00100   int raddr=-1;
00101   if(tm==NULL)  return(ERR_UNKNOWN);
00102   if((process<0)||(process>=MAX_PROCESSES)) return(ERR_UNKNOWN);
00103 
00104   /*  Get our process */
00105   proc=tm->processList[process];
00106   if(proc==NULL)  return(ERR_NOPROCESS);
00107 
00108   list=proc->usedheap;
00109 
00110   while(list!=NULL)
00111   {
00112     if((list->seg.pos<=addr)&&(list->seg.pos+list->seg.len>addr))
00113     {
00114       raddr=TMM_GetRealAddress(tm,process,addr);
00115       if(raddr<0)
00116       {
00117         printf("wtf!?\n");
00118         return(ERR_UNKNOWN);
00119       }
00120       
00121       tm->mem[raddr].type=DATA_INTEGER;
00122       tm->mem[raddr].integer.value=value;
00123       return(ERR_NONE);
00124     }
00125     list=list->next;
00126   }
00127 
00128   return(ERR_INVALIDADDRESS);
00129 }
00130 
00135 ErrMessage_t TMM_AllocateHeap(ToyMM *tm, int process, int size)
00136 {
00137   SegList *memblock=NULL;
00138   SegList *newblock=NULL;
00139   Process *proc=NULL;
00140 
00141   if(tm==NULL)  return(ERR_UNKNOWN);
00142   if((process<0)||(process>=MAX_PROCESSES)) return(ERR_UNKNOWN);
00143 
00144   /*  Get our process */
00145   proc=tm->processList[process];
00146   if(proc==NULL)  return(ERR_NOPROCESS);
00147 
00148   /*  Find an appropriate memory block in free list  */
00149   memblock=TMM_FindInFreeList(tm,proc,size);
00150   /*  Couldn't find one?  We're out of memory  */
00151   if(memblock==NULL)  return(ERR_HEAPFULL);
00152 
00153   /*  Create new node to represent this */
00154   newblock=TMM_CreateSegList(memblock->seg.pos,size,NULL,NULL);
00155   /*  Insert it into the used heap list */
00156   proc->usedheap=TMM_OrderedInsert(proc->usedheap,newblock);
00157 
00158   if(size==0) size=1;
00159 
00160   /*  Two cases.  If the sizes are exactly the same,
00161       we have to delete the block.  But if they're not,
00162       we can just shrink and move the free block.       */
00163   if(memblock->seg.len==size)
00164   {
00165     /*  Delete the space hole entirely.  */
00166     TMM_DeleteSpaceHole(proc,memblock);
00167   }
00168   else
00169   {
00170     /*  Move the block down 'size' units, and shrink it
00171         'size' units - effectively chopping a portion
00172         off the top.                                    */
00173     memblock->seg.pos+=size;
00174     memblock->seg.len-=size;
00175   }
00176 
00177   /* Force the occupied page to get swapped in */
00178   TMM_GetRealAddress(tm,process,newblock->seg.pos);
00179 
00180   return(ERR_NONE);
00181 }
00182 
00183 
00188 ErrMessage_t TMM_FreeHeap(ToyMM *tm, int process, int addr)
00189 {
00190   SegList *memblock;
00191   Process *proc;
00192 
00193   if(tm==NULL)  return(ERR_UNKNOWN);
00194   if((process<0)||(process>=MAX_PROCESSES)) return(ERR_UNKNOWN);
00195 
00196   /*  Get our process */
00197   proc=tm->processList[process];
00198   if(proc==NULL)  return(ERR_NOPROCESS);
00199 
00200   /*  Find pointer in used list */
00201   memblock=TMM_FindAddressInList(proc->usedheap,addr);
00202   /*  Didn't find it? */
00203   if(memblock==NULL)  return(ERR_BADFREEHEAPADDRESS);
00204 
00205   /*  If it's the head of the list, proceed to next
00206       If there IS no next, the list will become NULL,
00207       meaning empty.                                  */
00208   if(memblock==proc->usedheap)
00209   {
00210     proc->usedheap=proc->usedheap->next;
00211   }
00212 
00213   /*  Remove it from used list.  Not deallocating it,
00214       just unlinking it.                              */
00215   TMM_RemoveFromList(memblock);
00216 
00217   /* Segments of 0 size still take up 1 size */
00218   memblock->seg.len=TMM_MinSize(memblock->seg.len);
00219 
00220   /* Mark now-empty space as empty */
00221   TMM_MarkMemEmpty(tm,memblock->seg.pos,memblock->seg.len);
00222 
00223   /*  Add to list of free space */
00224   TMM_InsertSpaceHole(proc,memblock);
00225 
00226   /*  Combine segments together if any  */
00227   TMM_MergeAt(proc,memblock);
00228   TMM_MergeAt(proc,memblock->prev);
00229 
00230   return(ERR_NONE);
00231 }
00232 
00238 ErrMessage_t TMM_ReallocateHeap(ToyMM *tm, int process, int addr, int size)
00239 {
00240   SegList *memblock=NULL;
00241   SegList *freeblock=NULL;
00242 
00243   Process *proc;
00244   int pos=0;
00245   int dsize=0;  /* change in size */
00246 
00247   if(tm==NULL)  return(ERR_UNKNOWN);
00248   if((process<0)||(process>=MAX_PROCESSES)) return(ERR_UNKNOWN);
00249 
00250   /*  Get our process */
00251   proc=tm->processList[process];
00252   if(proc==NULL)  return(ERR_NOPROCESS);
00253 
00254   /*  Find the allocated block associated with this address */
00255   memblock=TMM_FindAddressInList(proc->usedheap,addr);
00256   /*  Didn't find it, return error  */
00257   if(memblock==NULL)  return(ERR_BADREALLOCADDRESS);
00258 
00259   /*  Calculate the change in size - larger is positive,
00260       smaller is negative                                 */
00261   dsize=size-TMM_MinSize(memblock->seg.len);
00262 
00263   /* Calculate current last address of segment to be reallocated */
00264   pos=memblock->seg.pos+TMM_MinSize(memblock->seg.len);
00265 
00266   freeblock=TMM_FindAddressInList(proc->freeheap,pos);
00267   if(dsize==0)    /*  Same size - no problem  */
00268   {
00269     return(ERR_NONE);
00270   }
00271   else if(dsize>0)  /*  memory grows  */
00272   {
00273     if(freeblock!=NULL)  /*  memory available below? */
00274     if(freeblock->seg.len>=dsize)
00275     {
00276       /*  Yet again the obnoxious 0 size is 1 size problem. */
00277       memblock->seg.len=TMM_MinSize(memblock->seg.len);
00278       memblock->seg.len+=dsize;
00279       freeblock->seg.pos+=dsize;
00280       freeblock->seg.len-=dsize;
00281       if(memblock->seg.len==0)
00282       {
00283         TMM_DeleteSpaceHole(proc,freeblock);
00284       }
00285       return(ERR_NONE);
00286     }
00287     /*  Space NOT available below - search elsewhere */
00288     {
00289       SegList *newmem;
00290       /*  Find free space */
00291       freeblock=TMM_FindInFreeList(tm,proc,size);
00292       /*  Didn't find space - out of memory. */
00293       if(freeblock==NULL)  return(ERR_HEAPFULL);
00294 
00295       /*  Create new node for used list */
00296       newmem=TMM_CreateSegList(freeblock->seg.pos,size,NULL,NULL);
00297 
00298       /*  Copy memory into new seg  */
00299       TMM_CopyMem(tm,newmem->seg.pos,memblock->seg.pos,memblock->seg.len);
00300       TMM_MarkMemEmpty(tm,memblock->seg.pos,memblock->seg.len);
00301 
00302       /*  Move and resize memory hole  */
00303       freeblock->seg.pos+=size;
00304       freeblock->seg.len-=size;
00305       /*  If the hole is empty, delete it */
00306       if(freeblock->seg.len==0)
00307       {
00308         TMM_DeleteSpaceHole(proc,freeblock);
00309       }
00310 
00311       /*  Add new memory to used list */
00312       proc->usedheap=TMM_OrderedInsert(proc->usedheap,newmem);
00313 
00314       /* Remove old memory from used list */
00315       TMM_RemoveFromList(memblock);
00316       /*  Add memory hole to free list  */
00317       proc->freeheap=TMM_OrderedInsert(proc->freeheap,memblock);
00318       /*  Merge space holes */
00319 
00320       TMM_MergeAt(proc,memblock);
00321       TMM_MergeAt(proc,memblock->prev);
00322 
00323       return(ERR_NONE);
00324     }
00325 
00326   }
00327   else  /*  dsize < 0: shrink */
00328   {
00329     SegList *newhole=NULL;
00330 
00331     dsize=-dsize; /*  make non-negative for more obvious calculations */
00332 
00333     /* Should not happen unless a negative gets entered
00334         somehow.  But just in case...                   */
00335     if(memblock->seg.len<dsize)
00336     {
00337       return(ERR_UNKNOWN);
00338     }
00339     else if(memblock->seg.len==dsize)  /*  collapse to 0 size  */
00340     {
00341       /*  Create hole ONE smaller than 'zero'-size block, and one below */
00342       newhole=TMM_CreateSegList(memblock->seg.pos+1,memblock->seg.len-1,NULL,NULL);
00343       /*  Set seg size to zero  */
00344       memblock->seg.len=0;
00345     }
00346     else
00347     {
00348       /*  Create new memory hole  */
00349       newhole=TMM_CreateSegList(memblock->seg.pos+memblock->seg.len-dsize,
00350                                 dsize,NULL,NULL);
00351       /*  Shrink the segment  */
00352 
00353       memblock->seg.len-=dsize;
00354     }
00355     /*  Insert new hole into free list  */
00356     proc->freeheap=TMM_OrderedInsert(proc->freeheap,newhole);
00357     /*  Merge end-to-end segments */
00358     TMM_MergeAt(proc,newhole);
00359     TMM_MergeAt(proc,newhole->prev);
00360     return(ERR_NONE);
00361   }
00362 }
00363 
00371 ErrMessage_t TMM_PrintHeap(ToyMM *tm, int process)
00372 {
00373   char str[]="*\0\0";
00374   int totalsize=0;
00375   int freesize=0;
00376   int usedsize=0;
00377 
00378   float freepercent;
00379 
00380   if((process<0)||(process>=MAX_PROCESSES)) return(ERR_UNKNOWN);
00381   if(tm->processList[process]==NULL)        return(ERR_NOPROCESS);
00382 
00383   printf(LINE_RULE);
00384   printf(LINE_PREFIX"Heap for Process P%01d:\n",process);
00385 
00386   totalsize+=PrintFreeHeap(tm->processList[process]);
00387   str[0]='\0';
00388   usedsize+=PrintSegList(tm->processList[process]->usedheap,"Used",str);
00389   totalsize+=usedsize;
00390 
00391   freesize=totalsize-usedsize;
00392 
00393   if(totalsize!=0)
00394   {
00395     freepercent=(freesize*100.0f)/totalsize;
00396   }
00397   else
00398   {
00399     freepercent=0.0f;
00400   }
00401 
00402   printf(LINE_PREFIX" Free: %d / %d = %.0f%%\n",freesize,totalsize,freepercent);
00403 
00404   printf(LINE_RULE);
00405 
00406   return(ERR_NONE);
00407 }
00408 
00413 int PrintFreeHeap(Process *proc)
00414 {
00415   SegList *list=NULL;
00416   char starstr[]="*\0\0";  
00417   int size=0;
00418   unsigned int charprinted=0;
00419   
00420   if(proc==NULL)  return(0);
00421   
00422   list=proc->freeheap;
00423   
00424   printf(LINE_PREFIX" Free");
00425 
00426   while(list!=NULL)
00427   {
00428     if(charprinted>=WRAP_LEN)
00429     {
00430       printf("\n"LINE_PREFIX"     ");
00431       charprinted=0;
00432     }
00433 
00434     if(list==proc->ptr) starstr[0]='*';
00435     else                starstr[0]='\0';
00436         
00437     charprinted+=printf(" -> %s[%d %d]",starstr,list->seg.pos,list->seg.len);
00438     starstr[0]='\0';
00439     size+=list->seg.len;
00440     list=list->next;    
00441   }
00442 
00443   if(charprinted>=WRAP_LEN)
00444   {
00445     printf("\n"LINE_PREFIX);
00446     charprinted=0;
00447   }
00448   printf(" -> %s[]\n",starstr);
00449   return(size);
00450 }
00451 
00456 int PrintSegList(SegList *list, const char *title, char *prefix)
00457 {
00458   int size=0;
00459   int charprinted=0;
00460   char startStr[20];
00461 
00462   strcpy(startStr,prefix);
00463   printf(LINE_PREFIX" %4s",title);
00464 
00465   while(list!=NULL)
00466   {
00467     /*  Handle linewrapping - if we've printed this much, go to a new line. */
00468     if(charprinted>=WRAP_LEN)
00469     {
00470       charprinted=0;
00471       printf("\n"LINE_PREFIX"     ");
00472     }
00473 
00474     size+=list->seg.len;
00475     if(list->seg.len==0)  size++;
00476                                            /*  Print the next seg, keeping track of how much we've printed */
00477     if(list->seg.len==0)
00478     {
00479       charprinted+=printf(" -> %s[%d 0 (1)]",startStr,list->seg.pos);
00480     }
00481     else
00482     {
00483       charprinted+=printf(" -> %s[%d %d]",startStr,list->seg.pos,list->seg.len);
00484     }
00485 
00486     /*  Forward to the next segment */
00487     list=list->next;
00488 
00489     /* Turn the "*" into a "" */
00490     startStr[0]='\0';
00491 
00492   } while(list!=NULL);
00493 
00494   /*  Handle linewrapping - if we've printed this much, go to a new line. */
00495   if(charprinted>=WRAP_LEN)
00496   {
00497     charprinted=0;
00498     printf("\n"LINE_PREFIX"     ");
00499   }
00500   printf(" -> %s[]\n",startStr);
00501 
00502   return(size);
00503 }
00504 
00505 /******************************************************************************
00506   Glue functions
00507  ******************************************************************************/
00508 
00512 SegList *TMM_InsertSpaceHole(Process *proc, SegList *hole)
00513 {
00514   if(proc==NULL)  return(NULL);
00515   if(hole==NULL)  return(proc->freeheap);
00516 
00517   proc->freeheap=TMM_OrderedInsert(proc->freeheap,hole);
00518   if(proc->ptr==NULL) proc->ptr=proc->freeheap;
00519 
00520   return(proc->freeheap);
00521 }
00522 
00529 SegList *TMM_CircularNext(Process *proc)
00530 {
00531   if(proc==NULL)            return(NULL);
00532   if(proc->freeheap==NULL)  return(NULL);
00533 
00534   if(proc->ptr==NULL)
00535   {
00536     proc->ptr=proc->freeheap;
00537     return(proc->ptr);
00538   }
00539 
00540   /*  Advance the pointer */
00541   proc->ptr=proc->ptr->next;
00542   /*  If we've reached the end, loop to the beginning */
00543   if(proc->ptr==NULL) proc->ptr=proc->freeheap;
00544   return(proc->ptr);
00545 }
00546 
00552 SegList *TMM_DeleteSpaceHole(Process *proc, SegList *hole)
00553 {
00554   /*  Special case - this hole is the ONLY hole in the list.
00555       Need to set heap and ptr to NULL to denote empty.     */
00556   int size=TMM_SegListSize(proc->freeheap);
00557   if(size==0)
00558   {
00559     return(NULL);
00560   }
00561   else if(size==1)
00562   {
00563     if(hole!=proc->freeheap)
00564     {
00565       /*  Should NOT happen */
00566       printf("wtf?\n");
00567       abort();
00568     }
00569 
00570     proc->ptr=NULL;
00571     proc->freeheap=NULL;
00572     free(hole);
00573     return(NULL);
00574   }
00575   else
00576   {
00577     /*  If we're pointing to the hole, have to seek to the next */    
00578     if(proc->ptr==hole) TMM_CircularNext(proc);
00579 
00580     /*  If it's the head, better move the head ptr */
00581     if(proc->freeheap==hole)
00582     {
00583       proc->freeheap=proc->freeheap->next;
00584     }
00585 
00586     TMM_RemoveFromList(hole);
00587     free(hole);
00588     return(proc->freeheap);
00589   }
00590 }
00591 
00596 SegList *TMM_FindInFreeList(ToyMM *tmm,Process *proc, int size)
00597 {
00598   SegList *list=proc->ptr;
00599   SegList *startpoint=list;
00600 
00601   /*  Set to minimum size */
00602   size=TMM_MinSize(size);
00603 
00604   /* Search through free list for suitable seg */  
00605   if(list!=NULL)
00606   {
00607     do
00608     {
00609       if(list->seg.len>=size) return(list);
00610 
00611       list=TMM_CircularNext(proc);
00612     }while(list!=startpoint);
00613   }
00614 
00615   /* Can't add pages to heap segment in legacy mode. */
00616   if(TMM_PagingEnabled(tmm)<0)
00617   {
00618     return(NULL);
00619   }
00620   else
00621   { /* Attempt to enlarge the heap */
00622     return(TMM_EnlargeHeap(tmm,TMM_FindProcess(tmm,proc),size));
00623   }
00624 }
00625 
00631 SegList *TMM_FindAddressInList(SegList *node, int address)
00632 {
00633   while(node!=NULL) /*  Loop through every node in used list  */
00634   {
00635     /*  If the address matches, we've found it. */
00636     if(node->seg.pos==address) return(node);
00637     node=node->next;
00638   }
00639 
00640   /*  Didn't find it. */
00641   return(NULL);
00642 }
00643 
00650 void TMM_MergeAt(Process *proc, SegList *list)
00651 {
00652   if(list==NULL)              return;
00653   else if (list->next==NULL)  return;  
00654   
00655   if(SegEnd(&(list->seg))==list->next->seg.pos)
00656   {
00657     if(list->next==proc->ptr)
00658     {
00659       proc->ptr=list;
00660     }
00661 
00662     list->seg.len+=list->next->seg.len;
00663     TMM_DeleteSpaceHole(proc,list->next);
00664   }
00665 }
00666 
00667 
00668 int TMM_FindProcess(ToyMM *tmm, Process *proc)
00669 {
00670   int n;
00671   if(tmm==NULL) return(-1);
00672 
00673   for(n=0; n<MAX_PROCESSES; n++)
00674   {
00675     if(tmm->processList[n]==proc) return(n);
00676   }
00677 
00678   return(-1);
00679 }
00680 
00681 int TMM_MinSize(int size)
00682 {
00683   if(size<MIN_SIZE) return(MIN_SIZE);
00684   else              return(size);
00685 }
00686 
00687 /* Enlarges the heap until 'pages' continuous pages exist in the free list.  Returns the hole or NULL. */
00688 SegList *TMM_EnlargeHeap(ToyMM *tmm, int process, int size)
00689 {
00690   SegList *lasthole=NULL;
00691   SegList *lastsegpos=NULL;
00692   int vaddr=-1;
00693   Process *proc=tmm->processList[process];
00694 
00695   lasthole=TMM_SeekSegListEnd(proc->freeheap);
00696   lastsegpos=TMM_GetSegmentNode(tmm, process, SEG_HEAP);
00697 
00698   vaddr=(lastsegpos->seg.pos+lastsegpos->seg.len);
00699 
00700   if(lastsegpos==NULL)
00701   {
00702     return(NULL);
00703   }
00704 
00705   if(lasthole==NULL)  /* Totally empty free list */
00706   {
00707     int frame=-1;
00708     int page=-1;
00709     int pages=TMM_GetNumFrames(tmm,size);
00710 /*    printf("Allocating memory in totally empty free list\n"); */
00711 
00712     /* Not enough available pages, return error */
00713     if(pages>TMM_CountFreePages(tmm,process)) return(NULL);
00714 
00715     /* Create new space hole */
00716     lasthole=TMM_CreateSegList(vaddr,0,NULL,NULL);
00717     proc->freeheap=TMM_AppendSegList(proc->freeheap,lasthole);
00718 
00719     page=vaddr/tmm->pageSize;
00720 
00721     /* Find free frames */
00722     while(pages>0)
00723     {
00724       frame=TMM_FindFreeFrame(tmm);
00725       if(frame<0) break;
00726       
00727       /* Assign found frame to process */
00728       TMM_AssignFrame(tmm,process,frame,page);
00729 
00730       /* Increase the virtual address(page) */
00731       page++;
00732       /* Decrease # of needed pages */
00733       pages--;
00734 
00735       /* Increase segment sizes */
00736       lastsegpos->seg.len+=tmm->pageSize;
00737       lasthole->seg.len+=tmm->pageSize;
00738     }
00739 
00740     if(pages>0)
00741     {
00742       printf("Page allocation error\n");
00743       abort();
00744     }    
00745 
00746     proc->ptr=lasthole;
00747     return(lasthole);
00748   }
00749   else if(lasthole->seg.pos+lasthole->seg.len==lastsegpos->seg.pos+lastsegpos->seg.len)
00750   {
00751     int frame=-1;
00752     int page=-1;
00753     int pages=TMM_GetNumFrames(tmm,size-lasthole->seg.len);
00754 
00755 
00756     /* Not enough available pages, return error */
00757     if(TMM_CountFreePages(tmm,process)<pages) return(NULL);    
00758 
00759 
00760     page=vaddr/tmm->pageSize;
00761 
00762     /* Find free frames */
00763     while(pages>0)
00764     {
00765       frame=TMM_FindFreeFrame(tmm);
00766       if(frame<0) break;
00767       
00768       /* Assign found frame to process */
00769       TMM_AssignFrame(tmm,process,frame,page);
00770 
00771       /* Increase the virtual address(page) */
00772       page++;
00773       /* Decrease # of needed pages */
00774       pages--;
00775 
00776       /* Increase segment sizes */
00777       lastsegpos->seg.len+=tmm->pageSize;
00778       lasthole->seg.len+=tmm->pageSize;
00779     }
00780 
00781     if(pages>0)
00782     {
00783       printf("Page allocation error\n");
00784       abort();
00785     }
00786 
00787     proc->ptr=lasthole;
00788     return(lasthole);
00789   }
00790   else
00791   {
00792     int frame=-1;
00793     int page=-1;
00794     int pages=TMM_GetNumFrames(tmm,size);
00795 
00796     /* Not enough available pages, return error */
00797     if(TMM_CountFreePages(tmm,process)<pages) return(NULL);
00798 
00799     /* Create new space hole */
00800     lasthole=TMM_CreateSegList(vaddr,0,NULL,NULL);
00801 
00802     proc->freeheap=TMM_AppendSegList(proc->freeheap,lasthole);
00803 
00804     page=vaddr/tmm->pageSize;
00805 
00806     /* Find free frames */
00807     while(pages>0)
00808     {
00809       frame=TMM_FindFreeFrame(tmm);
00810       if(frame==-1)      
00811       {
00812         printf("Page allocation error -Email me at monttyle@heavyspace.ca and tell me how you did this.\n");
00813         abort();
00814       }
00815       /* Assign found frame to process */
00816       TMM_AssignFrame(tmm,process,frame,page);
00817 
00818       /* Increase the virtual address(page) */
00819       page++;
00820       /* Decrease # of needed pages */
00821       pages--;
00822 
00823       /* Increase segment sizes */
00824       lastsegpos->seg.len+=tmm->pageSize;
00825       lasthole->seg.len+=tmm->pageSize;
00826     }
00827 
00828     proc->ptr=lasthole;
00829     return(lasthole);
00830   }
00831 }

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