Due: Dec 18, 2006
Generally speaking, you should begin your work starting from your solution to hw5. In particular, we assume that SOS/STM has the ability to do string I/O, supports multiprocessing, and has simple process synchronization. If you like, you can begin with our files stm.h, stm.c, sos.h, sos.c (but note that these lack the synchronization primitives).
In this document, I will first mention several possible projects, of varying degrees of difficulty, essentially independent of each other. Then I will go into detail one particular project, which is to introduce demand paging into SOS.
In this project, you are allowed to work in pairs (you would have to work hard to convince me if you want to work in groups larger than 2. Working alone is also fine.
CVS Tool: In this course, we emphasize two tools used by programmers: the C language and Makefile. Whether you work alone or in pairs, you have the opportunity to learn another important system building tool, "version control systems". These are software that help us manage large software projects that are worked on by many (or even one) programmer. We will like to use the "Concurrent Version System" (CVS) which is freely available on many platforms, including CYGWIN. Such systems allows you to keep track of different versions of a file, and even develop branching versions. Different users can simultaneously modify a file, since the system has a method of reconciling differences (which is quite amazing if you first see this at work).
If you want to use CVS, please see my web page on how to use CVS. Send us your pub_id.dsa file, and you and your partner will be ready to share files in this project.
LOA R15,=1instead of having to explicitly load the constant "1" into a location, and write the address of that location into our instruction for this load instruction. Also, we would like to be able to explicitly enter a literal constant at the current location: e.g.,
CON 123 CON "Hello"should load the CONstant 123, followed by the ASCII codes for "H", "e", "l", "l", "o" into consecutive locations. Similarly, we should be able to reserve a block of memory: e.g.,
RES 100will REServe the next block of 100 words of memory. The directory for the original assembler is HERE.
Implement the ability of stm programs to call system library routines. The ability of SOS to open/read/close files, as described in the previous project, would be useful, but otherwise, we can simulate this. This requires some primitive loader software. Write some useful library be able to write useful library routines to provide more flexible I/O (the equivalent of scanf and printf).
Command | Arguments | Action |
---|---|---|
jobs | [-q quantum][-d debug_level][-m max] prog1.stm prog2.stm ... | similar to arguments for SOS in hw4 |
status | [no arguments] | shows the list of jobs currently running |
halt | [no arguments] | shuts down the stm hardware |
What are some parameter values that can go into the initfile? The file [initfile] is optional (or has default values). Run time parameters such as Quantum=5, DebugLevel=0, PageSize=512, UserSpaceStart=16K, etc.
We should divide the memory into Kernel Space and User Space. UserSpaceStart is the starting address for User Space (so Kernel Space is mem[0] to mem[UserSpaceStart-1]).
We can tell you more about what is wrong: when we want to replace a page with mbit=1 (modify bit is set), there must be write-to-disk, followed by a read-from-disk. It seems that this program forgets to the write-to-disk.
In the following, we try to outline the logic found in the buggy file. To do paging, you need a secondary memory. So, in addition to main memory (mem) we have another array called disk.
#define VASIZE 262144 /* 2^18 virtual address space */ #define RAMSIZE 65536 /* 2^16 main memory */ #define DISKSIZE 2097152 /* 2^22 disk memory */ #define PAGESIZE 512 /* 2*9 page size */ #define MAXFRAMES (RAMSIZE / PAGESIZE) /* frame table size */ #define MAXPAGES (DISKSIZE / PAGESIZE) /* page table size */
struct pageTableEntry { int frame, /* frame number (frame=-1 means not loaded)*/ disk, /* relative page number in disk */ rbit, mbit, timestamp; } struct processTableEntry { char name[NAMESIZE]; int regs[NUMREGS]; int status; /* 0=ready, 1=blocked, 2=terminated */ struct pageTableEntry pageTable[MAXPAGES]; /* page table of process*/ int basePage; /* first page in disk for process */ int pageLimit; /* max number of disk page for process */ } struct processTableEntry processTable[MAXPROCS]; struct pageTableEntry pageTable[MAXPAGES]; /* page table of current process*/You would want procedures to initialize a pageTable, and to load a pageTable from the processTable into the current pageTable. (For simplicity, you do not hav eto put this table into the mem[].)
freeList[MAXFRAMES]; /* freeList[n]=1 is occupied, 0 if free */Assume a routine to find a free frame (return -1 if no more free frames).
int disk[DISKSIZE]; /* disk */ int pageFault = -1; /* if pageFault is not -1, it is the page that must be loaded to memory */ int clock; /* system clock */You need procedure to initialize the disk, and to load a process into the disk.
struct diskRequest { int diskPage; /* page number in disk */ int memPage; /* frame number in main memory */ int write; /* write=1 if writing, write=0 if reading */ } struct diskRequest RequestTable[MAXPROCS]; /* RequestTable[n] is request of Process n */You need functions to (1) post a disk request, (2) process a disk request, (3) read from Disk, and (4) write to Disk.
int physAddr( int relAddr, int writeBit); NOTE: writeBit=1 if we want to write, writeBit=0 if we want to read 1. Make sure that relAddr is between 0 and VASIZE. Else segment fault. 2. Initialize pageFault=-1. (This will change if we need a page fault) 3. page = ralAddr / PAGESIZE 4. frame = pageTable[page].frame 5. Update rbit, mbit, timestamp of pageTable[page]. (N.B. mbit=writeBit) 6. if (frame = -1) pageFault = page; (indicate need for page fault) else return ((frame * PAGESIZE) + (relAddr % PAGESIZE))
exec_instr(op, ra, ad, ...) { ... switch (op) { case 0: pa = physAddr(ad, 0); /* 0=read request */ if (pageFault == -1) regs[ra] = mem[pa]; /* load register ra */ break; case 1: ... ... }//switch ... }//exec_instrNote that in case of page fault, the instruction is not carried out. That is because the current process would be context switched anyway, and block while waiting for disk I/O.
void execPageFault () { 1. frame = freeFrame(); // try to get a free frame 2. if (frame != -1) // found free frame! Update page table Return 3. Find a frame to evict // this is the victim frame 4. If the mbit of victim is set, post a disk request to write post a disk request to read contextSwitch( 1 ) // 1=block current process else post a disk request to read contextSwitch( 0 ) // 0=nonblock current process }