00001
00002
00003
00004
00005
00006
00007
00008
00009
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
00031
00032
00033 SegList *TMM_InsertSpaceHole(Process *proc, SegList *hole);
00034
00035 SegList *TMM_CircularNext(Process *proc);
00036
00037 SegList *TMM_DeleteSpaceHole(Process *proc, SegList *hole);
00038
00039 SegList *TMM_FindInFreeList(ToyMM *tmm, Process *proc, int size);
00040
00041 SegList *TMM_FindAddressInList(SegList *list, int address);
00042
00043 void TMM_MergeAt(Process *proc, SegList *list);
00044
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
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
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
00145 proc=tm->processList[process];
00146 if(proc==NULL) return(ERR_NOPROCESS);
00147
00148
00149 memblock=TMM_FindInFreeList(tm,proc,size);
00150
00151 if(memblock==NULL) return(ERR_HEAPFULL);
00152
00153
00154 newblock=TMM_CreateSegList(memblock->seg.pos,size,NULL,NULL);
00155
00156 proc->usedheap=TMM_OrderedInsert(proc->usedheap,newblock);
00157
00158 if(size==0) size=1;
00159
00160
00161
00162
00163 if(memblock->seg.len==size)
00164 {
00165
00166 TMM_DeleteSpaceHole(proc,memblock);
00167 }
00168 else
00169 {
00170
00171
00172
00173 memblock->seg.pos+=size;
00174 memblock->seg.len-=size;
00175 }
00176
00177
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
00197 proc=tm->processList[process];
00198 if(proc==NULL) return(ERR_NOPROCESS);
00199
00200
00201 memblock=TMM_FindAddressInList(proc->usedheap,addr);
00202
00203 if(memblock==NULL) return(ERR_BADFREEHEAPADDRESS);
00204
00205
00206
00207
00208 if(memblock==proc->usedheap)
00209 {
00210 proc->usedheap=proc->usedheap->next;
00211 }
00212
00213
00214
00215 TMM_RemoveFromList(memblock);
00216
00217
00218 memblock->seg.len=TMM_MinSize(memblock->seg.len);
00219
00220
00221 TMM_MarkMemEmpty(tm,memblock->seg.pos,memblock->seg.len);
00222
00223
00224 TMM_InsertSpaceHole(proc,memblock);
00225
00226
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;
00246
00247 if(tm==NULL) return(ERR_UNKNOWN);
00248 if((process<0)||(process>=MAX_PROCESSES)) return(ERR_UNKNOWN);
00249
00250
00251 proc=tm->processList[process];
00252 if(proc==NULL) return(ERR_NOPROCESS);
00253
00254
00255 memblock=TMM_FindAddressInList(proc->usedheap,addr);
00256
00257 if(memblock==NULL) return(ERR_BADREALLOCADDRESS);
00258
00259
00260
00261 dsize=size-TMM_MinSize(memblock->seg.len);
00262
00263
00264 pos=memblock->seg.pos+TMM_MinSize(memblock->seg.len);
00265
00266 freeblock=TMM_FindAddressInList(proc->freeheap,pos);
00267 if(dsize==0)
00268 {
00269 return(ERR_NONE);
00270 }
00271 else if(dsize>0)
00272 {
00273 if(freeblock!=NULL)
00274 if(freeblock->seg.len>=dsize)
00275 {
00276
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
00288 {
00289 SegList *newmem;
00290
00291 freeblock=TMM_FindInFreeList(tm,proc,size);
00292
00293 if(freeblock==NULL) return(ERR_HEAPFULL);
00294
00295
00296 newmem=TMM_CreateSegList(freeblock->seg.pos,size,NULL,NULL);
00297
00298
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
00303 freeblock->seg.pos+=size;
00304 freeblock->seg.len-=size;
00305
00306 if(freeblock->seg.len==0)
00307 {
00308 TMM_DeleteSpaceHole(proc,freeblock);
00309 }
00310
00311
00312 proc->usedheap=TMM_OrderedInsert(proc->usedheap,newmem);
00313
00314
00315 TMM_RemoveFromList(memblock);
00316
00317 proc->freeheap=TMM_OrderedInsert(proc->freeheap,memblock);
00318
00319
00320 TMM_MergeAt(proc,memblock);
00321 TMM_MergeAt(proc,memblock->prev);
00322
00323 return(ERR_NONE);
00324 }
00325
00326 }
00327 else
00328 {
00329 SegList *newhole=NULL;
00330
00331 dsize=-dsize;
00332
00333
00334
00335 if(memblock->seg.len<dsize)
00336 {
00337 return(ERR_UNKNOWN);
00338 }
00339 else if(memblock->seg.len==dsize)
00340 {
00341
00342 newhole=TMM_CreateSegList(memblock->seg.pos+1,memblock->seg.len-1,NULL,NULL);
00343
00344 memblock->seg.len=0;
00345 }
00346 else
00347 {
00348
00349 newhole=TMM_CreateSegList(memblock->seg.pos+memblock->seg.len-dsize,
00350 dsize,NULL,NULL);
00351
00352
00353 memblock->seg.len-=dsize;
00354 }
00355
00356 proc->freeheap=TMM_OrderedInsert(proc->freeheap,newhole);
00357
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
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
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
00487 list=list->next;
00488
00489
00490 startStr[0]='\0';
00491
00492 } while(list!=NULL);
00493
00494
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
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
00541 proc->ptr=proc->ptr->next;
00542
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
00555
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
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
00578 if(proc->ptr==hole) TMM_CircularNext(proc);
00579
00580
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
00602 size=TMM_MinSize(size);
00603
00604
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
00616 if(TMM_PagingEnabled(tmm)<0)
00617 {
00618 return(NULL);
00619 }
00620 else
00621 {
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)
00634 {
00635
00636 if(node->seg.pos==address) return(node);
00637 node=node->next;
00638 }
00639
00640
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
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)
00706 {
00707 int frame=-1;
00708 int page=-1;
00709 int pages=TMM_GetNumFrames(tmm,size);
00710
00711
00712
00713 if(pages>TMM_CountFreePages(tmm,process)) return(NULL);
00714
00715
00716 lasthole=TMM_CreateSegList(vaddr,0,NULL,NULL);
00717 proc->freeheap=TMM_AppendSegList(proc->freeheap,lasthole);
00718
00719 page=vaddr/tmm->pageSize;
00720
00721
00722 while(pages>0)
00723 {
00724 frame=TMM_FindFreeFrame(tmm);
00725 if(frame<0) break;
00726
00727
00728 TMM_AssignFrame(tmm,process,frame,page);
00729
00730
00731 page++;
00732
00733 pages--;
00734
00735
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
00757 if(TMM_CountFreePages(tmm,process)<pages) return(NULL);
00758
00759
00760 page=vaddr/tmm->pageSize;
00761
00762
00763 while(pages>0)
00764 {
00765 frame=TMM_FindFreeFrame(tmm);
00766 if(frame<0) break;
00767
00768
00769 TMM_AssignFrame(tmm,process,frame,page);
00770
00771
00772 page++;
00773
00774 pages--;
00775
00776
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
00797 if(TMM_CountFreePages(tmm,process)<pages) return(NULL);
00798
00799
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
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
00816 TMM_AssignFrame(tmm,process,frame,page);
00817
00818
00819 page++;
00820
00821 pages--;
00822
00823
00824 lastsegpos->seg.len+=tmm->pageSize;
00825 lasthole->seg.len+=tmm->pageSize;
00826 }
00827
00828 proc->ptr=lasthole;
00829 return(lasthole);
00830 }
00831 }