00001
00002
00003
00004
00005
00006
00007
00008
00009
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 "ToyMemPage.h"
00022 #include "ToyVirtualMem.h"
00023 #include "ToyLoad.h"
00024 #include "ToySwap.h"
00025 #include "ToyParseCmd.h"
00026
00030 const char *ErrMessages[] =
00031 {
00032 "Invalid syntax in processor input"
00033 , "Process already loaded"
00034 , "Cannot open load file"
00035 , "Load file has invalid format"
00036 , "Excess values in load file"
00037 , "Invalid instruction in load file"
00038 , "Invalid data value in load file"
00039 , "Insufficient main memory to load file"
00040 , "Address is outside of valid segments"
00041 , "Specified process does not exist"
00042 , "Insufficient privilege for PrintAllMemory"
00043 , "END command reached, parser stopped"
00044 , "Command not yet implemented"
00045 , "Insufficient heap space"
00046 , "Invalid address for FreeHeap"
00047 , "Invalid address for ReallocateHeap"
00048 , "Invalid page size"
00049 , "Paging has not been enabled"
00050 , "Insufficient privilege for EnablePaging"
00051 , NULL };
00052
00053 void TMM_VPrintMem(ToyMM *tmm, int process, int vaddr);
00054
00059 ErrMessage_t TMM_PrintAllMemory(ToyMM *tmm)
00060 {
00061 int n;
00062
00063 if(tmm==NULL) return(ERR_UNKNOWN);
00064
00065 printf(LINE_RULE);
00066 printf(LINE_PREFIX"Memory Contents:\n");
00067
00068 for(n=0; n<tmm->memSize; n++)
00069 {
00070 TMM_PrintMem(tmm,n);
00071 }
00072
00073 printf(LINE_RULE);
00074
00075 return(ERR_NONE);
00076 }
00077
00082 ErrMessage_t TMM_PrintProcessTable(ToyMM *tm, int process)
00083 {
00084 int n;
00085
00086 if((process<0)||(process>=MAX_PROCESSES)) return(ERR_UNKNOWN);
00087 else if((process!=0)&&(tm->processList[process]==NULL))return(ERR_NOPROCESS);
00088
00089 printf(LINE_RULE);
00090 printf(LINE_PREFIX"Process Table:\n");
00091 printf(LINE_PREFIX" PID #SEG SEG1 LEN1 SEG2 LEN2 SEG3 LEN3 SEG4 LEN4\n");
00092 printf(LINE_PREFIX" --- ---- ---- ---- ---- ---- ---- ---- ---- ----\n");
00093
00094 for(n=0; n<MAX_PROCESSES; n++)
00095 {
00096 int i=-1;
00097 int numSegs = -1;
00098 int segSizes[4] = {-1,-1,-1,-1};
00099 int segPos[4] = {-1,-1,-1,-1};
00100 SegList *list=NULL;
00101
00102 if(tm->processList[n]==NULL) continue;
00103 list=TMM_SeekSegListHead(tm->processList[n]->segments);
00104
00105 for(numSegs=0; (list!=NULL)&&(numSegs<4); list=list->next,numSegs++ )
00106 {
00107 segSizes[numSegs]=list->seg.len;
00108 segPos[numSegs]=list->seg.pos;
00109 }
00110 printf(LINE_PREFIX" P%1d %1d",n,numSegs);
00111 for(i=0; i<numSegs; i++)
00112 {
00113 printf(" %4d",segPos[i]);
00114 printf(" %4d",segSizes[i]);
00115 }
00116 printf("\n");
00117 }
00118
00119 printf(LINE_RULE);
00120
00121 return(ERR_NONE);
00122 }
00123
00127 ErrMessage_t TMM_PrintProcessMemory(ToyMM *tm, int process)
00128 {
00129 int n=-1;
00130 int seg=0;
00131 SegList *list=NULL;
00132
00133 if( (process<0)||(process>=MAX_PROCESSES)) return(ERR_UNKNOWN);
00134 if(tm->processList[process]==NULL) return(ERR_NOPROCESS);
00135
00136 printf(LINE_RULE);
00137 printf(LINE_PREFIX"Memory Contents:\n");
00138
00139 list=tm->processList[process]->segments;
00140 list=TMM_SeekSegListHead(list);
00141
00142 while(list!=NULL)
00143 {
00144 if(seg==SEG_HEAP)
00145 {
00146 SegList *heap=tm->processList[process]->usedheap;
00147 while(heap!=NULL)
00148 {
00149 int hpos=0;
00150
00151 for(hpos=heap->seg.pos; hpos<(heap->seg.pos+heap->seg.len); hpos++)
00152 {
00153 TMM_VPrintMem(tm,process,hpos);
00154 }
00155 heap=heap->next;
00156 }
00157 }
00158 else
00159 {
00160
00161 for(n=list->seg.pos; n<(list->seg.pos+list->seg.len); n++)
00162 {
00163
00164
00165 TMM_VPrintMem(tm,process,n);
00166 }
00167 }
00168
00169 list=list->next;
00170 seg++;
00171 }
00172
00173 printf(LINE_RULE);
00174 return(ERR_NONE);
00175 }
00176
00181 ErrMessage_t TMM_StoreInteger(ToyMM *tm,int process,int addr,int val)
00182 {
00183 SegList *list;
00184 int raddr=-1;
00185 int seg=SEG_CODE;
00186
00187 if(tm->processList[process]==NULL) return(ERR_NOPROCESS);
00188
00189 list=tm->processList[process]->segments;
00190 list=TMM_SeekSegListHead(list);
00191
00192 list=list->next;
00193 seg++;
00194
00195 while(list!=NULL)
00196 {
00197
00198 if( (addr>=list->seg.pos) && (addr< (list->seg.pos+list->seg.len)) )
00199 {
00200 if(seg==SEG_HEAP)
00201 {
00202 return(TMM_StoreHeapInteger(tm,process,addr,val));
00203 }
00204
00205
00206 raddr=TMM_GetRealAddress(tm,process,addr);
00207 if(raddr<0) return(ERR_UNKNOWN);
00208
00209
00210 tm->mem[raddr].type=DATA_INTEGER;
00211 tm->mem[raddr].integer.value=val;
00212 return(ERR_NONE);
00213 }
00214 list=list->next;
00215 seg++;
00216 }
00217
00218
00219 return(ERR_INVALIDADDRESS);
00220 }
00221
00225 ErrMessage_t TMM_StoreString(ToyMM *tm, int process, int addr, const char *str)
00226 {
00227 SegList *list;
00228 int seg=SEG_CODE;
00229 int raddr=-1;
00230
00231 if(strlen(str)>MAX_STRLEN) return(ERR_INVALIDINPUT);
00232 if(tm->processList[process]==NULL) return(ERR_NOPROCESS);
00233
00234
00235
00236
00237
00238 list=tm->processList[process]->segments;
00239 list=TMM_SeekSegListHead(list);
00240
00241 list=list->next;
00242 seg++;
00243
00244 while(list!=NULL)
00245 {
00246
00247 if( (addr>=list->seg.pos) && (addr< (list->seg.pos+list->seg.len)) )
00248 {
00249 if(seg==SEG_HEAP)
00250 {
00251 return(TMM_StoreHeapString(tm,process,addr,str));
00252 }
00253
00254
00255 raddr=TMM_GetRealAddress(tm,process,addr);
00256 if(raddr<0) return(ERR_UNKNOWN);
00257
00258
00259 tm->mem[raddr].type=DATA_STRING;
00260 strcpy(tm->mem[raddr].string.value,str);
00261 return(ERR_NONE);
00262 }
00263 list=list->next;
00264 seg++;
00265 }
00266
00267
00268 return(ERR_INVALIDADDRESS);
00269 }
00270
00271
00272
00277 ErrMessage_t TMM_TerminateProcess(ToyMM *tmm, int ID)
00278 {
00279 SegList *list;
00280
00281 if(tmm==NULL) return(ERR_UNKNOWN);
00282
00283 if(tmm->processList[ID]==NULL) return(ERR_NOPROCESS);
00284 else if(TMM_PagingEnabled(tmm)>=0)
00285 {
00286 return(TMM_PagedTerminateProcess(tmm,ID));
00287 }
00288
00289
00290 list=tmm->processList[ID]->segments;
00291 list=TMM_SeekSegListHead(list);
00292
00293
00294 while(list!=NULL)
00295 {
00296 TMM_FreeSegment(tmm,list->seg.pos,list->seg.len);
00297 list=list->next;
00298 }
00299
00300
00301 if(tmm->processList[ID]->segments!=NULL)
00302 TMM_FreeSegList(tmm->processList[ID]->segments);
00303
00304 if(tmm->processList[ID]->freeheap!=NULL)
00305 TMM_FreeSegList(tmm->processList[ID]->freeheap);
00306
00307 if(tmm->processList[ID]->usedheap!=NULL)
00308 TMM_FreeSegList(tmm->processList[ID]->usedheap);
00309
00310
00311 free(tmm->processList[ID]);
00312
00313
00314 tmm->processList[ID]=NULL;
00315
00316 return(ERR_NONE);
00317 }
00318
00322 ErrMessage_t TMM_AllocateProcessAt(ToyMM *tmm, int ID, int pos, int nSegs, int size[])
00323 {
00324 int n=-1,startpos=-1;
00325 Process *p=NULL;
00326 SegList *list=NULL;
00327
00328 if((ID>=MAX_PROCESSES)||(ID<0)) return(ERR_UNKNOWN);
00329 if(tmm->processList[ID]!=NULL) return(ERR_NOPROCESS);
00330
00331 p=(Process *)malloc(sizeof(Process));
00332 if(p==NULL) return(ERR_UNKNOWN);
00333
00334 p->ptr=NULL;
00335 p->freeheap=NULL;
00336 p->usedheap=NULL;
00337 p->segments=NULL;
00338 p->ID=ID;
00339 p->pagetable=NULL;
00340
00341
00342 tmm->processList[ID]=p;
00343
00344
00345 for(n=0,startpos=pos; n<nSegs; n++)
00346 {
00347 SegList *node=NULL;
00348
00349
00350 if(TMM_AllocateSegmentAt(tmm,startpos,size[n])!=ERR_NONE)
00351 {
00352
00353 TMM_TerminateProcess(tmm,ID);
00354 return(ERR_INSUFFICIENTMEM);
00355 }
00356
00357
00358 node=TMM_CreateSegList(startpos,size[n],NULL,NULL);
00359
00360
00361 p->segments=TMM_AppendSegList(p->segments,node);
00362
00363
00364 startpos+=size[n];
00365 }
00366
00367
00368 p->segments=TMM_SeekSegListHead(p->segments);
00369
00370 list=TMM_GetSegmentNode(tmm,ID,SEG_HEAP);
00371 if(list!=NULL)
00372 {
00373 SegList *node=TMM_CreateSegList(list->seg.pos,list->seg.len,NULL,NULL);
00374 p->freeheap=node;
00375 p->ptr=p->freeheap;
00376 }
00377
00378 return(ERR_NONE);
00379 }
00380
00384 ErrMessage_t TMM_AllocateSegmentAt(ToyMM *tmm, int pos, int size)
00385 {
00386 int i=-1,overlap=0;
00387 ToySegment mySeg;
00388 mySeg.pos=pos;
00389 mySeg.len=size;
00390
00391
00392 if((pos+size)>tmm->memSize) return(ERR_INSUFFICIENTMEM);
00393
00394
00395 for(i=0,overlap=0; (i<MAX_PROCESSES)&&(overlap==0); i++)
00396 {
00397 SegList *list=NULL;
00398
00399 if(tmm->processList[i]!=NULL) list=tmm->processList[i]->segments;
00400 while(list!=NULL)
00401 {
00402 ToySegment seg;
00403
00404 seg.pos=TMM_GetRealAddress(tmm,i,list->seg.pos);
00405 seg.len=TMM_GetFramedSize(tmm,list->seg.len);
00406
00407 overlap|=TMM_AreaIntersectsSeg(&mySeg,&seg);
00408 list=list->next;
00409 }
00410 }
00411
00412 if(overlap!=0)
00413 {
00414 return(ERR_INSUFFICIENTMEM);
00415 }
00416 else
00417 {
00418
00419 for(i=pos; i<(pos+size); i++) tmm->mem[i].type=DATA_ERROR;
00420 tmm->memFree=TMM_RemoveAreaFromSegList(tmm->memFree,pos,size);
00421 return(ERR_NONE);
00422 }
00423 }
00424
00428 ErrMessage_t TMM_FreeSegment(ToyMM *tmm, int pos, int size)
00429 {
00430 int n;
00431 SegList *list;
00432
00433 for(n=0; n<MAX_PROCESSES; n++)
00434 {
00435 if(tmm->processList[n]==NULL) continue;
00436
00437 list=tmm->processList[n]->segments;
00438 while(list!=NULL)
00439 {
00440 if((list->seg.len==size)&&(list->seg.pos==pos))
00441 {
00442 list=TMM_AddAreaToSegList(tmm->memFree,pos,size);
00443 if(list==NULL)
00444 {
00445
00446 return(ERR_UNKNOWN);
00447 }
00448 else
00449 {
00450 tmm->memFree=list;
00451 return(ERR_NONE);
00452 }
00453 }
00454
00455 list=list->next;
00456 }
00457 }
00458
00459 return(ERR_UNKNOWN);
00460 }
00461
00462
00466 ToyMM *TMM_Create(int memSize)
00467 {
00468 int n;
00469
00470 ToyMM *tmm = (ToyMM *)malloc(sizeof(ToyMM));
00471
00472 if(tmm==NULL)
00473 {
00474 return(NULL);
00475 }
00476 else
00477 {
00478 for(n=0; n<MAX_PROCESSES; n++)
00479 {
00480 tmm->processList[n]=NULL;
00481 }
00482
00483
00484 tmm->pageSize=0;
00485 tmm->invPageTable=NULL;
00486 tmm->page=0;
00487 tmm->swap=NULL;
00488 tmm->watchPaging=0;
00489
00490
00491 tmm->mem=(ToyMem *)malloc(memSize*sizeof(ToyMem));
00492 tmm->memSize = memSize;
00493
00494
00495 for(n=0; n<memSize; n++)
00496 {
00497 tmm->mem[n].type=DATA_ERROR;
00498 }
00499
00500
00501 tmm->memFree = TMM_CreateSegList(0,memSize,NULL,NULL);
00502
00503
00504 return(tmm);
00505 }
00506 }
00507
00511 ErrMessage_t TMM_Free(ToyMM *tmm)
00512 {
00513 int n;
00514
00515 if(tmm==NULL) return(ERR_UNKNOWN);
00516
00517
00518 for(n=0; n<MAX_PROCESSES; n++)
00519 {
00520 if(tmm->processList[n])
00521 {
00522 if(TMM_PagingEnabled(tmm) ) {
00523 TMM_PagedTerminateProcess(tmm,n);
00524 }
00525 else
00526 {
00527 TMM_TerminateProcess(tmm,n);
00528 }
00529 }
00530 }
00531
00532
00533 if(tmm->invPageTable!=NULL)
00534 {
00535 free(tmm->invPageTable);
00536 }
00537
00538
00539 TMM_SwapDestroy(tmm);
00540
00541 free(tmm->mem);
00542 TMM_FreeSegList(tmm->memFree);
00543
00544 return(ERR_NONE);
00545 }
00546
00554 void TMM_VPrintMem(ToyMM *tmm, int process, int vaddr)
00555 {
00556 ToyMem *mem=NULL;
00557 int raddr=TMM_GetRealAddress(tmm,process,vaddr);
00558 if(raddr<0) return;
00559
00560 mem=tmm->mem+raddr;
00561
00562 if(mem->type==DATA_ERROR) return;
00563
00564 printf(LINE_PREFIX" %3d ",vaddr);
00565
00566 switch(mem->type)
00567 {
00568 case DATA_ERROR:
00569 break;
00570
00571 case DATA_INTEGER:
00572 printf("%d\n",mem->integer.value);
00573 break;
00574 case DATA_INSTRUCTION:
00575 printf("%s\n",DataType_List[DATA_INSTRUCTION][mem->instruction.value]);
00576 break;
00577 case DATA_STRING:
00578 printf("%s\n",mem->string.value);
00579 break;
00580
00581 default:
00582
00583 printf("Unknown mem type %d, ",mem->type);
00584 printf("Email me at monttyle@heavyspace.ca and tell me how you did this.\n");
00585 break;
00586 }
00587 }
00588
00595 void TMM_PrintMem(ToyMM *tmm, int addr)
00596 {
00597 ToyMem *mem=tmm->mem+addr;
00598
00599
00600 if(mem->type==DATA_ERROR) return;
00601
00602 printf(LINE_PREFIX" %3d ",addr);
00603 switch(mem->type)
00604 {
00605 case DATA_ERROR:
00606 break;
00607
00608 case DATA_INTEGER:
00609 printf("%d\n",mem->integer.value);
00610 break;
00611 case DATA_INSTRUCTION:
00612 printf("%s\n",DataType_List[DATA_INSTRUCTION][mem->instruction.value]);
00613 break;
00614 case DATA_STRING:
00615 printf("%s\n",mem->string.value);
00616 break;
00617
00618 default:
00619
00620 printf("Unknown mem type %d, ",mem->type);
00621 printf("Email me at monttyle@heavyspace.ca and tell me how you did this.\n");
00622 break;
00623 }
00624 }
00625
00630 SegList *TMM_GetSegmentNode(ToyMM *tm, int process, SegType_e sg)
00631 {
00632 SegList *list;
00633 int seg=sg;
00634
00635 if((process<0)||(process>=MAX_PROCESSES)) return(NULL);
00636 if(seg<0) return(NULL);
00637 if(tm->processList[process]==NULL) return(NULL);
00638
00639 list=TMM_SeekSegListHead(tm->processList[process]->segments);
00640
00641 while((list!=NULL)&&(seg>0))
00642 {
00643 seg--;
00644 list=list->next;
00645 }
00646
00647 return(list);
00648 }
00649
00651 int TMM_GetSegmentAddr(ToyMM *tm, int process, SegType_e seg)
00652 {
00653 SegList *list=TMM_GetSegmentNode(tm,process,seg);
00654
00655 if(list!=NULL) return(list->seg.pos);
00656 else return(-1);
00657 }
00658
00662 ErrMessage_t TMM_MarkMemEmpty(ToyMM *tmm,int addr, int len)
00663 {
00664 int n;
00665 for(n=addr; n<(addr+len); n++)
00666 {
00667 tmm->mem[n].type=DATA_ERROR;
00668 }
00669 return(ERR_NONE);
00670 }
00671
00675 ErrMessage_t TMM_CopyMem(ToyMM *tmm, int destaddr, int srcaddr, int len)
00676 {
00677 if(tmm==NULL) return(ERR_UNKNOWN);
00678
00679 while(len>0)
00680 {
00681 tmm->mem[destaddr++]=tmm->mem[srcaddr++];
00682 len--;
00683 }
00684 return(ERR_NONE);
00685 }
00686
00687 int TMM_FindFreeMem(ToyMM *tmm, int size)
00688 {
00689 SegList *list=NULL;
00690
00691 if(tmm==NULL) return(-1);
00692 list=tmm->memFree;
00693
00694 while(list!=NULL)
00695 {
00696 if(list->seg.len>=size) return(list->seg.pos);
00697
00698 list=list->next;
00699 }
00700
00701 return(-1);
00702 }
00703
00704 Process *TMM_GetProcess(ToyMM *tmm, int process)
00705 {
00706 if(tmm==NULL) return(NULL);
00707 else if(process<0) return(NULL);
00708 else if(process>=MAX_PROCESSES) return(NULL);
00709 else return(tmm->processList[process]);
00710 }
00711
00712 int TMM_ParseFilePtr(FILE *fp, ToyMM *tm, int prompt)
00713 {
00714 int line=0;
00715 char buf[160];
00716 ErrMessage_t error=ERR_UNKNOWN;
00717
00718 buf[0]='\0';
00719
00720 if(fp==NULL) return(-1);
00721
00722 if(prompt) printf(TMM_CONSOLE_PROMPT,line+1);
00723 fgets(buf,160,fp);
00724
00725
00726 if(strlen(buf)>1) error=TMM_ParseLine(buf,tm,++line);
00727 else error=ERR_NONE;
00728
00729 do
00730 {
00731 if(error!=ERR_NONE)
00732 {
00733 if(error==ERR_UNKNOWN)
00734 {
00735
00736 printf(ERR_PREFIX"Unknown error.\n");
00737 }
00738 else
00739 {
00740
00741 PRINT_ERROR(error);
00742 }
00743 if(error==ERR_PARSEEND)
00744 {
00745 fclose(fp);
00746 return(-1);
00747 }
00748 }
00749 buf[0]='\0';
00750
00751 if(prompt) printf(TMM_CONSOLE_PROMPT,line+1);
00752 fgets(buf,160,fp);
00753
00754
00755 if(strlen(buf)>1) error=TMM_ParseLine(buf,tm,++line);
00756 else error=ERR_NONE;
00757 }
00758 while(!feof(fp));
00759
00760
00761 if(error!=ERR_NONE)
00762 {
00763 if(error==ERR_UNKNOWN)
00764 {
00765
00766 printf(ERR_PREFIX"Unknown error.\n");
00767 }
00768 else
00769 {
00770
00771 printf(ERR_PREFIX"%s\n",ErrMessages[error]);
00772 }
00773 }
00774
00775 return(0);
00776 }
00777
00779 int TMM_ParseFile(const char *fname, ToyMM *tm)
00780 {
00781 int retval=-1;
00782 FILE *fp=NULL;
00783
00784 fp=fopen(fname,"r");
00785 if(fp==NULL) return(-1);
00786
00787 retval=TMM_ParseFilePtr(fp,tm,0);
00788
00789 fclose(fp);
00790
00791 return(retval);
00792 }