hw5:
two options, preemptive scheduler (“sched”) or
semaphore service (“sem”). To get started, copy everything from
$cs444/hw5 to your hw5 dir, including subdirs queue
and intqueue You can do this in
one recursive copy:
“cp
–r $cs444/hw5/* .”
hw5:
almost the same as hw3 solutions, with a little bit added.
Run of provided hw5 uprog123.c, built by “make U=uprog123”, or just “make”--looks same as hw3 solution
Recall this part of the expanded debuglog--
~a|(0-1)
|(1b-2)|(2b-3)|(3b-0)
~a|(0-1)
start delay loop in uprog1 process 1
running a long time here (no preemption possible)
~a~a~a~z~z~z~S drain output Q, shut down ints, all processes
have status RUN
~A|(1b-2)|(2b-3)|(3b-0) A output, more A's enqueued, process 1 finally
blocked
~A|(0-1)
|(1b-2)|(2b-3)|(3b-0)
~A|(0-1)
|(1b-2)|(2b-3)|(3b-0)
Find
the sequence
~a~a~a~z~z~z~S n the above debug log report. That happens when process 1 runs its long loop of
computations. It runs long enough that the
queue drains out (that takes 6 ms, 1 ms for each character), and the TX interrupts
are shut down, shown by the final S in the sequence.
Once
you get preemption working, it should show in this run. When process 1 runs its compute loop, it will use
up its quantum, and the output will drain, making process 2 and process 3 ready, so
preemption will cause a process switch from process 1 to process 2. The debug log will report the preemption: “|(1-2)”.
~a~a~a~z~z~z~S drain output Q, shut down ints, all processes have status RUN
|(1-2)~b(2b-3)(3b-1)
process 1 is preempted, 2 runs, fills
queue, blocks, 3 runs, blocks, 1 runs
...
(b may or may not be output during
this)
Note: to get preemption working, we need to add timer interrupts.
Another set of user programs for sched option: sequences
make
U=sequences builds sequences.lnx,
but, like uprog123, it doesn’t do preemption yet. It tests the case of two CPU-bound processes
running together. With preemption, they
should trade off the use of the CPU.
Test user programs for semaphore option: testmutex.c, prodcons.c.
Note
that although testmutex builds, it doesn’t run
properly because it can’t yet do real semaphore calls. You need to add new syscalls to ulib.s and the
kernel, and then uncomment the calls in testmutex.c.
Testmutex
uses a mutex semaphore to keep user input
straight.
main1: creates a semaphore of initial count 1 and puts its id in mutex, sets startflag to 1
main2: first makes sure that startflag
== 1, so that mutex is a good semaphore id
prints
“A requests mutex”
down(mutex);
prints
“A has mutex, enter 2 chars”
reads 2
chars -- This causes a big delay
up(mutex);
main3: first makes sure that startflag
== 1
prints
“B requests mutex”
down(mutex);
prints
“B has mutex, enter 2 chars”
reads 2
chars
up(mutex);
Here
is how the testmutex.lnx runs before you implement
the semaphore calls: Here the user typed
12 after the first prompt and 34 after the second prompt. Note that the provided hw5 tty.c blocks on input as well as output.
Tutor> go 100100
startflag=0 (this is a kprintf,
so no blocking here)
A requests mutex
A has mutex, enter 2
chars: --after this, A blocks on the read
B requests mutex
B has mutex, enter 2
chars: --but
A has not released the mutex yet!
12A got 12, releasing mutex
34B got 34, releasing mSHUTTING
DOWN
utex
Here
is the output from a run with working semaphores.
Tutor> go 100100
startflag=0
A requests mutex
A has mutex, enter 2
chars: --after
this, A blocks on the read
B requests mutex --
B starts running, but then blocks on the semaphore
12A got 12, releasing mutex
B has mutex, enter 2
chars: --
finally B gets the mutex after A releases it.
34B got 34, releasing mSHUTTING
DOWN
utex