Nitya
Emmett
Sit
If you're still reading after all that nonsense I just said, how are we
supposed to do this?
"Emmett Witchel" <wit...@cs.utexas.edu> wrote in message
news:d5k5m8$d2$2...@geraldo.cc.utexas.edu...
I'm trying to handle this by attaching a queue of continuations (i.e.
OSEvents) to each page, and the read interrupt handler runs each of
these in order. So if you have 5 processes trying to read the same page,
they'll all get blocked, and then when the page is done reading they'll
all get unblocked and have ReadCheck.write called and so forth.
I can't tell how the sample code expects us to handle this case either,
so I ended up redesigning almost everything and I agree it seems like
something else was intended.
Above, in "Lab 5: File size greater than Memory" the following discourse
took place:
Sit said:
for this lab, let's just assume we have enough memory so that these
situations do not happen...
In response to Syed Kamil Fareed:
> On a similar note, what should we return from removeLRU() if we cant
> remove any of the blocks if all of them have their io_pending boolean to
> true?
>
This makes it seem like we can simply assume that we will not run into the
case where the only pages that exist in memory when we need to call
removeLRU() are pages that are either pinned = true or io_pending = true.
That is, can we always assume enough memory for io_pending jobs to complete
their io before their cached page is needed?
I am currently wrestling the same demon as Craig and Adrian, unless I am
mistaken there is no way in our simulator to block a process in a fashion
similar to a normal system. What I mean is, there is no way for us to just
halt a process's activity, pack up what it is currently doing, and make it
just wait (like blocking on a Monitor.wait()). The system seems to force us
to complete the current call stack on a process before it "blocks." Being
forced to complete the current call stack causes problems when RemoveLRU()
is called because we cannot be certain about which page to return (something
that removeLRU "guarantees").
Or, are we supposed to use the strict ordering of io to simply assign pages
assuming that as long as we take the oldest one, its io access will finish
before ours?
--Eric
Yes, I believe this is true. We will not test this case.
> I am currently wrestling the same demon as Craig and Adrian, unless I am
> mistaken there is no way in our simulator to block a process in a fashion
> similar to a normal system. What I mean is, there is no way for us to just
> halt a process's activity, pack up what it is currently doing, and make it
> just wait (like blocking on a Monitor.wait()). The system seems to force us
> to complete the current call stack on a process before it "blocks." Being
> forced to complete the current call stack causes problems when RemoveLRU()
> is called because we cannot be certain about which page to return (something
> that removeLRU "guarantees").
>
> Or, are we supposed to use the strict ordering of io to simply assign pages
> assuming that as long as we take the oldest one, its io access will finish
> before ours?
I believe we use the strict ordering of I/O. This is not ideal, but it is ok for this lab and keeps things simple. Sit can confirm.
Emmett
Maybe this will confuse more people than it helps, but I have to share
this revelation I had. The whole deal with OSEvents is actually a wacky
form of continuation passing style[1]. You can think of event_number +
state as a function pointer, and when you pass this into a blocking
function like read, it does its IO and then "calls" the continuation to
let the process continue doing whatever it was when it blocked.
Thinking in CPS terms, you're turning your code "inside out" around the
possible blocking points, so that everything after the blocking point
goes into a continuation passed into the blocking method.
Of course, as you noticed nothing actually "blocks"; the blocking call
returns immediately and you are expected to unwind the call stack all
the way back to ProcessTrace.run, which will pick up and run the
continuation for you. This is called trampolining; it's a way of getting
around the fact that Java doesn't do tail-call elimination. If you never
returned you'd eventually run out of stack space, so you smuggle your
return values into the continuation and unwind to the top level which
starts the continuation on your behalf.
Since Java has primitive closures (local inner classes), you can make
OSEvent do *anything* you want, not just limited to the methods and
states already in the code. So you could do a read like this:
sched.proc_block(pid);
bufferTableEntry.lockForIo();
blockDriver.read(devNum, new OSEvent(baseEvent) {
public void happen() {
baseEvent.happen();
bufferTableEntry.unlockForIo();
sched.proc_unblock(pid);
bufferTableEntry.notifyWaiters();
}
});
Actually that won't work literally with the code we have, but hopefully
you get the idea -- it's starting to look like *real* CPS. Personally I
find this a lot easier to understand than the hard-coded function
pointers used in the lab, but not everybody agrees with me.
yes, this is true.
Sit
So what does this mean? We assign it the memPage that it would normally
receive, and just hope that the pending IO will complete first? Wouldn't
that mean that the IOPending flag does nothing?