38
Nachos Instructional OS CS 170, Tao Yang, Fall 2012

Nachos Instructional OS

  • Upload
    xander

  • View
    71

  • Download
    0

Embed Size (px)

DESCRIPTION

Nachos Instructional OS. CS 170, Tao Yang, Fall 2012. Why Nachos OS?. Learn by reading and modifying simple operating system code Extremely important OS experience A skeletal OS that supports kernel threads, user-level processes MIPS instruction execution as a virtual machine - PowerPoint PPT Presentation

Citation preview

Page 1: Nachos Instructional OS

Nachos Instructional OS

CS 170, Tao Yang, Fall 2012

Page 2: Nachos Instructional OS

04/24/23 2

Why Nachos OS? Learn by reading and modifying simple

operating system code Extremely important OS experience

A skeletal OS that supports kernel threads, user-level processes MIPS instruction execution as a

virtual machine ~9K lines of C++ code.

Page 3: Nachos Instructional OS

System Layers

Base Operating System (Linux for our class)

Nachos kernel threadsThread 1 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)

User processUser process

Page 4: Nachos Instructional OS

Project 1 Tasks 1-3

Linux

Nachos threadsThread 1 Thread 2 Thread N

Nachos OS modules

Simulated MIPS Machine

main()

ThreadTest()

Page 5: Nachos Instructional OS

04/24/23 5

Steps to Install Nachos Obtain and install Nachos source code.

Copy the source code from ~cs170/nachosSept20.tar.gz

Compile the source code with Makefile Run Nachos demo

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

Page 6: Nachos Instructional OS

04/24/23 6

Nachos code directory 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)

Page 7: Nachos Instructional OS

04/24/23 7

Source code reading and Project 1

Objectives of next 2 weeks Scan through ~1,000-2,000 lines of code

under threads directory 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

Page 8: Nachos Instructional OS

int shared=1;main (){ Thread *t1 = new Thread("forked thread1"); Thread *t2 = new Thread("forked thread2");

t1->Fork(SimpleThread, 1); t2->Fork(SimpleThread, 2);

SimpleThread(3);}

SimpleThread(int i){ printf(“Hello %d. Shared %d\n”, i, shared); currentThread->Yield();}

Sample Example of Nacho Threads

Start to fork and execute a function in each child thread.Parent also

executes the same function

Function executed by threads

Create 2 new threads.

Page 9: Nachos Instructional OS

04/24/23 9

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

thread.hint *stackTop; // stack pointerint machineState[18]; // copy of registersint *stack // bottom of stackThreadStatus status; //ready, running, or blockedchar *name;

Thread operations: Thread(char *debugName). Create a thread. Fork(VoidFunctionPtr func, int arg). Let a thread execute a

function. Yield(). Suspend the calling thread and select a new one for

execution. Sleep(). Suspend the current thread, change its state to

BLOCKED, and remove it from the ready list Finish()

Page 10: Nachos Instructional OS

Nachos Thread States and Transitions

running(kernel)

readyblocked

Scheduler::Run

Scheduler::ReadyToRun

Thread::Sleep

Thread::Yield

Page 11: Nachos Instructional OS

04/24/23 11

Semaphore object for thread synchronization

Disable and re-enable interrupts to achieve mutual exclusion (e.g., by calling Interrupt::SetLevel()).

Operations for a Semaphore object: Semaphore(char* debugName, int initialValue) P(): Decrement the semaphore's count, blocking

the caller if the count is zero. V() :Increment the semaphore's count, releasing

one thread if any are blocked waiting on the count.

Page 12: Nachos Instructional OS

Semaphore Implementation Atomic critical section

P(S) { while ( S <= 0) ; // wait S--; } V(S) { S++; }

Issue in busy waiting Waste time Applications may spend lots of time in such a critical

section

Page 13: Nachos Instructional OS

Semaphore Implementation with no busy waiting

Each semaphore has a waiting queue.

Two internal operations: Sleep– place the thread invoking the

operation on the waiting queue. Nachos: Thread:Sleep()

wakeup – remove one thread in the waiting queue and place it in the ready queue.

Page 14: Nachos Instructional OS

Semaphore Implementation with no Busy waiting (Cont.) P(semaphore *S) {

S->value--; if (S->value < 0) { add this thread to waiting-queue; sleep();} }

V(semaphore *S) { S->value++; if (S->value <= 0) {

Remove x from waiting-queue;

wakeup(x); }}

Page 15: Nachos Instructional OS

04/24/23 15

Reading source code Have a picture of overall components and their

roles. Be able to compile and run a simple case.

Follow Project 0 and execute two cases. Trace the code execution through a simple case

Basic/high level mechanism involved in execution.

Walk through a simple thread test case in Nachos.

Week 2 link in http://www.cs.ucsb.edu/~cs170/refer.html

Page 16: Nachos Instructional OS

Project 1 Tasks 1-3

Linux

Nachos threadsThread 1 Thread 2 Thread N

Nachos OS modules

Simulated MIPS Machine

main()

ThreadTest()

Page 17: Nachos Instructional OS

04/24/23 17

Key steps when Nachos executes

After you type ``nachos'' under threads subdirectory:

It is executing as a single Unix process. The main() calls

Initialize() to start up interrupt handling, create a scheduler for managing the ready queue.

ThreadTest() currentThread->Finish() to let other threads

continue to run.

Page 18: Nachos Instructional OS

04/24/23 18

Key Calling graph when Nachos executes under thread directory

All files are in threads directory.

main() inmain.cc

Initialize()in system.cc

ThreadTest ()in threadtest.cc

Thread:Yield ()in thread.cc

Thread:Fork ()in thread.cc

StackAllocate()in thread.cc

FindNextToRun ()in scheduler.cc

ReadyToRun ()in scheduler.cc

Run ()in scheduler.cc

SWITCH ()in switch.s

ThreadRoot ()in switch.s

func() such as SimpleThread()in ThreadTest.cc

currentThread->Finish ()in threadtest.cc

Page 19: Nachos Instructional OS

04/24/23 19

Key Calling graph for Project 1 Task 1All files are in

threads directory.

main() inmain.cc

Initialize()in system.cc

ThreadTest ()in threadtest.cc

Thread:Yield ()in thread.cc

Thread:Fork ()in thread.cc

currentThread->Finish ()in threadtest.cc

Spawn multiple threads.Each executesa sample loop.

Finally print sharedvariable at the end

Semaphore P()/V()in synch.cc

Page 20: Nachos Instructional OS

04/24/23 20

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

threads directory.

main() inmain.cc

Initialize()in system.cc

ThreadTest ()in threadtest.cc

Thread:Fork ()in thread.cc

currentThread->Finish ()in threadtest.cc

Spawn multiple threads as test stations

Each executes allocate()and release() operations

Lock/conditionsin synch.cc

Page 21: Nachos Instructional OS

04/24/23 21

Scheduler object for thread scheduling

Decide which thread to run next Invoked when the current thread gives up CPU.

The current Nachos scheduling policy is round-robin: Select the front of ready list. Append new threads to the end.

Key operations: ReadyToRun(Thread *thread).

Make thread ready to run and add to ready list. Thread *FindNextToRun() Run(Thread *nextThread)

Page 22: Nachos Instructional OS

04/24/23 22

Thread Switching Suspend current thread, save its state,

and restore the state of new thread. Switch(oldThread, newThread):

Save all registers in oldThread's TCB. to be used when the old thread is

resumed. Load new values into the registers

from TCB of the new thread.

Page 23: Nachos Instructional OS

04/24/23 23

Single-threaded vs multithreaded Process

Page 24: Nachos Instructional OS

04/24/23 24

Key operations of SWITCH()

SWITCH ()in switch.s

Thread->Fork(func(), arg)

func(arg)

Call ThreadRoot ()in switch.s

Save current thread context

Load targetthread context

CallThreadFinish()

Call InterruptEnable()

Callfunc(arg)

Page 25: Nachos Instructional OS

04/24/23 25

SWITCH(oldThread, nextThread)Save register values to current thread’s TCB

# a0 -- pointer to old thread’s TCB a1 -- pointer to new thread’sTCB

sw sp, SP(a0) # save new stack pointer sw s0, S0(a0) sw s1, S1(a0) sw s2, S2(a0) sw s3, S3(a0) sw s4, S4(a0) sw s5, S5(a0) sw s6, S6(a0) sw s7, S7(a0) sw fp, FP(a0)sw ra, PC(a0) # save return address

sp

s0

s1

s2

stackTopmachineState[0]machineState[1]machineState[2]…

a0

TCBsave

savesave

save

Registers

Page 26: Nachos Instructional OS

04/24/23 26

Load register values from new thread’s TCB

# a0 -- pointer to old thread’s TCB a1 -- pointer to new thread’sTCB

lw sp, SP(a1) # load the new stack pointer lw s0, S0(a1) lw s1, S1(a1) lw s2, S2(a1) …lw s7, S7(a1) lw fp, FP(a1) lw ra, PC(a1) # load the return address

j ra #Call ra which is ThreadRoot();

sp

s0

s1

s2

s3

stackTopmachineState[0]machineState[1]machineState[2]machineState[3]…

machineState[9]

ra

a1

Page 27: Nachos Instructional OS

04/24/23 27

How TCB is initialized? # a0 -- pointer to old thread’s TCB a1 -- pointer to new thread’sTCB

lw sp, SP(a1) # load the new stack pointer lw s0, S0(a1) lw s1, S1(a1) lw s2, S2(a1) …lw s7, S7(a1) lw fp, FP(a1) lw ra, PC(a1) # load the return address

j ra #Call ra which is ThreadRoot();

sp

s0

s1

s2

s3

stackTopfunc() argThreadFinish()InterruptEnable()…

ThreadRoot() addr

ra

a1

Page 28: Nachos Instructional OS

04/24/23 28

Which routine fills values of the new thread TCB?StackAllocate() in Thread::Fork()

machineState[PCState] = (int) ThreadRoot; // PCState=9machineState[StartupPCState] = (int) InterruptEnable;

//StartupPCState=3 =>s3machineState[InitialPCState] = (int) func; //InitialPCState=0 =>s0machineState[InitialArgState] = arg; //InitialArgState=1 =>s1machineState[WhenDonePCState] = (int) ThreadFinish;

//WhenDonePCState=2 =>s2

bb

Page 29: Nachos Instructional OS

04/24/23 29

ThreadRoot() uses registers s0, s1,s2,s3 to execute targeted func()

jal StartupPC # call InterruptEnable() stored in register s3

move a0, InitialArg #move argument in s1 to a0

jal InitialPC # call main thread procedure func() stored in s0

jal WhenDonePC # when done, call ThreadFinish() in s2

Page 30: Nachos Instructional OS

04/24/23 30

Project 1 Objectives Tasks 1-3 under threads subdirectory.

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 hw1_task1_pthreads

subdirectory Show that Pthreads code works similarly

Page 31: Nachos Instructional OS

04/24/23 31

Tasks 1/2/3: Nachos Files involved

Key files to read and modify (modify 3 files in red) 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 thread ready 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: 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.

Page 32: Nachos Instructional OS

04/24/23 32

Sample/Makefile, and test script [cs170@csil PROJECT1]$ more testscriptmake clean; makethreads/nachos > Task1-1_trace

make clean; make "DEFINES = -DTHREADS -DHW1_SEMAPHORES"threads/nachos > Task1-2_trace

make clean; make "DEFINES = -DTHREADS -DHW1_LAUNDRY_LC"threads/nachos > Task3_trace

cd hw1_task1_pthreadsmake; make run >Task4_trace

Page 33: Nachos Instructional OS

04/24/23 33

Sample Code for Tasks 1/2/3~cs170/sample/PRJECT1/ Has an incomplete sample solution for Project 1

<~50 lines of sample code are removed. Removed positions are marked

Caveat: Not well documented, not fully tested.

Possibly awkward style/design Still your responsibility to produce good

solutions (correctness, performance, style) with at least 50% difference

Page 34: Nachos Instructional OS

04/24/23 34

Task 1 (1): Use Nachos threads and explain behavior

int SharedVariable; void SimpleThread(int which) { int num, val; for(num = 0; num < 5; num++) { val = SharedVariable; printf("*** thread %d sees value %d\n", which, val); currentThread->Yield(); SharedVariable = val+1; currentThread->Yield(); } val = SharedVariable; printf("Thread %d sees final value %d\n", which, val); }

Page 35: Nachos Instructional OS

04/24/23 35

Task 1 (2): Use Nachos semaphores to synchronize

int SharedVariable; void SimpleThread(int which) { int num, val; for(num = 0; num < 5; num++) { val = SharedVariable; printf("*** thread %d sees value %d\n", which, val); currentThread->Yield(); SharedVariable = val+1; currentThread->Yield(); } val = SharedVariable; printf("Thread %d sees final value %d\n", which, val); }

Critical section needs a mutual execution

Need a barrier so every thread sees the same value of “SharedVariable”

Page 36: Nachos Instructional OS

04/24/23 36

Task 2: Lock/condition variable implementation

Implement Lock code in synch.cc similar as Nachos semaphore code Sample solution is available

Implement conditional variables A few lines were removed from the sample code.

Page 37: Nachos Instructional OS

04/24/23 37

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

int SharedVariable; void SimpleThread(int which) { int num, val; for(num = 0; num < 5; num++) { val = SharedVariable; printf("*** thread %d sees value %d\n", which, val); currentThread->Yield(); SharedVariable = val+1; currentThread->Yield(); } val = SharedVariable; printf("Thread %d sees final value %d\n", which, val); }

Use pthread_create() to execute

Use pthread_yield()Use pthread_mutex_lock/unlock(),

Barrier using pthread_mutex_lock()/unlock() pthread_cond_wait(),/cond_broadcast()

Page 38: Nachos Instructional OS

04/24/23 38

Implementation Strategy for Project 1

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