Embedded Systems Laboratory Alexandru Andrei alean@ida.liu.se TDDB63: Nachos -2- TDDB63 Lab lesson Multiprogramming - multiple user processes Page tables Process handling Lab 3 : Memory Management & System Calls Introduction to – and – making user programs in Nachos User memory vs Kernel memory in Nachos File & Console related syscalls Synchronizing kernel functions and data structures Lab 2 : System Calls Outline -3- TDDB63 Lab lesson System calls ”prototypes” in syscall.h FileSystem and OpenFile: 5.2 – 5.3 User Level Processes: Section 4 ¾machine/mipssim.cc (RaiseException) ¾machine.cc (Machine::RaiseException) ¾Userprog/exception.cc (ExceptionHandler) Machine: section 2.1 – 2.4 Examine exception handling in Read ”Road Map through Nachos” Introduction -4- TDDB63 Lab lesson Source files: Working dir. is ../code/userprog Central files for assignment ¾”Exception.cc” contains ExceptionHandler function ¾syscall.h - definitions and constants for system calls Files necessary for understanding how Nachos works ¾Progtest.cc – test routines, how to load & execute user prog. ¾Example of running Nachos with a user program: ¾nachos –x <user_program_name> ¾E.g.: ../userprog/nachos –x ../test/halt ¾/machine/machine.* - how MIPS emulator works Introduction (cont) -5- TDDB63 Lab lesson ¾translate.cc ¾data structures for managing translation from virtual page # -> physical page # ¾used for managing memory on behalf of user programs ¾mipssim.cc (ReadMem, Writemem, Translate, and OneInstruction) In code/machine: ¾data structures to keep track of executing user programs (address spaces) In code/userprog: addrspace.h, addrspace.cc Introduction (cont.) -6- System Calls OS Kernel User Application User Application System Calls System Calls TDDB63 Lab lesson User Application System Calls System Calls -7- TDDB63 Lab lesson Class Machine emulates MIPS processor Emulation – runs on MIPS simulator MIPS is a RISC architecture, with delayed loads Cross compile – compile in one machine for a different target machine Compiled with cross-compiler to MIPS machine code (see code/test/Makefile) User Programs -8- TDDB63 Lab lesson In nachos-3.4/code/test For a new test program, add it to the Makefile from nachos-3.4/code/test Simple C programs (any C program that doesn’t use library functions like printf) User Programs (cont.) -9- #include ”syscall.h” void main(void) { int i; char a[10]; for (i=0;i<=8;i++) a[i]=’a’; a[9]=’\0’; Create(a); i = Open(a); Write(”some text”, 10,i); Close(i); Halt(); } TDDB63 Lab lesson User Program - Example -10- TDDB63 Lab lesson halt.o: halt.c $(CC) $(CFLAGS) -c halt.c halt: halt.o start.o $(LD) $(LDFLAGS) start.o halt.o -o halt.coff ../bin/coff2noff halt.coff halt start.o: start.s ../userprog/syscall.h $(CPP) $(CPPFLAGS) start.s > strt.s $(AS) $(ASFLAGS) -o start.o strt.s rm strt.s all: halt shell matmult sort Test Program Makefile -11- ¾SC_Halt implemented TDDB63 Lab lesson see …/code/userprog/exception.cc ExceptionHandler see …/code/test/start.s ¾register2 (r2)-> type of system call ¾Additional arguments to system call in reg. r4-r7 ¾System calls return values in reg. r2 arguments in machine registers ”syscall” machine code instruction System Calls and Exception Handling void Machine::Run() { Instruction *instr = new Instruction; if(DebugIsEnabled('m')) printf("Starting thread \"%s\" at time %d\n", currentThread->getName(), stats->totalTicks); interrupt->setStatus(UserMode); for (;;) { OneInstruction(instr); interrupt->OneTick(); if (singleStep && (runUntilTime <= statstotalTicks)) Debugger(); } } -12TDDB63 Lab lesson Program Execution -13- TDDB63 Lab lesson Void Machine::OneInstruction(Instruction *instr){ int raw; int nextLoadReg = 0; int nextLoadValue = 0; if (!machine->ReadMem(registers[PCReg],4,&raw)) return; // exception occurred instr->value = raw; instr->Decode(); pcAfter = registers[NextPCReg] + 4; switch (instr->opCode) { Ænextslide OneInstruction() -14- case OP_SYSCALL: RaiseException(SyscallException, 0); return; switch (instr->opCode) { case OP_ADD: … case OP_DIV: … TDDB63 Lab lesson OneInstruction() (cont.) } -15- enabled at this point interrupt->setStatus(UserMode); TDDB63 Lab lesson ExceptionHandler(which); // interrupts are interrupt->setStatus(SystemMode); Void Machine::RaiseException(ExceptionType which, int badVAddr){ DEBUG('m', "Exception: %s\n", exceptionNames[which]); registers[BadVAddrReg] = badVAddr; DelayedLoad(0, 0); // finish anything in progress RaiseException() } -16- TDDB63 Lab lesson printf("Unexpected user mode exception %d %d\n", which, type); } else DEBUG('a', "Shutdown, initiated by user program.\n"); interrupt->Halt(); void ExceptionHandler(ExceptionType which) { int type = machine->ReadRegister(2); if ((which == SyscallException) && (type == SC_Halt)) { Exception Handling: System Calls -17- TDDB63 Lab lesson int Read(char* buf, int size, OpenFileId id) void Write(char* buf, int size, OpenFileId id) void Close(int fileid) See …/code/userprog/syscall.h for the list open file for read/write OpenFileId Open(char *filename) Create an empty file File operations (lab 2) void Create(char* filename) System Calls for File Operations }; -18- TDDB63 Lab lesson bool Remove(char *name) { return Unlink(name) == 0; } } int fileDescriptor = OpenForReadWrite(name, FALSE); if (fileDescriptor == -1) return NULL; return new OpenFile(fileDescriptor); OpenFile* Open(char *name) { } int fileDescriptor = OpenForWrite(name); if (fileDescriptor == -1) return FALSE; close(fileDescriptor); return TRUE; FileSystem(bool format) {} bool Create(char *name, int initialSize) { public: class FileSystem { FileSystem -19- TDDB63 Lab lesson int ReadAt(char *into, int numBytes, int position) { } int WriteAt(char *from, int numBytes, int position) { } int Read(char *into, int numBytes) { } int Write(char *from, int numBytes) { } …… class OpenFile { public: OpenFile(int f) { file = f; currentOffset = 0; } // open the file ~OpenFile() { Close(file); } // close the file OpenFile -20- TDDB63 Lab lesson Read and Write must choose based on the OpenFileId if it’s a file or the Console The actual file operations are handled by the FileSystem and OpenFile Global unique id for each open file ConsoleInput and ConsoleOutput OpenFileId File Related SysCalls -21- TDDB63 Lab lesson ie. synchronize the console operations The Console class handles reading/writing from/to the console at the char level void PutChar(char ch) char GetChar() TODO: introduce the possibility to read/write strings (char* or char[]) Console -22- TDDB63 Lab lesson Console( char *readFile, char *writeFile, VoidFunctionPtr readAvail, VoidFunctionPtr writeDone, int callArg ); Console Internals -23- TDDB63 Lab lesson void ReadAvail(int arg) {…} void WriteDone(int arg) {…} console = new Console(NULL, NULL, ReadAvail, WriteDone, 0); Console Internals 0000 FFFF 0000 Process 2 Process 1 Kernel -24- TDDB63 Lab lesson Virtual memory vs. Phisycal memory Process2: FFFF char buffer[10] FFFF Open(buffer); Memory Process1: char buffer[10] Create(buffer); 0000 User Programs&User Memory -25- TDDB63 Lab lesson for (int i = 0; i < filename_length; i++) { int data; machine->ReadMem(address + i, 1, &data); filename[i] = data; } filename[i]=‘\0’; } void UserToKernel(void) { char* filename = new char[100]; int address = machine->ReadRegister(4); UserToKernel -26- TDDB63 Lab lesson Create(char* filename) Read(char* buf, int size, OpenFileId id) User space vs. Kernel Space User address vs. Kernel Address Pointer arguments passed to system calls must be translated to/from user space example: Important ! -27- TDDB63 Lab lesson int Read(char* buf, int size, OpenFileId id) void Write(char* buf, int size, OpenFileId id) void Close(int fileid) See …/code/userprog/syscall.h for details open file for read/write OpenFileId Open(char *filename) Create an empty file File operations (lab 2) void Create(char* filename) TODO: System Calls for File Operations (Lab2) -28- TDDB63 Lab lesson ¾A pageTable inside the AddrSpace object: translation of virtual address to physical address ¾ Different page table for each process One address space object for each process Several processes (user programs) reside in memory at the same time ¾machine->pageTable contains the pageTable of the current threads address space Multiprogramming Lab 3 - Memory Management -29- TDDB63 Lab lesson Separate OpenFile objects for each process Different processes can open the same file Each process has it’s own offset into file (i.e. different OpenFile object) Lab 3 - Memory Management (cont.) -30- TDDB63 Lab lesson Only one user program in the lab #2 through system calls (open file, start a new process, etc.) Reside in user address space Communication with the kernel User Programs -31- TDDB63 Lab lesson Uninitialized variable section are not read from the file (as it contains all 0’s). Nachos creates an address space Copies the content of the instructions’ and initialized variable segments into the address space. When executing a user program, User Level Processes -32- TDDB63 Lab lesson Creating an address space Allocating physical memory for the AddrSpace Load content of executable into the physical memory Initialize registers and address translation tables Invoke machine::Run() to start executing. Run turns on the simulated MIPS machine and enter into an infinite loop that executes one instruction at a time. progtest.cc to see an example Nachos process are formed by: Process Creation thread 2 thread variables thread 1 thread variables Other machine variables machine->mainMemory machine -33- Address space of Nachos process Addresses in Nachos TDDB63 Lab lesson of the MIPS machine) (”Physical” memory Adress space of user program. Lab 2 - User Programs Pages •Page number •Same size •Allocation unit for a process -34- TDDB63 Lab lesson Machine.h contains the details regarding the memory size, number of pages, page size, etc. Memory Memory Organization Process1 2 1 0 ... Physical Memory -35- TDDB63 Lab lesson Only one process running Every process gets the same physical pages pageTable Machine object Running process Lab 3 - Page tables in lab 2 More than one process running bitMap can be used for allocation pageTable Machine object -36- Process1 n-1 1 2 Running process Process2 n 3 0 TDDB63 Lab lesson ... Physical Memory Lab 3 - Page tables in lab 3 ¾ BitMap(int nitems) ¾ Mark ¾ Clear ¾ Test ¾ Find -37- TDDB63 Lab lesson // total number of items // mark (allocate) a position // clear (free) a position // check if a position is marked // find a free position and mark it AddrSpace constructor allocates memory pages In lab 2 all memory is assigned to one address space In lab 3 several address spaces will exist Use a BitMap object to keep track of free pages Address spaces (AddrSpace object) Lab 3 - Address spaces -38- TDDB63 Lab lesson NoffHeader object stored in the beginning of the file Three Segment objects in the header Noff binary format, noff header Loads the executable ¾ Amount of memory needed is stored in noff-header Takes an executable (filename) Allocates memory, sets up page table AddrSpace constructor Lab 3 - Address spaces -39- TDDB63 Lab lesson ¾Noff header (information concerning segments below) ¾Code segment – program residence ¾Initialized variables segment ¾Unitialized variables segment Noff consists of four parts Noff: Nachos Object File Format Compare with coff(Unix), com, exe (DOS) Noff Executable Format -40- TDDB63 Lab lesson ¾ virtualAddr: segment’s starting address in virtual memory ¾ inFileAddr: start of the segment in Noff file ¾ Size: size of the segment For each of the remaining sections Nachos maintains ¾ Reserved number indicating that the file is in Noff format noffMagic: Noff format check (4 bytes) ¾ information concerning segments below ¾ Describe content of the rest of the file, giving information about programs’s instructions, initialized and uninitialized variables Noff: header Noff Format (cont) -41- TDDB63 Lab lesson ¾ Declared but unassigned data (empty arrays etc). ¾ Not stored in the file. uninitData ¾ initialized data (constant strings etc) initData ¾ the executable machine code code Segments: Address spaces ¾ size of the segment size -42- ¾ offset of segment in the file inFileAddr TDDB63 Lab lesson ¾ start address of segment in the address space virtualAddr The Segment object: Lab 3 - Address Space -43- TDDB63 Lab lesson Simultaneously running user programs Using pre-emptive switches between threads Tests: Allocate/Deallocate physical pages (addrspace) Setting translation tables Implement Exec, Exit, Join TODO: Memory Management -44- TDDB63 Lab lesson Load a program/file from disk into a new AddrSpace Create a new Thread for it to execute in (forks and execute a new program) Return a unique global id for that AddrSpace object (SpaceId of the new program) Multiple processes and threads (lab 3) SpaceId Exec(char *name) TODO: Syscalls for Mem. Management. (Lab 3) -45- TDDB63 Lab lesson exits the calling user process returns ”status” to the parent process void Exit(int status) Wait for the process with id id to exit Return the exit status of that process int Join(SpaceId id) TODO: Lab 3 System Calls for Exit & Join -46- See …/code/userprog/syscall.h Roadmap through Nachos, section 4 TDDB63 Lab lesson Switch to another thread, in this address space or in another (i.e. another process) void Yield() --optional Start a new user level thread in the same address space Execute a function func in that thread void Fork(void (* func)()) --optional To do: Lab 3 System Calls for Mem. Mgt.