Nachos Instructional OS: Part 2

Slides:



Advertisements
Similar presentations
Process Management.
Advertisements

Chapter 3 Process Description and Control
Chapter 3 Memory Management. 3.1 From Programs To Address Space 3 steps to run the programs of an application – A Compiler translates the source code.
Introducing User Programs into Nachos SPARC HW OS Kernel (Solaris) MIPS sim Nachos User Programs Syscalls Machine instructions MIPS instr Nachos calls.
CSC 501 Lecture 2: Processes. Von Neumann Model Both program and data reside in memory Execution stages in CPU: Fetch instruction Decode instruction Execute.
Processes CSCI 444/544 Operating Systems Fall 2008.
1 CS 333 Introduction to Operating Systems Class 2 – OS-Related Hardware & Software The Process Concept Jonathan Walpole Computer Science Portland State.
Introduction to Kernel
Advanced OS Chapter 3p2 Sections 3.4 / 3.5. Interrupts These enable software to respond to signals from hardware. The set of instructions to be executed.
Process in Unix, Linux and Windows CS-3013 C-term Processes in Unix, Linux, and Windows CS-3013 Operating Systems (Slides include materials from.
CS-502 Fall 2006Processes in Unix, Linux, & Windows 1 Processes in Unix, Linux, and Windows CS502 Operating Systems.
Computer Organization and Architecture
Unix & Windows Processes 1 CS502 Spring 2006 Unix/Windows Processes.
1 Process Description and Control Chapter 3 = Why process? = What is a process? = How to represent processes? = How to control processes?
7/3/20151 Announcement (No deadline extension for the rest of quarter) Project 2 final deadline is Tuesday midnight May 19 Project 0 resubmission for autograding.
Processes in Unix, Linux, and Windows CS-502 Fall Processes in Unix, Linux, and Windows CS502 Operating Systems (Slides include materials from Operating.
1 User-Level Processes Needed to test the system call you implement The “Noff” format file required –Look at the Makefile in test MIPS “syscall” instruction.
Process. Process Concept Process – a program in execution Textbook uses the terms job and process almost interchangeably A process includes: – program.
CSE 451: Operating Systems Autumn 2013 Module 6 Review of Processes, Kernel Threads, User-Level Threads Ed Lazowska 570 Allen.
Process Description and Control Chapter 3. Major Requirements of an OS Interleave the execution of several processes to maximize processor utilization.
1 CS503: Operating Systems Part 1: OS Interface Dongyan Xu Department of Computer Science Purdue University.
System Calls 1.
Nachos Instructional OS: Part 2
Welcome to the World of Nachos CPS 110 Spring 2004 Discussion Session 1.
Process in Unix, Linux, and Windows CS-3013 A-term Processes in Unix, Linux, and Windows CS-3013 Operating Systems (Slides include materials from.
Implementing Processes. Review: Threads vs. Processes 1. The process is a kernel abstraction for an independent executing program. includes at least one.
Introduction to Processes CS Intoduction to Operating Systems.
CS1550 Assignment 5 Multiprogramming Implementation notes Matt Craven.
CSC 501 Lecture 2: Processes. Process Process is a running program a program in execution an “instantiation” of a program Program is a bunch of instructions.
Exec Function calls Used to begin a processes execution. Accomplished by overwriting process imaged of caller with that of called. Several flavors, use.
Chapter 1 Process and Thread. 1.2 process The address space of a program – Text – Code – Stack – Heap A set of registers – PC – SP Other resources – Files.
Computer Architecture and Operating Systems CS 3230: Operating System Section Lecture OS-1 Process Concepts Department of Computer Science and Software.
Lecture 3 Process Concepts. What is a Process? A process is the dynamic execution context of an executing program. Several processes may run concurrently,
Operating Systems Lecture 7 OS Potpourri Adapted from Operating Systems Lecture Notes, Copyright 1997 Martin C. Rinard. Zhiqing Liu School of Software.
Hardware process When the computer is powered up, it begins to execute fetch-execute cycle for the program that is stored in memory at the boot strap entry.
1 CSE 451 Section 2: Interrupts, Syscalls, Virtual Machines, and Project 1.
ITEC 502 컴퓨터 시스템 및 실습 Chapter 2-1: Process Mi-Jung Choi DPNM Lab. Dept. of CSE, POSTECH.
Project 2: Initial Implementation Notes Tao Yang.
Nachos Tutorial Courtesy: University of Waterloo.
Nachos Instructional OS CS 270, Tao Yang, Spring 2011.
Interrupt driven I/O. MIPS RISC Exception Mechanism The processor operates in The processor operates in user mode user mode kernel mode kernel mode Access.
Processes CS 6560: Operating Systems Design. 2 Von Neuman Model Both text (program) and data reside in memory Execution cycle Fetch instruction Decode.
1 Computer Systems II Introduction to Processes. 2 First Two Major Computer System Evolution Steps Led to the idea of multiprogramming (multiple concurrent.
Concurrency, Processes, and System calls Benefits and issues of concurrency The basic concept of process System calls.
Processes, Threads, and Process States. Programs and Processes  Program: an executable file (before/after compilation)  Process: an instance of a program.
Processes and Virtual Memory
Programs and Processes. The Virtual Address Space A typical process VAS space includes: user regions in the lower half V->P mappings specific to each.
Hardware process When the computer is powered up, it begins to execute fetch-execute cycle for the program that is stored in memory at the boot strap entry.
Nachos Instructional OS: Part 2
Interrupt driven I/O Computer Organization and Assembly Language: Module 12.
1 Process Description and Control Chapter 3. 2 Process A program in execution An instance of a program running on a computer The entity that can be assigned.
1 Lecture 6 “Nachos” n nachos overview n directory structure n nachos emulated machine n nachos OS n nachos scheduler n nachos threads.
Introduction to Kernel
Processes and threads.
Process concept.
Operating Systems CMPSC 473
Process Management Process Concept Why only the global variables?
CS 6560: Operating Systems Design
Protection of System Resources
Modeling Page Replacement Algorithms
Processes in Unix, Linux, and Windows
More examples How many processes does this piece of code create?
Processes in Unix, Linux, and Windows
System Structure and Process Model
CSE 451: Operating Systems Spring 2012 Module 6 Review of Processes, Kernel Threads, User-Level Threads Ed Lazowska 570 Allen.
Modeling Page Replacement Algorithms
Processes in Unix and Windows
CS510 Operating System Foundations
Presentation transcript:

Nachos Instructional OS: Part 2 Tao Yang 4/22/2017 Nachos Instructional OS: Part 2 CS 170, Tao Yang, Fall 2015

Announcement and update Project 1 deadline was extended. Project 2 description was revised last weekend. Start now or you miss deadline There are bonus points to submit and pass 1/3 of autograding by this Saturday. Midterm exam sample was given out. Exercise 1 will be updated in next few days. Some students still look for a partner… 4/22/2017

What to learn? How to execute a program in Nachos Produce binary MIPS code from a C program Execute this MIPS code in a tiny space Make a simple Nachos system call in a C program Project 2. Support the execution of multiple processes Support multiprogramming and memory protection with address translation using 1-level page table System calls for process execution. System calls for a simple file system interface. 4/22/2017

System Layers Nachos kernel threads Thread 1 Thread 2 Thread N User process: Binary code User process: Binary code Nachos kernel threads Thread 1 Thread 2 Thread N Nachos OS modules (Threads mgm, File System, Code execution/memory mapping, System calls/Interrupt) MIPS Virtual Machine (Memory, Disk, Console) Base Operating System (Linux for our class)

Virtual Machine Layer under machine subdirectory. Approximates the MIPS architecture Can execute a sequence of MIPS instructions. Machine object SP Rn PC memory page table registers Timer 4/22/2017

Two modes of executions User mode: execute instructions which only access the user space. Kernel mode kernel executes when Nachos first starts up or when an instruction causes a trap illegal instruction, page fault system call Nachos layer 4/22/2017

Code execution steps in Nachos Load instructions into the machine's memory. Initialize registers (program counter, etc). Tell the machine to start executing instructions. The machine fetches the instruction, decodes it, and executes it. Repeat until all instructions are executed. Handle interrupt/page fault when needed User binary code Nachos Nachos execution layer MIPS Machine 4/22/2017

Machine Object: Implement a MIPS machine Tao Yang 4/22/2017 Machine Object: Implement a MIPS machine an instance created when Nachos starts up. Supported public variables: Registers: 40 registers. 4KB Memory: Byte-addressable. 32 pages (128Bytes) Virtual memory: use a single linear page table or a software-managed TLB. Machine object SP Rn PC memory page table 4/22/2017

Code/machine/machine.h class Machine { char *mainMemory; // physical memory to store user program, // code and data, while executing int registers[NumTotalRegs]; // CPU registers, for executing user programs TranslationEntry *pageTable; unsigned int pageTableSize; } Machine object SP Rn PC memory page table 4/22/2017

Machine Object: Supported operations Machine(bool debug);//allocate memory of 32 pages (128bytes per page). Initialize memory/register/ page table Translate(int virtAddr, int* physAddr, int size, bool writing); OneInstruction(); // Run one instruction of a user program. Run(); // Run a user program ReadRegister(int num); WriteRegister(int num, int value); ReadMem(int addr, int size, int* value); WriteMem(int addr, int size, int value); 4/22/2017

Code/machine/ipssim.cc void Machine::Run(){ Instruction *instr = new Instruction; // storage for decoded instruction interrupt->setStatus(UserMode); for (;;) { OneInstruction(instr); //fetch and execute one instruction interrupt->OneTick(); //advance clock } 4/22/2017

Code/machine/machine.h class Instruction { public: void Decode(); // decode binary representation of instruction unsigned int value; // binary representation of the instruction unsigned char opCode; // Type of instruction unsigned char rs, rt, rd; // Three registers from instruction. int extra; // offset or other purpose. Treat as 0 };

Code/machine/ipssim.cc Void Machine::OneInstruction(Instruction *instr) { //Fetch an instruction and then decode if (!machine->ReadMem(registers[PCReg], 4, &raw)) return; //if error, return instr->value = raw; instr->Decode(); // Execute the instruction switch (instr->opCode) { … case OP_ADDU: registers[instr->rd] = registers[instr->rs] + registers[instr->rt];break; case OP_SW: machine->WriteMem(registers[instr->rs], 4, registers[instr->rt]); break; case OP_SYSCALL: RaiseException(SyscallException, 0); return; } // Advance program counters. registers[PCReg] = registers[NextPCReg]; registers[NextPCReg] = pcAfter; //which is registers[NextPCReg] + 4;

Code/machine/translate.cc bool Machine::WriteMem(int addr, int size, int value) { ExceptionType exception; int physicalAddress; exception = Translate(addr, &physicalAddress, size, TRUE);//address translation if (exception != NoException) { machine->RaiseException(exception, addr); return FALSE; } switch (size) { //Copy value to the target physical memory address properly case 1: machine->mainMemory[physicalAddress] = (unsigned char) (value & 0xff); break; case 2: *(unsigned short *) &machine->mainMemory[physicalAddress] = ShortToMachine((unsigned short) (value & 0xffff)); break; case 4: …. } bool Machine::ReadMem(int addr, int size, int *value) { …

A Simple Page Table process page table PFN 0 PFN 1 Each process has its own page table. Virtual addresses are translated relative to the current page table. PFN i PFN i + offset page #i offset user virtual address physical memory page frames

Code/machine/translate.cc Physical page use bit | dirty bit ExceptionType Machine::Translate(int virtAddr, * physAddr, size, writing) { unsigned int vpn, offset; TranslationEntry *entry; unsigned int pageFrame; // calculate virtual page number, and offset within the page vpn = (unsigned) virtAddr / PageSize; offset = (unsigned) virtAddr % PageSize; entry = &pageTable[vpn]; pageFrame = entry->physicalPage; entry->use = TRUE; // set the use, dirty bits if (writing) entry->dirty = TRUE; *physAddr = pageFrame * PageSize + offset; // compute physical address return NoException; } Physical page use bit | dirty bit

Virtual Machine Layer Machine object page table memory registers Timer SP Rn PC memory page table registers Timer Interrupt 4/22/2017

Interrupt Object Maintain an event queue with a simulated clock. Supported operations: Schedule(VoidFunctionPtr handler, int arg, int when, IntType type) Schedule a future event to take place at time ``when''. Usage: schedule a yield at random interval. SetLevel(IntStatus level). Used to temporarily disable and re-enable interrupts. Two levels are supported: IntOn and IntOff. OneTick()—advance 1 clock tick CheckIfDue(bool advanceClock). Examines if some event should be serviced. Idle(). ``advances'' to the clock to the time of the next scheduled event 4/22/2017

Interrupt::OneTick() Software managed clock. The clock advances 1 tick after one binary instruction execution with user mode , 10 with system mode after every restored interrupt (disable/enable Interrupt) or after the MIPS simulator executes one instruction. When the ready list is empty, fast-advance ticks until the next scheduled event happens. 4/22/2017

Timer object Generate interrupts at regular or random intervals Then Nachos invokes the predefined clock event handling procedure. Supported operation: Timer(VoidFunctionPtr timerHandler, int callArg, bool doRandom). Create a real-time clock that interrupts every TimerTicks (100) time units Or set this a random number for random mode nachos –rs 0 Setup a random timer that requests a thread yield

Console Object Simulates a character-oriented CRT device Data can be written to the device one character at a time through the PutChar() routine. Input characters arrive one-at-a-time. They can be retrieved by GetChar(). Supported operations: Console(char *readFile, char *writeFile, VoidFunctionPtr readAvail,VoidFunctionPtr writeDone, int callArg). Create a console instance.``readFile'' is the Unix file of where the data is to be read from; if NULL, standard input is assumed. PutChar(char ch) GetChar()

Disk Object Simulates the behavior of a real disk. The disk has only a single platter, with multiple tracks (32). Each track contains the same number of sectors (32). Allow only one pending operation at a time. Contain a ``track buffer'' cache. Immediately after seeking to a new track, the disk starts reading sectors, placing them in the track buffer. Supported operations: Disk(char *name, VoidFunctionPtr callWhenDone, int callArg) ReadRequest(int sectorNumber, char *data) WriteRequest(int sectorNumber, char *data) ComputeLatency(int newSector, bool writing) 4/22/2017

Executing a user program halt user space MIPS instructions executed by the emulator data ExceptionHandler() Nachos kernel MIPS emulator Machine::Run() fetch/execute examine/deposit SaveState/RestoreState examine/deposit Rn page table process page tables Machine object SP PC registers memory

From C program to MIPS binary myprogram.c myprogram.o object file int j; char* s = “hello\n”; int p() { j = write(1, s, 6); return(j); } data assembler data data data libraries and other objects ….. p: store this store that push jsr _write ret etc. linker Executable images are also built from separately developed components (modules)... separate compilation symbol tables ...linked together by system utilities. cross-module procedure calls and data references relocation records and linkage sections static link-and-load in “traditional” Unix DLLs and shared libraries importance of calling conventions gcc compiler data program myprogram.s myprogram (executable file)

Binary code format (Noff) Source code: under userprog subdirectory. Current Nachos can run a single MIPS binary (Noff format) type ``nachos -x ../test/halt''. A user program must be compiled using a cross-platform gcc compiler that generates MIPS code. A Noff-format file contains (bin/noff.h) the Noff header, describes the contents of the rest of the file executable code segment (TEXT) initialized data segment (DATA) uninitialized data segment (BSS). 4/22/2017

Space usage during execution of a C program STACK HEAP BSS DATA TEXT Stack grows from top-down. Heap grows bottom-up Uninitialized data Initialized data Code

TEXT, DATA, BSS, HEAP, STACK in C Tao Yang 4/22/2017 TEXT, DATA, BSS, HEAP, STACK in C Int f3=3; /* DATA segment */ Int f1; /*BSS segment*/ def[] = "1"; int main(void) { static char abc[12]; /* BSS segment */ static float pi = 3.14159; int i = 3; /* Stack*/ char *cp; cp= malloc(10); /* HEAP for allocated chunk*/ f1= i+f3; /* code is in TEXT. f1 on STACK*/ strcpy(abc , "Test" ); } STACK HEAP BSS DATA TEXT DATA or BSS? DATA or BSS or STACK? DATA or BSS or STACK? Where is “Test”? DATA or BSS or STACK? 4/22/2017

TEXT, DATA, BSS, HEAP, STACK in C Tao Yang 4/22/2017 TEXT, DATA, BSS, HEAP, STACK in C Int f3=3; /* DATA segment */ Int f1; /*BSS segment*/ def[] = "1"; /* DATA segment */ int main(void) { static char abc[12], /* BSS segment */ static float pi = 3.14159; /* DATA segment */ int i = 3; /* Stack*/ char *cp; /*stack*/ cp= malloc(10); /*malloc allocates space from HEAP*/ f1= i+f3; /* code is in TEXT*/ strcpy(abc , "Test" ); /* “Test” is located in DATA segment */ } STACK HEAP BSS DATA TEXT 4/22/2017

Noff format virtualAddr: virtual address that segment begins at. . Each segment has the following information: virtualAddr: virtual address that segment begins at. inFileAddr: Pointer within the Noff file where that section actually begins. The size (in bytes) of that segment. STACK HEAP BSS DATA TEXT 4/22/2017

User process for executing a program A Nachos thread is extended as a process Each process has its own address space containing Executable code (Code segment) Initialized data (Data segment) Uninitialized data (BSS) Stack space for function calls/local variables how big is address space? A process owns some other objects, such as open file descriptors. 4/22/2017

Steps in User process creation Tao Yang 4/22/2017 Steps in User process creation Currently only execute a single user program. Create an address space. Zero out all of physical memory (machine->mainMemory) Read the binary into physical memory and initialize data segment. Initialize the translation tables to do a one-to-one mapping between virtual and physical addresses. Zero all registers, setting PCReg and NextPCReg to 0 and 4 respectively. Set the stackpointer to the largest virtual address of the process (stack grows downward). 4/22/2017

Key Calling graph when Nachos executes under userprog directory Executable file ReadAt() Space= New AddrSpace() in addrspace.cc Initialize() in system.cc Machine-> WriteRegister() Space-> InitRegisters() main() in main.cc StartProcess () in progtest.cc Space ->RestoreState() Machine-> OneInstruction() Machine->Run () in mipssim.cc Interupt-> OneTick() In Interupt.cc 4/22/2017

Creating a Nachos Process (code/userprog/progtest.cc) Create a handle for reading text and initial data out of the executable file. void StartProcess(char *filename) { OpenFile *executable; AddrSpace *space; executable = fileSystem->Open(filename); if (executable == NULL) { printf("Unable to open file %s\n", filename); return; } space = new AddrSpace(executable); currentThread->space = space; delete executable; // close file space->InitRegisters(); space->RestoreState(); machine->Run(); ASSERT(FALSE); Create an AddrSpace object, allocating physical memory and setting up the process page table. Set address space of current thread/process. Initialize registers, load pagetable, and begin execution in user mode. Run binary code

Creating a Nachos Address Space (code/userprog/addrspace.cc) AddrSpace::AddrSpace(OpenFile *executable) { NoffHeader noffH; unsigned int i, size; executable->ReadAt((char *)&noffH, sizeof(noffH), 0); // how big is address space? size = noffH.code.size + noffH.initData.size + noffH.uninitData.size + UserStackSize; // we need to increase the size to leave room for the stack numPages = divRoundUp(size, PageSize); size = numPages * PageSize; pageTable = new TranslationEntry[numPages]; for (i = 0; i < numPages; i++) { pageTable[i].virtualPage = i; // for now, virtual page # = phys page # pageTable[i].physicalPage = i; pageTable[i].valid = TRUE; } .... Read the header of binary file Compute address space need Setup a page table for address translation

Initializing a Nachos Address Space Zero out memory allocated bzero(machine->mainMemory, size); // copy in the code and data if (noffH.code.size > 0) { executable->ReadAt(&(machine->mainMemory[noffH.code.virtualAddr]), noffH.code.size, noffH.code.inFileAddr); } if (noffH.initData.size > 0) { executable->ReadAt(&(machine->mainMemory[noffH.initData.virtualAddr]), noffH.initData.size, noffH.initData.inFileAddr); Copy code segment to memory Copy initialized data segment to memory

Compilation of halt.c Test/halt.c: halt.s: assembly code of halt.c #include "syscall.h" main() { Halt(); /* not reached */ } halt.s: assembly code of halt.c gcc -S main: …. jal Halt … Test/start.s … Halt: addiu $2,$0,SC_Halt syscall j $31 .end Halt start.s has system call entries. System call number is always in register 2

Nachos –x halt using halt.c in test directory Machine-> RaiseException(SyscallException) Machine->Run () in mipssim.cc ExceptionHandler(SyscallException) OneInstruction() Interrupt-> Halt() In Interupt.cc 4/22/2017

Code/userprog/exception.cc ExceptionType Machine::Translate(int virtAddr, * physAddr, size, writing) { void ExceptionHandler(ExceptionType which) { int type = machine->ReadRegister(2); if ((which == SyscallException) && (type == SC_Halt)) { DEBUG('a', "Shutdown, initiated by user program.\n"); interrupt->Halt(); } } // Code Convention: // system call code -- r2 // arg1 -- r4, arg2 -- r5, arg3 -- r6, arg4 -- r7

Summary: actions of “nachos –x halt” The main thread starts by running function StartProcess() in file progtest.cc. This thread is used to run halt binary. StartProcess() allocates a new address space and loads the halt binary. It also initializes registers and sets up the page table. Call Machine::Run() to execute the halt binary using the MIPS emulator. The halt binary invokes the system call Halt(), which causes a trap back to the Nachos kernel via functions RaiseException() and ExceptionHandler(). The exception handler determines that a Halt() system call was requested from user mode, and it halts Nachos. 4/22/2017

Assignment 2: Multiprogramming&System Calls Modify source code under userprog subdirectory. ~500-600 lines of code. The crossplatform compiler is under ~cs170/gcc/. This compiler on x86 machines produces a.out with the coff format. Use utility coff2noff (under nachos’ bin directory) to convert it as Noff. Check the makefile under test subdirectory on how to use gcc and coff2noff. System calls to be implemented: Multiprogramming: Fork(), Yield(), Exit(), Exec() and Join(). File and console I/O: Creat(), Open(), Read(), Write(), and Close(). 4/22/2017

Multi-Processes and the Kernel binary Fork or Exec text data BSS user stack text data BSS user stack text data BSS user stack 2n-1 Nachos kernel 2n-1

To run multiple processes Tao Yang 4/22/2017 To run multiple processes Nachos should Provide the physical memory management; Fill memory with proper data, instruction. Set up an address translation table with linear page tables; Save/restore address-space related state during process switching (AddrSpace::SaveUserState() and AddrSpace:RestoreUserState() are called). 4/22/2017

Project 2: Files involved Key files. (Red for modification/extension) progtest.cc -- test routines to run user code. addrspace.h addrspace.cc -- create an address space and load the program from disk. syscall.h -- the system call interface. exception.cc -- the handler for system calls and other user-level exceptions such as page faults. filesys.h, openfile.h console.h -- interface to the Nachos file system and console (connected Linux file system) Extension : pcb.cc, memorymanager.cc processmanager.cc, openfilemanager.cc, useropenfile.cc Other related files: bitmap.h bitmap.cc -- manipulate bitmsps (useful for keeping track of physical page frames). translate.h, translate.cc -- translation tables. machine.h, machine.cc -- emulates main memory, processor, etc. mipsim.cc -- emulates MPIS R2/3000 instructions. console.cc -- emulates a terminal using UNIX files.

Project 2: Makefile flow make -C userprog userprog subdirectory. You expand here Produce nachos which supports processes and system calls make -C bin bin subdirectory. No change is needed Produce programs that read Nachos binary code format used by test program compilation make -C test test subdiretory. Add your test cases here Produce MIPS binary code for test cases. Executed as ../userprog/nachos –x binaryname

Deadline Earlier submission of partial results for 2 bonus points May 3 Pass 1/3 of autograding tests Full submission May 12 (35 points)

Project 2: Implementation Notes Tao Yang

Part I: Multiprogramming void Fork(func) creates a new user-level (child) process, whose address space starts out as an exact copy of that of the caller (the parent), void Yield(): temporarily relinquish the CPU to another process. void Exit( status) call takes a single argument, which is an integer status value as in Unix. The currently executing process is terminated. SpaceID Exec(filename) spawns a new user-level thread (process), but creates a new address space. It should return to the parent a SpaceId. int Join(ID) call waits and returns only after a process with the specified space ID has finished. Return the exit code collected.

Getting Started Review syscall.h (under userprog directory). Review start.cc (under test directory) which includes all system call stubs, following the style of Halt. Modify ExceptionHandler() in exception.cc to include all system call entries. After each system call, increment PC registers so that ExceptionHandler() execution flow returns back to next instruction after user’s system call place. counter = machine->ReadRegister(PCReg); machine->WriteRegister(PrevPCReg,counter); counter = counter + 4; machine->WriteRegister(PCReg,counter); machine->WriteRegister(NextPCReg,counter); Arguments of a system call are in Registers 4, 5, 6 etc. how to verify? You may review MPIS assembly code produced for a test C program using gcc with -S. If needed, return result is register 2 machine->WriteRegister(2,result);

Process Control Block (PCB) Information associated with each process Process state Program counter CPU registers CPU scheduling information Memory-management information Page table Accounting information I/O status information

PCB (Process Control Block) Write the PCB and a process manager. Create a PCB class that will store the necessary information about a process. To start, it should have a PID, parent PID, and kernel ThreadID. pcb.h, pcb.cc The process manager- getPID and clearPID methods, which return an unused process id and clear a process id. Maintain state, exit status, conditional waiting processmanager.h, processmanager.cc.

Diagram of Process State

Memory Manager Write a Memory Manager that will be used to facilitate memory allocation: Track memory page usage. Allocate a page Free a page memorymanager.cc/memorymanager.h Modify AddrSpace:AddrSpace (addrspace.cc) to use the memory manager. Modify the page table constructors to use pages allocated by your memory manager Create a PCB (process control block) also for each process to include key control information.

Management of Free Pages Can use vector of bits to represent availability of each page 00110001110001101 … 110010 1allocated, 0free Before allocation After allocation

AddSpace.cc Write a function (e.g. AddrSpace::Translate), which converts a virtual address to a physical address. It does so by breaking the virtual address into a page table index and an offset. Already in the harness code release Write a function( e.g. AddrSpace::ReadFile), which loads the code and data segments into the translated memory, instead of at position 0. Read data into a system buffer (diskBuffer). Copy buffered data into proper memory locations (e.g. at machine->mainMemory[physAddr].)

Address Translation for Paging Logical address = logical page number + page offset Role of page table: logical page number  physical page number Physical address = physical page number + page offset

How to Run User Processes Concurrently? Forked process Forked process Main program text data BSS user stack binary 2n-1 … Machine->run() … Machine->run() … Machine->run() Nachos Kernel Threads 2n-1 Create a Nachos kernel thread to manage each user process and execute its binary!

Nachos system call Fork() Fork() creates a new process with a duplicated space from parent, but executes a specific function. Not same definition as syscall.h Difference compared to Linux fork()? Func1(){ char *str = “Hello\n"; Write(str, 6, 1); } main(){ char *str = "Greetings from the parent!\n"; Fork(Func1); Write(str, 28, 1); Hello Greetings from the parent!

Compilation of a Fork program #include "syscall.h“ Func1(){} main() { Fork(Func1); } Assembly code gcc -S Func1: … main: ... la $4, Func1 jal Fork jal Fork … Fork: addiu $2,$0,SC_Fork syscall j $31 .end Fork System call number is in register 2. Argument 1 is in register 4 Test/start.s

Questions on Forking a Process When to spawn a new kernel thread? Do we directly use thread fork function to execute the binary of a child? Thread->Fork(Func1, NULL)? Thread->Fork(Machine->Run, NULL)? Who needs to set the program counter for the new process? Parent thread vs child thread? Machine-> RaiseException(SyscallException) Machine->Run () in mipssim.cc ExceptionHandler(SyscallException) OneInstruction() 4/22/2017

User Process and Nachos Kernel Threads text data BSS user stack Forked process Main program text data BSS user stack binary 2n-1 … Machine->run() ForkBridge { … Machine->run() } ForkBridge { … Machine->run() } Thread fork Nachos Kernel Threads 2n-1 Spawn a thread which executes ForkBridge(). ForkBridge() manages each user process.

Implement Fork() in ExceptionHandler() Func1 address is in register 4. Target function to be executed in the new space. Create a new kernel thread. Create a new AddrSpace to be a duplicate of the CurrentThread's space and get a new PCB. The new thread runs a dummy function that creates a bridge for execution of the user function). Call NewThread->Fork(ForkBridge, Func1) The current thread calls Yield() so the new thread can run.

ForkBridge() : Key parts Set counter = Func1 Initialize and restore the registers. For example, currentThread->RestoreUserState(); currentThread->space->RestoreState(); machine->WriteRegister(PCReg, counter); machine->WriteRegister(PrevPCReg,counter-4); machine->WriteRegister(NextPCReg,counter+4); Call machine->Run() which executes the forked user process starting from the desired Func1 address.

Nachos system call Exec() Exec() creates a new process with new code and data segments from a file. Return the new address space ID. Only use the first argument. Difference compared to Linux exec()? main(){ char *str = "Greetings from the parent!\n"; Write(str, 28, 1); Exec("../test/hello“, 0,0,0); } Greetings from the parent!

Implement Exec() main(){ char *str = "Greetings from the parent!\n"; Write(str, 28, 1); Exec("../test/hello“, 0,0,0); } text data BSS user stack new process Main program text data BSS user stack binary 2n-1 … Machine->run() ExecLauncher { … Machine->run() } Thread fork Nachos Kernel Threads 2n-1

Implement Exec() Exec handler creates a new process from a file. Allocate a new address space which fits this file. Load data/code from an OpenFile object constructed from the filename passed in by the user. In order to get that file name you will have to write a function that copies over the string from user space. Allocate a new kernel thread and a PCB to execute with the above space. Fork the new thread to run a dummy bridge function that sets the machine registers straight and runs the code Call NewThread->Fork(execLauncher ,NULL); The calling thread should yield to give control to the newly spawned thread. Return the space ID.

Bridge function for Exec() Called execLanucher() in the released harness code. Initialize registers/restore state. (currentThread->space)->InitRegisters(); (currentThread->space)->RestoreState(); Machine->run();

Nachos system call Yield() Current process gives up CPU and yields to another process Func1(){ char *str = “Hello\n"; Yield(); Write(str, 6, 1); } main(){ char *str = "Greetings from the parent!\n"; Fork(Func1); Write(str, 28, 1); Greetings from the parent! Hello

CPU Switch From Process to Process

Implement Yield(): Context Switch Tao Yang 4/22/2017 Implement Yield(): Context Switch Save the current user process state. AddrSpace:SaveState() Current process state is READY. Conduct the current kernel thread switch with thread yield. When returns, restore the user process restate AddrSpace:RestoreState() Process A Process B Yield() Bridge{ … Machine->run() } … Machine->run() Two context switches involved Process context switch Who saves/restores state? Kernel context switch Thread yield Nachos Kernel Threads

Key operations of Nachos’ function Thread::Yield() nextThread = scheduler->FindNextToRun(); if (nextThread != NULL) { scheduler->ReadyToRun(this); scheduler->Run(nextThread); } Restore current context. Save current context SWITCH() SWITCH () in switch.s 4/22/2017

Nachos threads/scheduler:Run() #ifdef USER_PROGRAM if (currentThread->space != NULL) { currentThread->SaveUserState(); currentThread->space->SaveState(); } #endif SWITCH(oldThread, nextThread); … currentThread->RestoreUserState(); currentThread->space->RestoreState();

Nachos system call int Join(SpaceId id) Wait until the completion of a specific process and return exit code. int main() { int i, c, ret; for( i=0 ; i <1 ; ++i ) { c= Exec( “hello“,0,0,0 ); ret=Join(c); } new process Main program Exit(0) c=Exec() Join(c) … Machine->run() ExecLauncher { … Machine->run() } Thread fork Nachos Kernel Threads 2n-1

Tao Yang 4/22/2017 Implement Join() If the child process already finishes, return its exit status Who maintains such info? Change the current process state as blocked Call ProcessManager for a conditional waiting. When waking up, the current process state should be Running. Return the exit code of child process. ProcessManager/PCB Process A Process B Join() Bridge{ … Machine->run() } … Machine->run() Thread yield Nachos Kernel Threads

Nachos system call Exit (int code) Exit the current process and return the exit code int main() { int i, c, ret; for( i=0 ; i <1 ; ++i ) { c= Exec( “hello“,0,0,0); ret=Join(c); } new process Main program Exit(0) c=Exec() Join(c) … Machine->run() ExecLauncher { … Machine->run() } Thread fork Nachos Kernel Threads 2n-1

Implement Exit() Exit code is in register 4 Tao Yang 4/22/2017 Implement Exit() Exit code is in register 4 Set the exit status of this process in PCB Release resource allocated to this process Close files opened. Change the current process state as Terminated Broadcast everybody that I exit. Clear/release the address space of this process. Clear/release the current kernel thread threadFinish() ProcessManager Process A Process B Join() Exit(0) Bridge{ … Machine->run() } … Machine->run() Thread yield Nachos Kernel Threads

Review of Linux System Calls for Files fileHandle = open(pathName, flags) fileHandle = creat(path,  flags); errorCode = close(fileHandle) byteCount = read(fileHandle, buf, count) byteCount = write(fileHandle, buf, count) position=lseek(fileHandle, offset, flag) Re-position the offset of the current file location for next read/write. Current offset count New offset

What is the output content of tmpfile? Tao Yang 4/22/2017 What is the output content of tmpfile? main() { int pid, fd; char *s1; fd = open("tmpfile", O_WRONLY | O_TRUNC | O_CREAT, 0666); pid = fork(); if (pid > 0) { sleep(1); /* Delay the parent by 1 second */ s1 = "Parent\n"; } else { s1 = "Child\n"; } write(fd, s1, strlen(s1)); close(fd); Create if it does not exist. Remove content if exist tmpfile Child Parent

What is the output content of tmpfile? Tao Yang 4/22/2017 What is the output content of tmpfile? main() { int pid, fd; char *s1; pid = fork(); fd = open("tmpfile", O_WRONLY |O_CREAT, 0666); if (pid > 0) { sleep(1); /* Delay the parent by 1 second */ s1 = "Parentt"; } else { s1 = "Child"; } write(fd, s1, strlen(s1)); close(fd); tmpfile Child Parentt

Nachos system calls for files Tao Yang 4/22/2017 Nachos system calls for files void Create(char *name); OpenFileId Open(char *name); void Write(char *buffer, int size, OpenFileId id); int Read(char *buffer, int size, OpenFileId id); void Close(OpenFileId id); Current offset count New offset

System Calls for File System For the entire system, maintain a set of objects (SysOpenFile class) representing system-wide opened files. Each file may be opened by many user processes. Each file has filename, and offset for the current read/write pointer Do parent/child processes share the same offset pointer? For create/Open/Read/Write, Nachos already has a simple file system implemented Use FILESYS_STUB compiler directive  Directly use Linux interface filesys.cc and openfile.cc under filesys directory

Implement open() 0, 1, 2 file descriptors are reserved for Linux stdin, stdout, stderr. Make sure parent/child processes share files opened before Fork(). Offset is shared. Use fileSystem->Open() (nachos’open) to locate the file object. Add the opened file object to the system-wide fileOpenTable. Keep track files opened for each process. Close them during Exit() as not all of them are closed.

Implement read() Allocate an internal buffer. If Inputfile ID is ConsoleInput Then use getchar() and save data in the internal buffer. Read until EOF or \n. Else, find the current read offset. Use openFile:ReadAt (defined in openfile.h) to read data (essentially use Linux read()) Copy data from the internal buffer to the destination memory location. Need to copy one byte by one byte since the address needs to be translated one by one. How to deal the file offset shared between parent/child processes? How to deal with the file offset not shared?

Implement write() Allocate an internal buffer. Copy data from the source memory location to the internal buffer. Need to copy one by one since the address needs to be translated one by one. If Outputfile ID is ConsoleOutput Then use console output (essentially, printf assuming string type). Else, find the current write offset. Use openFile:WriteAt (defined in openfile.h) to write data to the Linux file. How to deal the file offset shared between parent/child processes? How to deal with the file offset not shared?