Nachos Instructional OS CS 170 Tao Yang Fall

  • Slides: 38
Download presentation
Nachos Instructional OS CS 170, Tao Yang, Fall 2012

Nachos Instructional OS CS 170, Tao Yang, Fall 2012

Why Nachos OS? n Learn by reading and modifying simple operating system code n

Why Nachos OS? n Learn by reading and modifying simple operating system code n n Extremely important OS experience A skeletal OS that supports n kernel threads, user-level processes n MIPS instruction execution as a virtual machine n ~9 K lines of C++ code. 10/6/2020 2

System Layers User process Thread 1 User process Nachos kernel threads Thread 2 Thread

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

Project 1 Tasks 1 -3 main() Thread. Test() Thread 1 Nachos threads Thread 2

Project 1 Tasks 1 -3 main() Thread. Test() Thread 1 Nachos threads Thread 2 Nachos OS modules Simulated MIPS Machine Linux Thread N

Steps to Install Nachos n Obtain and install Nachos source code. n n n

Steps to Install Nachos n Obtain and install Nachos source code. n n n Compile the source code with Makefile Run Nachos demo n n n Copy the source code from ~cs 170/nachos. Sept 20. tar. gz Under the threads subdirectory (run threads) Under the userprog subdirectory (compile/execute binary code) Project 0: Form a group/turn-in proj 0. Due on Oct 10 10/6/2020 5

Nachos code directory n n n n machine --- Basic machine specification (MIPS simulator

Nachos code directory n n n n machine --- Basic machine specification (MIPS simulator as a virtual machine). threads --- threads management (Project 1). userprog -- binary code execution and system calls (Project 2). vm -- virtual memory (empty, Project 3). filesys -- file system (Project 3) test -- binary code to be executed in this virtual machine network -- networking protocol (not used in this class) bin -- utilities/tools (binary format conversion) 10/6/2020 6

Source code reading and Project 1 Objectives of next 2 weeks n Scan through

Source code reading and Project 1 Objectives of next 2 weeks n Scan through ~1, 000 -2, 000 lines of code under threads directory n n n Learn how context switch is accomplished among threads. Learn how thread scheduling is done. Learn how locks/synchronization are implemented and used. Use Linux pthreads. Complete Project 1 10/6/2020 7

Sample Example of Nacho Threads int shared=1; main () { Thread *t 1 =

Sample Example of Nacho Threads int shared=1; main () { Thread *t 1 = new Thread("forked thread 1"); Thread *t 2 = new Thread("forked thread 2"); t 1 ->Fork(Simple. Thread, 1); t 2 ->Fork(Simple. Thread, 2); Create 2 new threads. Start to fork and execute a function in each child thread. Parent also executes the same function Simple. Thread(3); } Simple. Thread(int i) { printf(“Hello %d. Shared %dn”, i, shared); current. Thread->Yield(); } Function executed by threads

Nachos Threads n n Each thread has the following TCB (thread control block) from

Nachos Threads n n Each thread has the following TCB (thread control block) from thread. h int *stack. Top; // stack pointer int machine. State[18]; // copy of registers int *stack // bottom of stack Thread. Status status; //ready, running, or blocked char *name; Thread operations: n Thread(char *debug. Name). Create a thread. n Fork(Void. Function. Ptr func, int arg). Let a thread execute a function. n Yield(). Suspend the calling thread and select a new one for execution. n Sleep(). Suspend the current thread, change its state to BLOCKED, and remove it from the ready list n Finish() 10/6/2020 9

Nachos Thread States and Transitions Thread: : Yield running (kernel) Thread: : Sleep blocked

Nachos Thread States and Transitions Thread: : Yield running (kernel) Thread: : Sleep blocked Scheduler: : Run Scheduler: : Ready. To. Run ready

Semaphore object for thread synchronization n n Disable and re-enable interrupts to achieve mutual

Semaphore object for thread synchronization n n Disable and re-enable interrupts to achieve mutual exclusion (e. g. , by calling Interrupt: : Set. Level()). Operations for a Semaphore object: n Semaphore(char* debug. Name, int initial. Value) n P(): Decrement the semaphore's count, blocking the caller if the count is zero. n V() : Increment the semaphore's count, releasing one thread if any are blocked waiting on the count. 10/6/2020 11

Semaphore Implementation n n Atomic critical section n P(S) { while ( S <=

Semaphore Implementation n n Atomic critical section n P(S) { while ( S <= 0) ; // wait S--; } n V(S) { S++; } Issue in busy waiting n Waste time n Applications may spend lots of time in such a critical section

Semaphore Implementation with no busy waiting Each semaphore has a waiting queue. n n

Semaphore Implementation with no busy waiting Each semaphore has a waiting queue. n n Two internal operations: n Sleep– place thread invoking the operation on the waiting queue. n Nachos: Thread: Sleep() n wakeup – remove one thread in the waiting queue and place it in the ready queue.

Semaphore Implementation with no Busy waiting (Cont. ) n P(semaphore *S) { S->value--; if

Semaphore Implementation with no Busy waiting (Cont. ) n P(semaphore *S) { S->value--; if (S->value < 0) { add this thread to waiting-queue; sleep(); }} n V(semaphore *S) { S->value++; if (S->value <= 0) { Remove x from waiting-queue; wakeup(x); }}

Reading source code n n Have a picture of overall components and their roles.

Reading source code n n Have a picture of overall components and their roles. Be able to compile and run a simple case. n n Follow Project 0 and execute two cases. Trace the code execution through a simple case n Basic/high level mechanism involved in execution. n Walk through a simple thread test case in Nachos. Week 2 link in http: //www. cs. ucsb. edu/~cs 170/refer. html 10/6/2020 15

Project 1 Tasks 1 -3 main() Thread. Test() Thread 1 Nachos threads Thread 2

Project 1 Tasks 1 -3 main() Thread. Test() Thread 1 Nachos threads Thread 2 Nachos OS modules Simulated MIPS Machine Linux Thread N

Key steps when Nachos executes After you type ``nachos'' under threads subdirectory: n It

Key steps when Nachos executes After you type ``nachos'' under threads subdirectory: n It is executing as a single Unix process. n The main() calls n Initialize() to start up interrupt handling, create a scheduler for managing the ready queue. n Thread. Test() n current. Thread->Finish() to let other threads continue to run. 10/6/2020 17

Key Calling graph when Nachos executes under thread directory All files are in threads

Key Calling graph when Nachos executes under thread directory All files are in threads directory. Thread: Fork () in thread. cc Initialize() in system. cc main() in main. cc Thread: Yield () in thread. cc Thread. Test () in threadtest. cc current. Thread->Finish () in threadtest. cc 10/6/2020 Stack. Allocate() in thread. cc Find. Next. To. Run () in scheduler. cc SWITCH () in switch. s Ready. To. Run () in scheduler. cc Thread. Root () in switch. s Run () in scheduler. cc func() such as Simple. Thread() in Thread. Test. cc 18

Key Calling graph for Project 1 Task 1 All files are in threads directory.

Key Calling graph for Project 1 Task 1 All files are in threads directory. Initialize() in system. cc main() in main. cc Spawn multiple threads. Each executes a sample loop. Finally print shared variable at the end Thread: Fork () in thread. cc Thread: Yield () in thread. cc Thread. Test () in threadtest. cc current. Thread->Finish () in threadtest. cc 10/6/2020 Semaphore P()/V() in synch. cc 19

Key Calling graph for Project 1 Task 3 All files are in threads directory.

Key Calling graph for Project 1 Task 3 All files are in threads directory. Initialize() in system. cc main() in main. cc Spawn multiple threads as test stations Thread: Fork () in thread. cc Each executes allocate() and release() operations Thread. Test () in threadtest. cc current. Thread->Finish () in threadtest. cc 10/6/2020 Lock/conditions in synch. cc 20

Scheduler object for thread scheduling n n n Decide which thread to run next

Scheduler object for thread scheduling n n n Decide which thread to run next n Invoked when the current thread gives up CPU. The current Nachos scheduling policy is round-robin: n Select the front of ready list. n Append new threads to the end. Key operations: n Ready. To. Run(Thread *thread). Make thready to run and add to ready list. n Thread *Find. Next. To. Run() n Run(Thread *next. Thread) 10/6/2020 21

Thread Switching n n Suspend current thread, save its state, and restore the state

Thread Switching n n Suspend current thread, save its state, and restore the state of new thread. Switch(old. Thread, new. Thread): n Save all registers in old. Thread's TCB. n n to be used when the old thread is resumed. Load new values into the registers from TCB of the new thread. 10/6/2020 22

Single-threaded vs multithreaded Process 10/6/2020 23

Single-threaded vs multithreaded Process 10/6/2020 23

Key operations of SWITCH() Thread->Fork(func(), arg) Save current thread context SWITCH () in switch.

Key operations of SWITCH() Thread->Fork(func(), arg) Save current thread context SWITCH () in switch. s func(arg) Load target thread context Call Thread. Root () in switch. s 10/6/2020 Call Interrupt. Enable() Call func(arg) Call Thread. Finish() 24

SWITCH(old. Thread, next. Thread) Save register values to current thread’s TCB n # a

SWITCH(old. Thread, next. Thread) Save register values to current thread’s TCB n # a 0 -- pointer to old thread’s TCB sw sw sw sp, SP(a 0) # save new stack pointer s 0, S 0(a 0) s 1, S 1(a 0) s 2, S 2(a 0) s 3, S 3(a 0) s 4, S 4(a 0) s 5, S 5(a 0) s 6, S 6(a 0) s 7, S 7(a 0) fp, FP(a 0) ra, PC(a 0) # save return address a 1 -- pointer to new thread’s. TCB a 0 TCB Registers sp s 0 s 1 s 2 save stack. Top machine. State[0] machine. State[1] machine. State[2] … … 10/6/2020 25

Load register values from new thread’s TCB n lw lw … lw lw lw

Load register values from new thread’s TCB n lw lw … lw lw lw # a 0 -- pointer to old thread’s TCB sp, s 0, s 1, s 2, a 1 -- pointer to new thread’s. TCB SP(a 1) # load the new stack pointer S 0(a 1) S 1(a 1) S 2(a 1) s 7, S 7(a 1) fp, FP(a 1) ra, PC(a 1) # load the return address j ra #Call ra which is Thread. Root(); a 1 sp s 0 s 1 s 2 s 3 stack. Top machine. State[0] machine. State[1] machine. State[2] machine. State[3] … machine. State[9] ra 10/6/2020 26

How TCB is initialized? n # a 0 -- pointer to old thread’s TCB

How TCB is initialized? n # a 0 -- pointer to old thread’s TCB a 1 -- pointer to new thread’s. TCB n a 1 lw lw … lw lw lw sp, s 0, s 1, s 2, SP(a 1) # load the new stack pointer S 0(a 1) S 1(a 1) sp S 2(a 1) s 0 s 7, S 7(a 1) fp, FP(a 1) ra, PC(a 1) # load the return address j ra #Call ra which is Thread. Root(); 10/6/2020 s 1 s 2 s 3 stack. Top func() arg Thread. Finish() Interrupt. Enable() … Thread. Root() addr ra 27

Which routine fills values of the new thread TCB? n Stack. Allocate() in Thread:

Which routine fills values of the new thread TCB? n Stack. Allocate() in Thread: : Fork() machine. State[PCState] = (int) Thread. Root; // PCState=9 machine. State[Startup. PCState] = (int) Interrupt. Enable; //Startup. PCState=3 =>s 3 machine. State[Initial. PCState] = (int) func; //Initial. PCState=0 =>s 0 machine. State[Initial. Arg. State] = arg; //Initial. Arg. State=1 =>s 1 machine. State[When. Done. PCState] = (int) Thread. Finish; //When. Done. PCState=2 =>s 2 n bb 10/6/2020 28

Thread. Root() uses registers s 0, s 1, s 2, s 3 to execute

Thread. Root() uses registers s 0, s 1, s 2, s 3 to execute targeted func() jal Startup. PC move a 0, Initial. Arg jal Initial. PC jal # call #move argument in s 1 to a 0 # call main thread procedure func() stored in s 0 When. Done. PC 10/6/2020 Interrupt. Enable() stored in register s 3 # when done, call Thread. Finish() in s 2 29

Project 1 Objectives n Tasks 1 -3 under threads subdirectory. n n Gain experience

Project 1 Objectives n Tasks 1 -3 under threads subdirectory. n n Gain experience with simple thread programming (execute multiple Nachos threads with synchronization). Implement locks and condition variables (missing from the file synch. cc). Use for laundromat application Task 4 under hw 1_task 1_pthreads subdirectory n Show that Pthreads code works similarly 10/6/2020 30

Tasks 1/2/3: Nachos Files involved Key files to read and modify (modify 3 files

Tasks 1/2/3: Nachos Files involved Key files to read and modify (modify 3 files in red) n n n main. cc, threadtest. cc -- a simple test of our thread routines. thread. h thread. cc -- Nachos thread data structure and operations. scheduler. h scheduler. cc -- The thready list. synch. h synch. cc -- synchronization routines. system. h, system. cc -- Nachos startup initialization /shutdown switch. h, switch. s -- assembly code for thread switching. Other related files: n n n synchlist. h, synchlist. cc -- synchronized access to lists using locks/conditions (useful examples for your programming). list. h list. cc -- generic list management. utility. h utility. cc -- some useful definitions and debugging routines. interrupt. h interrupt. cc -- manage interrupts. time. h timer. cc -- clock emulation. stats. h stats. cc -- collect interesting statistics. 10/6/2020 31

Sample/Makefile, and test script [cs 170@csil PROJECT 1]$ more testscript make clean; make threads/nachos

Sample/Makefile, and test script [cs 170@csil PROJECT 1]$ more testscript make clean; make threads/nachos > Task 1 -1_trace make clean; make "DEFINES = -DTHREADS -DHW 1_SEMAPHORES" threads/nachos > Task 1 -2_trace make clean; make "DEFINES = -DTHREADS -DHW 1_LAUNDRY_LC" threads/nachos > Task 3_trace cd hw 1_task 1_pthreads make; make run >Task 4_trace 10/6/2020 32

Sample Code for Tasks 1/2/3 ~cs 170/sample/PRJECT 1/ n Has an incomplete sample solution

Sample Code for Tasks 1/2/3 ~cs 170/sample/PRJECT 1/ n Has an incomplete sample solution for Project 1 n <~50 lines of sample code are removed. n Removed positions are marked n Caveat: n Not well documented, not fully tested. Possibly awkward style/design n Still your responsibility to produce good solutions (correctness, performance, style) with at least 50% difference 10/6/2020 33

Task 1 (1): Use Nachos threads and explain behavior int Shared. Variable; void Simple.

Task 1 (1): Use Nachos threads and explain behavior int Shared. Variable; void Simple. Thread(int which) { int num, val; for(num = 0; num < 5; num++) { val = Shared. Variable; printf("*** thread %d sees value %dn", which, val); current. Thread->Yield(); Shared. Variable = val+1; current. Thread->Yield(); } val = Shared. Variable; printf("Thread %d sees final value %dn", which, val); } n 10/6/2020 34

Task 1 (2): Use Nachos semaphores to synchronize int Shared. Variable; void Simple. Thread(int

Task 1 (2): Use Nachos semaphores to synchronize int Shared. Variable; void Simple. Thread(int which) { int num, val; for(num = 0; num < 5; num++) { val = Shared. Variable; printf("*** thread %d sees value %dn", which, val); Critical section needs a mutual execution current. Thread->Yield(); Shared. Variable = val+1; Need a barrier so every thread sees the current. Thread->Yield(); same value of “Shared. Variable” } val = Shared. Variable; printf("Thread %d sees final value %dn", which, val); } n 10/6/2020 35

Task 2: Lock/condition variable implementation Implement Lock code in synch. cc similar as Nachos

Task 2: Lock/condition variable implementation Implement Lock code in synch. cc similar as Nachos semaphore code n Sample solution is available n Implement conditional variables n A few lines were removed from the sample code. n 10/6/2020 36

Task 4: Use Pthreads instead Nachos for Task 1 (2) Use pthread_create() to execute

Task 4: Use Pthreads instead Nachos for Task 1 (2) Use pthread_create() to execute int Shared. Variable; void Simple. Thread(int which) { int num, val; for(num = 0; num < 5; num++) { val = Shared. Variable; Use pthread_yield() printf("*** thread %d sees value %dn", which, val); Use pthread_mutex_lock/unlock(), current. Thread->Yield(); Shared. Variable = val+1; current. Thread->Yield(); Barrier using pthread_mutex_lock()/unlock() } pthread_cond_wait(), /cond_broadcast() val = Shared. Variable; printf("Thread %d sees final value %dn", which, val); } n 10/6/2020 37

Implementation Strategy for Project 1 n n n Read key Nachos files listed in

Implementation Strategy for Project 1 n n n Read key Nachos files listed in the previous slide. Find difference between sample solution with the existing code: main. cc, threadtest. cc, synch. cc. Find what is removed (search “removed”) Implement Task 1 using semaphore Implement Task 2 using code similar to semaphore implementation in synch. cc (check how sample solution implements lock). Implement Task 3 using lock/conditions with 2 stations (sample solution). Then test with 3 stations. For Task 4, study related Pthread functions, model Task 1 using Pthreads, and synchronize with its lock/condition variables 10/6/2020 38