Вы находитесь на странице: 1из 5

Operating Systems

EECE 432
Quiz 1 Solution Oct 25, 2017

Problem 0: Wonder why? (2 pts.)


Why did IBM name the Eclipse IDE as such? Solution: Word is that they wanted to spite
Sun Microsystems who created Java and provided a non-optimal IDE and system libraries for
it, especially for the GUI and system components.

Why are those messages in the browser message passing API named cookies? Solution: the
term was coined by Lou Mntulli (programmer) and he exported it from the Unix magic
cookie idiom. A magic cookie is a piece of data kept at the receiver and not used by the
receiver except for sending it back to the sender. It is sender state information kept at the
receiver side. Magic cookies were first used to tell where in a file is the stream reader. They
are kept by the user code as cursors and made sense only at the file system APIs.

Problem 1: Processes, threads and program elements. (20 pts.)


Consider the following program and answer the following questions.

What is the total number of processes per one invocation of the program? Solution: 2
processes

What is the total number of threads ran by one invocations of the program? Solution: six
threads. main thread + 4 threads + one thread for the forked program.

What is the maximum possible number of times message secret is gets printed? Solution: at
most once per child thread. So 4 times at most.

List two of each of the following program elements.

symbols pointing to the code segment. Solution: main, try, fail are function symbols
with addresses in the code space.
statements that result in context switching. Solution: fopen, fclose, fprintf, cout, cerr,
create thread are all functions that result in context switching.
symbols that point to the data segment. Solution: msg and err point to literal strings
in the data segment.
symbols that point to a stack. Solution: str in function fail. arg and fptr in function
try. argc and argv are in the stack of main.

List a symbol in the program that points to the heap. Solution: word in try is in the stack,
once it is initialized it will holds an address that is in the heap.

1
const char * msg = " Welcome to thread " ; int
const char * err = " Error : failure to " ; main (unsigned i n t argc , char ** argv ) {
i n t pid = fork () ;
void fail ( const char * str ) { i f ( pid == 0) {
cerr << err << str << endl ; cout << " In child . " ;
exit ( -1) ; FILE * fptr = fopen ( argv [1] , " w " ) ;
} fprintf ( fptr , " abracadabra " ) ;
fclose ( fptr ) ;
void * try ( void * arg ) { } e l s e i f ( pid > 0) {
cout << msg << endl ; cout << " In parent . " ;
FILE * fptr = fopen (( char *) arg , " r " ) ; f o r ( i n t i = 0; i < 4; i ++) {
i f ( fptr != NULL ) { pthread_t th ;
char * word = new char [128]; pthr ead_crea te (& th , NULL , try , ( void
fread ( word , 1 , 128 , fptr ) ; *) argv [1]) ;
fclose ( fptr ) ; }
cout << " secret is : " << word << endl ; } else {
delete [] word ; fail ( " spawn child " ) ;
} }
return NULL ; return 0;
} }

Problem 2. Scheduling. (25 pts.)


Consider processes P1 , P2 , P3 , and P4 running on a processor with two cores C0 and C1 . The system
uses a round robin scheduler with a quantum of 4, allows only one kernel thread at a time, and the
kernel thread runs always on core C0 .
Process User-CPU, Kernel-CPU and IO bursts
P1 4 2k 4io 4 2k 4io
P2 2 2k 2io 2 2k 2io
P3 4 1k 3io 4 1k 3io
P4 12 1k 1io 12 1k 1io

Which process is likely doing more computationally intensive tasks? Solution: P4 spends
more time in the CPU. So it is likely doing more computations.
4 2
Which of these processes is likely most interactive? Solution: P1 has a 10
ratio, P2 has a 6
ratio, and P3 has a 35 ratio. So P3 seems more interactive than the rest.

Present a plausible scenario of how the short term schedule might run processes P1 , P2 , P3 , and
P4 on the cores. Assume all processes are ready at the beginning, assume zero time context
switching and zero delay input/output waiting.

Compute the average waiting time (ratio of time processes spent in the ready queue
versus the number of times they entered the ready queue).
Compute the total idle time for both cores (cycles where a core is not running a task).
Are the cores efficiently utilized in your scenario?

Problem 3. Dispatcher-worker threads. (20 pts.)


One dispatcher thread infinitely performs a blocking-listen to requests. Once the dispatcher thread
gets a request, it inserts the request into a queue of tasks (taskQ). Four pre-allocated worker threads
exists. Each worker thread infinitely checks the queue of tasks. If the queue is empty, the worker

2
thread waits on the condition variable. Otherwise, it removes a task from taskQ using the deq
interface. It executes the task and iterates again.
Consider the following dispatcher worker thread implementation.

Is there a possible race condition in the following implementation?

If yes, suggest a fix and argue for correctness.

What if there were two dispatcher threads instead of only one?

Queue < Task > taskQ ; void * worker ( void * arg ) {


Mutex lock ; while ( true ) {
Condition cv ; i f ( taskQ . empty () ) {
void * dispatcher ( void * arg ) { cv . wait ( lock ) ;
while ( true ) { }
Task task = blocking - listen () ; Task task = taskQ . deq () ;
taskQ . enq ( task ) ; task . execute () ;
cv . signal () ; } }
} }

Solution: The taskQ is not guarded and that may cause race conditions: enq and deq called
simultaneously.

Queue < Task > taskQ ; void * worker ( void * arg ) {


Mutex lock ; while ( true ) {
Condition cv ; lock . acquire () ;
void * dispatcher ( void * arg ) { i f ( taskQ . empty () ) {
while ( true ) { cv . wait ( lock ) ;
Task task = blocking - listen () ; } else {
lock . acquire () ; // housing this in the else is important
taskQ . enq ( task ) ; // since in case a thread was suspended
lock . release () ; // then signaled , another thread now enters
cv . signal () ; // the loop and consumes the task .
} } // our thread tries to deq from an empty
// taskQ again .
Task task = taskQ . deq () ;
lock . release () ;
task . execute () ;
} } }

Solution: With more than one dispatcher, the blocking listen acts like a producer. If it does
not guard the tasks it produces, we might have a race condition as well. To secure that, we might
add a lock for the blocking listen.

Problem 4. Collect apples competition. (25 pts.)


A team consists of three players. A team is ready when all players arrive. Four teams compete to
collect the most apples. Once the four teams are ready, a judge blows a whistle. Once the judge
blows the whistle, the teams start collecting the apples. There are a total of 100 apples. Once all
the apples are collected, the game ends and the judge declares the winning team to be the team
with the most collected apples.
Write three or more processes that simulate players, teams and the judge and use your pre-
ferred synchronization constructs (locks, semaphores, condition variables) to simulate the above
synchronization.
Solution: Check a solution in the code below.

3
barrier t e a m R e a d y B a r r i e r [4]; player ( teamIndex ) {
barrier a l l T e a m R e a d y B a r r i e r ; t e a m R e a d y B a r r i er [ teamIndex ]. signal () ;
winner = -1;
whistle . wait ( dummy ) ;
i n t apples = 100; dummy . release () ;
mutex applesLock ; // lock needed to to protect < check
applesLock . acquire () ;
i n t teamAapples [4] = {0 ,0 ,0 ,0}; while ( apples > 0) {
mutex tea mApplesL ock [4]; // release needed : fairness to other
applesLock . release () ; // players
mutex dummy ; // syntactic for whistle // no need for a condition variable
cond_var whistle ; // here since we do not desire the
// suspension ! We are in a competition
team ( teamIndex ) { // and there is no producer ! The apples
// needs three signals to open // are there .
t e a m R e a d y B a r r i er [ teamIndex ]. wait (3) ; // Had the apples been produced while
a l l T e a m R e a d y B a r r i e r . signal () ; // the game is on , we would need a
} // condition variable .
applesLock . acquire () ;
judge () { // applesLock gets released either in
// needs 4 signals to open // the next iteration or after the
a l l T e a m R e a d y B a r r i e r . wait (4) ; // loop exits .
whistle . broadcast () ; // let the game start i f ( apples > 0) {
while ( winner <0) { // judge is very attentive teamA pplesLo ck [ teamIndex ]. acquire () ;
applesLock . acquire () ; // :) always spinning // we need both locks to ensure
i f ( apples > 0) { // the integrity of the count .
} e l s e { // make sure things are correct . apples - -; // apples >= 0 always
assert ( apples == 0) ; teamAapples [ teamIndex ]++;
assert ( sum ( teamApples ,4) == 100) ; teamA pplesLo ck [ teamIndex ]. release () ;
winner = maxindex ( teamApplesLock ,4) ; } e l s e ; { // could wake up judge here
} } // to avoid spinning .
applesLock . release () ; }
} applesLock . release () ;
} }

Problem 5. OS trivia. (20 pts.)


Provide short answers for the following.

A. Name the inter process communication mechanism involved in the following commands.

ps -ef | grep root Solution: pipes.


kill -s 10055 120345 Solution: signals
ssh user@192.168.132.10 Solution: sockets.

B. Give an example of a forced exit of a process. Solution: segmentation faults cause forced
exits. signal kill respected by the process can be a graceful exit in case the process implements
a signal handler for it. Yet, that is an acceptable answer.

C. Which of the following synchronization constructs holds a state?

mutual exclusive lock Solution: holds a state: binary semaphore.


semaphore Solution: holds a state.
condition variable
transactional memory Solution: holds a state: the buffered memory, isDirty?

4
D. Which of the following is part of an operating systems kernel.
Compiler Assembler Scheduler Linker Browser
Editor Device driver Memory manager File system Shell
Solution: Scheduler, Device driver, memory manager, file system.

E. A process spawns two threads. What parts of the process memory do the spawned threads
share? Solution: They share the whole address space. Each thread treats its stack space as
a stack, yet it can access the space of the stack of other threads as regular memory.

Cute student question: What is common between Dinosaurs (cover of Silberchatzs OS


book), Penguins (Linux logo) and operating systems? Perhaps the xkcd.com/1508 comic
below has the answer.
Solution: They are all cute and somehow funny.

Вам также может понравиться