The mouse is a slow, low-data rate device, so making it polling isn't a big deal.
Implementing an asynchronous write would seem to make the most sense. Once a process has written data, it is done with that data and may move on to other data; there is no need to wait for the data write to finish. On the other hand, when reading data, the process may be able to do other things, but can't proceed with its main-line processing until the data show up. The performance advantages to an asynchronous write are always available, but the performance advantages to an asynchronous read depends on the process's ability to find other things to do while the read takes place.
The answer gets more complicated if you look at the storage being used to hold the data. In this case the writes are equivalent to reads because, while the data may not matter, the storage holding the data does, and the writing process has to wait until the OS is done reading the storage before the process can write it again. This can be dealt with using double buffering, but the same technique can be used for reading too. There is still, however, a slight advantage to writing over reading due to the potential delay required when the read buffer is filling for the first time.
The idea is to get mutual exclusion while in the semaphore's get()
and put()
operations. The easiest way to do that on a priority-based
selection scheduler is to raise the priority of the calling process to its
maximum for the duration of the calls:
old_p = set_priority(max_p) // access semaphore data set_priority(old_p)
For safety, max_p
should be a high priority reserved for use by
semaphores (and other OS structures providing mutual exclusion).
p() while true begin_cs() while not empty { } buffer = p() empty = false end_cs() c() while true begin_cs() while empty { } c(buffer) empty = true end_cs()
Assuming empty
is initially false, is this correct? Explain. Note that
this question is asking whether or not the code is correct, not whether or
not it is well written.
Given the incorrect initial value for empty
, this question turned out
to be tricker to answer than I anticipated. Let me first given the answer I
was trying to elicit, and then I'll deal with the empty
is false
assumption.
The problem with your colleague's code is that the critical section in
both cases is too large. A process waiting for empty to become a particular
value (true for the consumer and false for the produce) will spin within the
critical section, which blocks out the other process from ever changing
empty
.
Now for the initial value of empty. For the most part, the initial value of
empty is irrelevant to the answer for this question; I had added the clause
to keep people from getting side-tracked about the initial value of
empty
(of course, by getting the initial value wrong, exactly the
opposite effect occurred). Given the false initial value, you have to make
a further assumption to answer the question: the state of the buffer itself.
If you assume the buffer contains garbage (which is an inconsistent
assumption, although one you're allowed to make) then another problem
could be that the first read by the consumer returns garbage if the consumer
enters the critical section first. If you assume the buffer contains data,
the initial value of empty doesn't matter.
This page last modified on 14 November 2004.