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 "ToyLoad.h"
00022 #include "ToyMemPage.h"
00023 #include "ToyVirtualMem.h"
00024 #include "ToySwap.h"
00025
00026
00027
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)
00101 {
00102 tmm->watchPaging=0;
00103 return(ERR_NONE);
00104 }
00105 else if(enable==1)
00106 {
00107 tmm->watchPaging=1;
00108 return(ERR_NONE);
00109 }
00110 else
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 {
00126 return(ERR_INVALIDPAGESIZE);
00127 }
00128
00129
00130 for(n=1; n<MAX_PROCESSES; n++)
00131 if(tm->processList[n]!=NULL)
00132 {
00133 TMM_TerminateProcess(tm,n);
00134 }
00135
00136
00137 if(tm->memFree!=NULL) TMM_FreeSegList(tm->memFree);
00138 tm->memFree=NULL;
00139
00140
00141 tm->invPageTable=(InvPageTable *)malloc(sizeof(InvPageTable)*(tm->memSize/pagesize));
00142
00143
00144 if(tm->invPageTable==NULL)
00145 {
00146 return(ERR_UNKNOWN);
00147 }
00148
00149
00150 tm->pageSize=pagesize;
00151
00152
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
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
00214 while(pages>0)
00215 {
00216
00217
00218
00219
00220
00221 page++;
00222 pages--;
00223 }
00224
00225 page-=TMM_GetNumFrames(tmm,size);
00226
00227 if(pages!=0)
00228 {
00229
00230 return(ERR_INSUFFICIENTMEM);
00231 }
00232
00233
00234 newnode=TMM_CreateSegList(page*tmm->pageSize,size,NULL,NULL);
00235 if(newnode==NULL) return(ERR_UNKNOWN);
00236
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
00252 if(tmm==NULL) return(ERR_UNKNOWN);
00253
00254 else if((ID<0)||(ID>=MAX_PROCESSES)) return(ERR_UNKNOWN);
00255 else if(tmm->processList[ID]!=NULL)
00256 {
00257 return(ERR_PROCESSEXISTS);
00258 }
00259
00260
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
00278 tmm->processList[ID]=proc;
00279
00280 for(n=0; n<nSegs; n++)
00281 {
00282 newsizes[n]=sizes[n];
00283 }
00284
00285
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
00296 list=TMM_GetSegmentNode(tmm,ID,SEG_HEAP);
00297
00298
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
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
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
00387 tm->processList[process]=NULL;
00388
00389 if(proc->pagetable!=NULL)
00390 {
00391 free(proc->pagetable);
00392 }
00393
00394
00395 free(proc);
00396
00397 return(ERR_NONE);
00398 }
00399
00401 void TMM_PrintInvPage(ToyMM *tmm, int frame, int show_framestatus)
00402 {
00403
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
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 {
00470 case SEG_CODE:
00471 case SEG_DATA:
00472 break;
00473
00474
00475 case SEG_STACK:
00476 (*page)=(TMM_GetNumPages(tmm))-1;
00477 (*size)=tmm->pageSize;
00478 break;
00479
00480
00481 case SEG_HEAP:
00482 (*size)=tmm->pageSize;
00483 break;
00484
00485
00486 default:
00487 return(ERR_UNKNOWN);
00488 }
00489
00490 return(ERR_NONE);
00491 }