Re: designing fast, streaming disk i/o with mmap: help wanted

From: Paul Barton-Davis (pbd@Op.Net)
Date: Sat Apr 01 2000 - 00:37:19 EST


OK, so forget most of my previous message on this topic. As usually
happens, the task of writing out an explanation of my current scheme
leads to a deeper insight into how to do it right.

I got rid of the whole intermediate ringbuffer idea. The current
scheme now uses mmap(2) exclusively. An excellent prod, since this
removes one entire layer of copying. We now move data from the
soundcard (which is itself using system RAM as a PCI busmaster) direct
to the buffer cache with 1 copy. Very nice.

However, there is still a problem to solve. The audio thread (the one
thats copying data from the soundcard hardware) is absolutely *not*
allowed to block for anything except the soundcard. That includes page
faults. As a result, it must be guaranteed that the region it maps are
in physical memory before it tries to read/write from them. This is
where the butler thread comes in. Its primary job is to keep touching
pages some distance ahead of the current playback and record positions
to try to ensure that the pages are faulted in before the audio thread
tries to use them. If the VM system let us specify this behaviour, we
could do without the butler for this function, but as far as I know,
read-ahead is not configurable, and neither is
"fault-in-and-keep-resident-till-i-say-so" behaviour.

The butler thread has a secondary function: it munmaps() regions that
were used for recording, so that the contents are flushed back to
disk. In the current context, this is less significant.

For the most part, this scheme works well. Typical mmap(2) times are
on the order of 10-30usec; typical data copying time to/from the
mmapped regions by the audio thread on the order of 0.5msec for
32K. This is all just fine.

But every so often, it fails, with either an mmap(2) call that takes
10's of msecs or a copy that takes the same, or both. This leads to
missed deadlines reading from the soundcard.

My guess is that the VM system decided to throw out some of the pages
that the butler thread faulted in, and when the audio thread finally
comes to use them, it has to refault them back into RAM. Right now, I
am typically using 64K * 24 tracks = 1MB of RAM for the read-ahead,
and at any point in time, 32K for each track currently playing back
(i map and unmap the 32K immediately). I would not have expected such
small amounts of RAM to have been the subject of page "ejection".

I know about mlock(2), but I am not clear how to use it here, since
the mapping used by the butler thread is distinct from the mapping
used by the audio thread. All I want to ensure is that once the butler
thread has faulted in data from a file, it won't be lost until the
audio thread unmaps it.

Comments, ideas ?

--p

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Fri Apr 07 2000 - 21:00:07 EST