Sie sind auf Seite 1von 46

CS‐205

Operating Systems Project
Development of NachOS
Project Phases
Project Phases
• Project is comprises of 3 Phases
Project is comprises of 3 Phases
– Phase 1 – Process Management ( Due on Oct 20)

– Phase 2 – Process Coordination ( Due on Nov 8)

– Phase 3 – Multiprogramming ( Due On Nov 26)
NachOS Installation Guide
Installation Guide
• You
You can directly download NachOS
can directly download NachOS on your 
on your
machine from anywhere you like or you can 
use the following link
use the following link
• http://mll.csie.ntu.edu.tw/course/os_f08/217.
htm
• NachOS official Web site
• http://www.cs.washington.edu/homes/tom/n
achos/
Phase 1
Phase 1

Process Management Module
Tasks
• Implement Thread Scheduling
Implement Thread Scheduling
– Default is FCFS
– Priority scheduling + Round Robin
Priority scheduling + Round Robin
NACHOS Threads
NACHOS Threads
• Ready queue
– A List object: a list of ready thread objects
b l f d h d b
• Thread state
– READY
• The thread will be kept in readyList.
The thread will be kept in readyList.
– RUNNING
• The global variable currentThread always points the currently running thread.
– BLOCKED
• The thread is blocked to wait for some event until the event takes place.
The thread is blocked to wait for some event until the event takes place
• A blocked thread is not in readyList. Instead, it would be put in other queues.
– JUST_CREATED
• The thread is just created, but not ready to be put in readyList (not ready to run).
Thread Life Cycle
Thread Life Cycle
Note:
N
Thread::Yield() invoks 
JUST_CREATED Scheduler::FindNextToRun() to 
select next thread to run.

Thread::Fork()
Call Scheduler::
ReadyToRun() EEvent occurs, call 
t ll
Scheduler::ReadyToRun()
READY (Move thread back to the ready queue)
(use a readyList)
(use a readyList)

Call Thread::Yield() BLOCKED

RUNNING Call Thread::Sleep()


Call Thread::Sleep()
(Put thread to waiting queue) 7
Thread Objects
Thread Objects
• Thread()
– Constructor: sets the thread as JUST_CREATED
h h d status
• Fork()
– Allocate stack, initialize registers.
– Call Scheduler::ReadyToRun()
Call Scheduler::ReadyToRun() to put the thread into readyList, and set its 
to put the thread into readyList and set its
status as READY. 
• Yield()
– Suspend the calling thread and put it into readyList.
– Call Scheduler::FindNextToRun()
C ll S h d l Fi dN tT R () to select another thread from readyList.
t l t th th d f d Li t
– Execute selected thread by Scheduler::Run(), which sets its status as RUNNING 
and call SWITCH() (in code/threads/switch.s) to exchange the running thread.
• Sleep()
– Suspend the current thread and find other thread to run
– Change its state to BLOCKED.
Example : Create Threads
Example : Create Threads
• void SelfTest()
()
– Test whether thread implementation works.
– Fork a new thread and yield current one to execute it
• static void SimpleThread(int which)
– A procedure where execution is to begin when the thread 
starts executing
starts executing
• Command line: nachos ‐K
p j ,y
• In this project, you can trace the above two functions 
as the starting point.
The Flow to Invoke SelfTest()
The Flow to Invoke SelfTest()

In main.cc
– if (strcmp(argv[i], "‐K") == 0) >./nachos ‐K
threadTestFlag g = TRUE;;
– if (threadTestFlag) 
kernel‐>ThreadSelfTest(); kernel‐>ThreadSelfTest()
// test threads and synchronization
• In Kernel::ThreadSelfTest()
In Kernel::ThreadSelfTest()
currentThread‐>SelfTest(); Thread::SelfTest()
// test thread switching
– In Thread::SelfTest()
Thread *t = new Thread("forked thread");
( ); Fork(SimpleThread,1)
( p , )
t‐>Fork((VoidFunctionPtr) SimpleThread, (void *) 1);
kernel‐>currentThread‐>Yield();
SimpleThread(0);

10
Timesharing in Nachos
Timesharing in Nachos
• Alarm object
j
– code/threads/alarm.cc and alarm.h
– Nachos create a Timer object which interrupts every 
“TimerTicks”
TimerTicks  ticks
ticks
• code/machine/timer.cc and timer.h
• When Timer interrupts, nachos calls its interrupt handler 
Timer::CallBack(), which resets the timer and call Alarm::CallBack()
– Alarm::CallBack()
• Call interrupt‐>YieldOnReturn(), which would yield current thread 
in Interrupt::OneTick() after all interrupts are handled
– “Ti
“TimerTicks” is defined in code/machine/stats.h, default is 
Ti k ” i d fi d i d / hi / t t h d f lt i
100
Timesharing in Nachos (Cont.)
Timesharing in Nachos (Cont.)
• Nachos
Nachos initialize a Alarm object in 
initialize a Alarm object in
Kernel::Initialize()
• Alarm generates interrupts every 100 ticks 
Alarm generates interrupts every 100 ticks
(default)
• Nachos yields current thread in Alarm 
Nachos yields current thread in Alarm
interrupt handler
• In effect, no thread could run longer than 100 
In effect, no thread could run longer than 100
ticks 
(unless there is no other threads)
Tasks to done
Tasks to done
• We have following tasks to be completed:
g p
– Implement a priority scheduling to replace default FCFS
– Round‐Robin mechanism is already built by Alarm object, 
b t
but we can change its time slice
h it ti li
Reading Schedule File
Reading Schedule File

• We do actual works in a new function in class 
Thread 
(Modify code/threads/thread cc and thread h)
(Modify code/threads/thread.cc and thread.h)
void Thread::SchedulingTest(char *ParameterFile) {
<Parse the parameter file to put thread’s name, remaining execution ticks, and priority to 
ThreadName[], RemainingExecutionTicks[], and ThreadPriorityp[], respectively.>

Thread *t;
for(i=0;i<NumberOfThreadsDefinedInParemeterFile;i++)
{
t = new Thread(ThreadName[i]);
t = new Thread(ThreadName[i]); 
t‐>setPriority(ThreadPriority[i]);
t‐>Fork((voidFunctionPtr) threadBody, 
(void *) RemainingExecutionTicks[i]);
}
kernel‐>currentThread‐>Yield(); // Give up CPU in order to run new threads
14
}
Reading Schedule File
Reading Schedule File
• Sample schedule file:
p
4
A 2 7
B 1 3
C 3 5
D 2 4
– 4 threads: A,B,C,D
– Thread name, priority, remaining ticks
– P i it 1 10 1 i th hi h t i it
Priority = 1~10, 1 is the highest priority
– Thread name is 10 characters (including NULL) or less, NOTE THAT you 
should provide a newly allocated space for name strings to Thread 
y p g
constructor because it only stores pointer. DON’T give it local 
variables.
Reading Schedule File
Reading Schedule File

• Implement thread body:
– We run a while loop, which loops tick_to_exec times.
This parameter is supplied by 
Fork( (void*) RemainingExecutionTicks[i])
Fork(…, (void*) RemainingExecutionTicks[i])
– Call kernel‐>interrupt‐>OneTick() to increase system 
execution ticks
– Print thread info, including its name and remaining ticks
, g g
void threadBody (int tick_to_exec) {
while(tick_to_exec > 0) {
tick_to_exec‐‐;
kernel >interrupt >OneTick();
kernel‐>interrupt‐>OneTick();
printf("%s: remaining = %d\n", 
kernel‐>currentThread‐>getName(), tick_to_exec);
}
}
16
Priority Scheduling
Priority Scheduling
• Add required member variables and methods to Thread class
(code/threads/thread.cc and thread.h)
– void Thread::setPriority(int p)
• Set new priority p to this thread
– int Thread::getPriority()
• Retrieve current priority
– int priority
• A thread’s priority (private variable)
p y (p )
• Modify constructor to give default priority to new threads
– Thread::Thread()
• In this project, we set default priority to 10 in order to avoid these threads’ 
p j p y
effects when doing our scheduling
Priority Scheduling
Priority Scheduling
• Modify Scheduler class
Modify Scheduler class
– code/threads/scheduler.cc and scheduler.h
– How to do? Please figure it out yourself
– You may need to use SortedList class
– If two threads have the same priority, the first thread in 
the schedule file runs first (FCFS)
h h d l fil fi ( )
Round Robin
Round‐Robin
• Alarm
Alarm class generates interrupts every 
class generates interrupts every
TimerTicks ticks (default = 100)
• TimerTicks is defined in code/machine/stats.h
is defined in code/machine/stats h
• You can change it, and watch the differences
Sample scheduling result
Sample scheduling result
B: remaining = 2
B: remaining = 2
B: remaining = 1
B: remaining = 0
• Time slice = 100 ticks D: remaining = 3
D: remaining = 2
D: remaining = 2
• Schedule file: D: remaining = 1
D: remaining = 0
4
A: remaining = 6
A 2 7 A: remaining = 5
A: remaining = 5
B 1 3 A: remaining = 4
C: remaining = 4
C 3 5 C: remaining = 3
D 2 4 C: remaining = 2
C: remaining = 2
C: remaining = 1
• Why thread D run before  C: remaining = 0
A? A: remaining = 3
A: remaining = 2
A: remaining = 2
– Timer interrupts A: remaining = 1
20
A: remaining = 0
Machine halting!
Requirement
• Implement priority scheduling
• Write a 2‐page report
– Don’t just paste your code, I’ll read it myself
– Change time slice to 50 ticks, run nachos on test schedule we supply 
and explain the results
d l i h l
– You may need to use “‐d +” to trace the execution
• You need to update the 
p threads.cc, threads.h, scheduler.cc and 
, ,
scheduler.h

• If your Project could not run at the time of 
evaluation, it will be considered as FAILURE
Test files
Test files
• We
We supply a test schedule file 
supply a test schedule file “testThreads
testThreads.txt
txt” 
at OS Folder 
– Your implementation should have the same 
Your implementation should have the same
results as the sample scheduling when time slice = 
100
– We will use other schedules to test, so don’t cheat
Deadlines
• Due
Due on Oct 20
on Oct 20
• Late submission will cause a deduction on 20% 
per day
per day
• Do not copy the code & protect your code well
Phase 2
Phase 2

Process Coordination Module
Synchronization
• Practice thread synchronization
Practice thread synchronization
– Producer‐consumer problem
– Dining philosophers problem
Dining philosophers problem
– Implement these problems with Nachos thread 
and synchronization routines
and synchronization routines
Synchronization Problems
Synchronization Problems

• Producer‐consumer problem
– A fixed‐size buffer
– Producer generates data and put it into buffer
Producer generates data and put it into buffer
– Consumer retrieves data from buffer
– They work simultaneously
– The objective is to make sure that
The objective is to make sure that
• producer won’t put data into buffer when it’s full
• consumer won’t remove data from en empty buffer
• the state of buffer is consistent after each action

Producer Buffer Consumer


Producer‐consumer
Producer consumer problem
problem
• When it comes to Nachos …
– A buffer may be a global variable, e.g. a global array
– The consumer and the producer would be threads
• Where the problem lies …
Where the problem lies
– Threads may be yielded at any point
– When both threads access the same data, we must make 
sure that a thread won’t access it when another is working 
h h d ’ i h h i ki
on it.
– Or, the data may be corrupted
Synchronization Problems (cont.)
Synchronization Problems (cont.)
• Dining philosophers problem
Dining philosophers problem
– 5 philosophers, with 5 chopsticks
– A philosopher can either think or 
eat
– When she/he want to eat, she/he 
must take both chopsticks on 
g
her/his left and right
– If all philosophers hold one 
chopstick, we have a deadlock
(philosophers are strange, aren’t 
th ?)
they?)

http://en.wikipedia.org/wiki/Image:Dining_philosophers.png 28
Dining philosophers problem
Dining philosophers problem
• Now we deal with 5 threads, apparently
Now we deal with 5 threads apparently
• Figure out a method to prevent deadlock
– An easy solution is to make sure that a 
A l ti i t k th t
philosopher need to pick up both chopsticks at 
the same time
the same time
Tasks to be done
Tasks to be done 
• Implements
Implements producer
producer‐consumer
consumer problem with 
problem with
semaphores and locks (built by Nachos)
• Implements dining philosopher problem with 
Implements dining philosopher problem with
a monitor‐style class (built by you)
Producer Consumer Problem
Producer Consumer Problem
• Produce and consume 30 items: 0~29
Produce and consume 30 items: 0~29
• The buffer size is 5
• Print the item number you produced or consumed, and the 
current total number of items in the shared buffer
l b fi i h h d b ff
// Thread body for producer
void Producer(int arg) {
int i;
f (i 0 i 30 i ){
for(i=0;i<30;i++){
// Produce item i here (maybe stores it in a global array)
printf("Produced item %d, Total %d item(s)\n“, ...);
}
}

// Thread body for consumer


void Consumer(int arg) {
int i;
for(i=0;i<30;i++){
// Consume item i here (maybe retrieve it from a global array)
printf(“Consumed item %d, Total %d item(s)\n“, ...); 31
}
}
Producer‐Consumer
Producer Consumer problem (cont.)
problem (cont.)
Produced item 0,
0 Total 1 item(s)
Produced item 1, Total 2 item(s)
• Sample output: Consumed item 0, Total 1 item(s)
Consumed item 1, Total 0 item(s)
Produced item 2, Total 1 item(s)
Produced item 3, Total 2 item(s)
Produced item 4, Total 3 item(s)
Consumed item 2, Total 2 item(s)
Produced item 5, Total 3 item(s)
Consumed item 3, Total 2 item(s)
Consumed item 4, Total 1 item(s)
Produced item 6
6, Total 2 item(s)
Consumed item 5, Total 1 item(s)
Produced item 7, Total 2 item(s)
Produced item 8,, Total 3 item(s)
( )
Produced item 9, Total 4 item(s)
32
Consumed item 6, Total 3 item(s)
...
Dining Philosopher problem
Dining Philosopher problem
• Following
Following skeleton is an example, you can 
skeleton is an example, you can
design by yourself
• A monitor
A monitor‐style
style class DiningTable:
class DiningTable:
• We have 5 philosophers (0~4), which means 5 
threads
• Each philosopher starts at thinking, then 
eating, then thinking … for 10 times
eating, then thinking … for 10 times
• Print what a philosopher is doing when she/he 
starts to do that
starts to do that
Dining Philosopher Problem (cont)
Dining Philosopher Problem (cont)
0: Philosopher 0 is eating
0: Philosopher 0 is thinking
• Sample output: 1: Philosopher
0: Philosopher
0
3
is
is
eating
eating
0: Philosopher 3 is thinking
0: Philosopher 2 is eating
1: Philosopher 0 is thinking
0: Philosopher 2 is thinking
0: Philosopher 1 is eating
0: Philosopher 1 is thinking
1: Philosopher 1 is eating
1 Philosopher
1: 1 is thinking
0: Philosopher 4 is eating
0: Philosopher 4 is thinking
p
2: Philosopher 0 is eating
g
1: Philosopher 3 is eating
34
...
Some Tips
Some Tips
• Just like Thread, Semaphore, Lock, and Condition all 
p
have a name argument in constructor: please DO 
NOT provide a local string to them 
• You should make sure that main thread (the only 
You should make sure that main thread (the only
thread which builds other threads) “waits” until 
other threads finish
–H
How to do? This is also a synchronization problem (an easy 
t d ? Thi i l h i ti bl (
one)
Requirements

• Implement 2 synchronization problems
– Make sure that no deadlock would occur
– The output should be reasonable
h h ld b bl
• E.g. in first problem, following output is wrong
Produced item 0, Total 1 item(s)
P d
Produced
d it
item 1
1, T
Total
t l 1 it
item(s)
( ) # T
Total
t l should
h ld bbe 2
Consumed item 2, Total 1 item(s) # Item 2 is not generated yet
• E.g. in second problem, following output is wrong

0: Philosopher 0 is eating
0: Philosopher 1 is eating # Ph. 1 cannot eat because Ph. 0
is eating and holding the
chopstick
h ti k Ph.
h 1 needs
d
36
Documentation
• Write a 2‐page report
– Don’t just paste your code, I’ll read it myself
– Explain why your implementations would generate correct output, 
and why there is no deadlock

• If your Project could not run at the time of 
,
evaluation, it will be considered as FAILURE
• The files you need to update are threads.cc, threads.h, and 
main.cc
Deadlines
• Due
Due on Nov 8
on Nov 8
• Late submission will cause a deduction on 20% 
per day
per day
• Do not copy the code & protect your code well
Phase 3
Phase 3

Multiprogramming
Problem
• Design
Design and implement appropriate support 
and implement appropriate support
for multiprogramming
• Extend the system calls to handle process 
Extend the system calls to handle process
management and inter‐process 
communication primitives
communication primitives
Goal 1
Goal 1
• Alter
Alter your exceptions to finish the thread 
your exceptions to finish the thread
instead of halting the system. 
• This will be important, as a run time exception 
This will be important as a run time exception
should not cause the operating system to shut 
down.
down
• Modify exception.cc
Goal 2
Goal 2
• Implement multiprogramming. 
– The Nachos code is restricted to running one user program at a 
time. 
• In order to convert the system from uni‐programming to 
multiprogramming. 
• Modify addrspace.h, addrspace.cc, and  machine.h
• You will need to:
You will need to:
– Come up with a way of allocating physical memory frames so 
that multiple programs can be loaded into memory at once.
– Properly handling freeing address space when a user program 
p y g g p p g
finishes.
– It is very important to alter the user program loader algorithm 
such that it handles frames of information.
Goal 2 (cont)
Goal 2 (cont)
Modify NumPhysPages (default 128) variable in 
machine.h
• You are not required to deal with limited memory space
• Currently
Currently, memory space allocation assumes that 
memory space allocation assumes that
a process is loaded into a contiguous section of 
memory. 
• Once multiprogramming is active, memory will 
l ll
no longer appear contiguous in nature. 
• If you do not correct the routine, it is most likely 
If you do not correct the routine it is most likely
that loading another user program will corrupt 
the operating system
Documentation
• Write a 2‐page report ( NOT more than 2 )
– Don’t just paste your code, I’ll read it myself
– Explain why your implementations would generate correct output
– Describe meaningful problems you encountered and how you solved.
g p y y

• You need to send us whole NACHOS directory
• If your code could not run at evaluation time, 
If your code could not run at evaluation time
it will be considered as a failure
Deadlines
• Due
Due on Nov 26
on Nov 26
• Late submission will cause a deduction on 20% 
per day
per day
• Do not copy the code & protect your code well
Good Luck
Good Luck

Das könnte Ihnen auch gefallen