Subject: Re: DVMA
To: None <chuck@maria.wustl.edu>
From: Charles M. Hannum <mycroft@ai.mit.edu>
List: port-sparc
Date: 06/06/1995 08:12:14
Actually, maybe I can...

One idea is to grab a fixed number of DVMA pages at attach time, and
simply have the driver keep a queue of which ones are available.  That
way you don't have to fiddle with VM structures; just mark it free,
and let the PTEs hang around until someone else grabs them.  This does
have the obvious drawback that the space is always taken, though.

BTW, a somewhat similar problem occured recently with ccd and vnd.
Chris changed them to malloc() and free() struct buf's, but the free()
is done at interrupt time when the I/O request is completed.  The i386
port didn't block bio interrupts while malloc() or free() were
running, so there was a semi-obvious race condition.  Were there some
way to have a callback run outside the interrupt context, this would
have been much simpler; as it was, I fixed it by simply having
splimp() block bio interrupts (a kluge, but analogous to what the
other ports do anyway).

The essential problem is that there is not necessarily a context
backing the I/O; currently, you *have* to handle it at interrupt time.

It's occured to me that perhaps the best solution is to have kernel
threading, and have each driver occupy one thread.  The thread can
then do whatever is necessary; sleep waiting for memory, fall asleep
waiting for its interrupt handler to signal an I/O completion so it
can queue another request, or whatever.  You can also do cleanup for a
finished transaction in the thread.

On most architectures (including the i386, soon), switches between
kernel threads can be very fast, so this shouldn't hurt performance.

On the other hand, waking up another thread non-preemptively is rather
analogous to simply scheduling a soft interrupt to occur RSN, so
perhaps that's overall a preferrable solution.

Another potential solution is something one of Gordon's recent changes
alluded to: a sort of `kernel signal' handling.  If you have a
separate interrupt stack, then you can `push' a frame onto the
non-interrupt stack, such that another function is called before you
return to what you were doing.  However, if this can sleep for a
significant period of time, you have to be very careful about
interactions with things like file system locking.

Of course, depending on the architecture, switching to the interrupt
stack may slow down interrupt entry and exit noticably.


Anyway, this is sort of a catalog of various options.  I'm not really
intending to answer the question here.