TDDI12: Operating Systems, Real-time and Concurrent programming Agenda • • • Laboratory Lesson I Introduction to NACHOS Laboratory Assignment 1/3 Requirements for Laboratory Work Introduction to NACHOS Assignment I Andrzej Bednarski, IDA Linköpings universitet, 2006 Overview • • • • • 1.3 Laboratory Work Overview (1/3) • • Provided + Part of a working thread system and an implementation of semaphores To do: + Implement locks and condition variables ̶ Test your implementation (implement synchronized bounded buffer) TDDI12, A. Bednarski, IDA, Linköpings universitet 1.2 Features NACHOS: “Not Another Completely Heuristic Operating System” Free operating system and simulation environment to study an operating system Runs as a single Unix process (real operating systems run on bare machines) Simulates low-level facilities (including interrupts, virtual memory and interrupt-driven device I/O) Implemented in subset of C++, ca. 2.500 lines of code TDDI12, A. Bednarski, IDA, Linköpings universitet TDDI12, A. Bednarski, IDA, Linköpings universitet 1.5 • • • NACHOS simulates a MIPS machine NACHOS approximates a real machines architecture + Registers + Memory + CPU + Event-driven simulated clock (=> schedule interrupts) Can execute arbitrary C programs TDDI12, A. Bednarski, IDA, Linköpings universitet 1.4 Preparation • Read and understand the partial thread system (…/nachos-3.4/code/threads) • Run the test program in the debugger and follow the state of each thread object TDDI12, A. Bednarski, IDA, Linköpings universitet 1.6 1 (NACHOS) Threads • • (NACHOS) Threads Thread Object methods: + Thread + Fork + StackAllocate + Yield + Sleep + Finish Read documentation / source code TDDI12, A. Bednarski, IDA, Linköpings universitet 1.7 Semaphore • • NACHOS Threads’ status: + READY + RUNNING + BLOCKED + JUST_CREATED (temporary state) • The scheduler decides which thread to run next • Synchronization facilities provided through semaphores TDDI12, A. Bednarski, IDA, Linköpings universitet P() or Wait() A semaphore is an integer variable, accessible only by the operations Wait and Signal (Originally called P and V) • Signal(S): S := S + 1; 1.9 V() or Signal() • TDDI12, A. Bednarski, IDA, Linköpings universitet 1.10 Overview Increment the semaphore’s count, release one thread if any are blocked waiting on the count void Semaphore::V() { Thread *thread; IntStatus oldLevel = interrupt->SetLevel(IntOff); thread = (Thread *)queue->remove(); if (thread != NULL) scheduler->ReadyToRun(thread); value = value + 1; (void) interrupt->SetLevel(oldLevel); } TDDI12, A. Bednarski, IDA, Linköpings universitet Decrement the semaphore’s count, block the caller if count is less than zero or zero void Semaphore::P() { IntStatus oldLevel = interrupt->SetLevel(IntOff); while(value <= 0) { queue->Append((void *)currentThread); currentThread->Sleep(); } value = value - 1; (void) interrupt->SetLevel(oldLevel); } Wait(S): while S <= 0 do no-op; S := S -1; TDDI12, A. Bednarski, IDA, Linköpings universitet 1.8 1.11 • Implement locks and conditions - when used together provides the same functionality as monitors • Write code for the Lock and Condition classes (in the file .../code/threads/sync.cc) + Interfaces (class definition) for Lock and Condition are already defined (in .../code/threads/sync.h) + No changes to the interfaces should be done. Only needed variables should be added to the classes + NB: It should not take too much code for you to implement all functionality TDDI12, A. Bednarski, IDA, Linköpings universitet 1.12 2 Lock • Condition Variables Binary semaphore (with constraints) • class Lock { public: Lock(char* debugName); ~Lock(); void Acquire(); // atomic void Release(); // atomic bool isHeldbyCurrentThread(); private: char *name; // some variables you need }; P1 • TDDI12, A. Bednarski, IDA, Linköpings universitet 1.13 Condition Variable (Wait) • • • • Release the Lock Add the thread to waiting thread on this condition Release the CPU (sleep) Acquire the Lock (after wake-up) TDDI12, A. Bednarski, IDA, Linköpings universitet 1.15 Test Your Implementation • • • Write a class BoundedBuffer and use it for Producer / Consumer communication (see [SGG 7, Sec. 6.6]) Check border conditions Try with several Producers / Consumers (see course homepage) 1.17 P2 P3 Lock1->Acquire() Lock3->Acquire() Lock2->Acquire() Lock2->Acquire() Lock1->Acquire() Lock3->Acquire() … … … Lock2->Release() Lock1->Release() Lock3->Release() Lock1->Release() Lock3->Release() Lock2->Release() While hold a lock if cannot use it? TDDI12, A. Bednarski, IDA, Linköpings universitet 1.14 Condition Variable (Signal) • • Take one thread from the queue Run it (scheduler->ReadyToRun(thread)) TDDI12, A. Bednarski, IDA, Linköpings universitet 1.16 Laboratory Sessions • Mark your changes in the source code // // // // // • • TDDI12, A. Bednarski, IDA, Linköpings universitet Semaphores and Locks are inefficient when dealing with multiple resources -------------------------------------------------02-04-24: your name: changes ... end of changes -------------------------------------------------- Show working solutions Turn in hard copy of your changed code + testprogram + documentation TDDI12, A. Bednarski, IDA, Linköpings universitet 1.18 3 Laboratory Sessions (cont’) • Documentation + A readme file which contain: ̶ The files you have created and a short description ̶ The major changes you have made to the given files + Testcase file(s) ̶ Which test cases did you use ̶ What was the output of the test cases ̶ What those testcases should demonstrate TDDI12, A. Bednarski, IDA, Linköpings universitet 1.19 4