Date: Fri, 23 Jan 1998 22:49:23 +1030 From: Mike Smith <mike@smith.net.au> To: daniel_sobral@voga.com.br Cc: mike@smith.net.au, hackers@FreeBSD.ORG Subject: Re: uiomove() Message-ID: <199801231219.WAA00455@word.smith.net.au> In-Reply-To: Your message of "Fri, 23 Jan 1998 09:55:25 -0300." <83256595.0045CB26.00@papagaio.voga.com.br>
next in thread | previous in thread | raw e-mail | index | archive | help
>
> > Er. Why do it that way? I presume that you are passed
> > a pointer to a linear region containing "plaintext", and
> > your task is to convert it into "ciphertext". Am I
> > close?
>
> > If not, then I assume that you have separate write and
> > read interfaces.
>
> Yep, I'm using separate read and write interfaces.
Do you have to do this? Are all your consumers in the kernel?
> > Can the card only handle one character at a time? How
> > slow is it handling a character/block?
>
> The card has single character and eight characters modes, but it is
> terribly slow in either mode. If I block everything until I finish the
> operation, I can gain about 20% in the 8 characters mode (which still must
> be feed one by one). As it is, both modes are taking almost the same time
> to process. The main problem is that I don't have a precise definition of
> how much time each operation takes. I only know some operations take up to
> a second to complete. The 512 bytes buffer I used to test the driver
> currently takes me 21 seconds to be processed, a reasonable amount of this
> time, it seems, taken by context switches. I plan to reduce it further
> using wakeup instead of 1 tick tsleeps (as I'm doing right now).
You could use an exponential backoff, or a weighted hunting heuristic.
I would be inclined to try to gather some data on the average
performance of the card in order to improve such a computation.
> > Do you (plan to) handle more than one writer at a time? Do
> > you synchronise writers and readers?
>
> The card is too stupid to handle multiple readers/writers (though I only
> realised that, and simplified the driver, after someone asked me how I
> saved context from stream to stream). I only accept one open() at a time.
I think that was me. 8) Only accepting one open won't save you from
multiple writers. (Think about fd inheritance from parent to child.)
If you only support one stream at a time, there is no requirement to
synchronise your input or output at all. I would do something like this:
#define CRYPT_CHUNK 64
struct crypt_softc
{
char waiting[CRYPT_CHUNK];
int nwaiting;
char done[CRYPT_CHUNK];
int ndone;
int flags
#define C_READBUSY (1<<0)
};
crypt_write(...)
{
int s, result, hmuch;
struct crypt_softc *sc = ...
while (uio->uio_resid > 0) {
s = splsoftclock();
while (sc->nwaiting > 0) {
tsleep(&sc->nwaiting, PCATCH, "cryptwrite", 0)
}
splx(s);
hmuch = min(uio->uio_resid, CRYPT_CHUNK);
result = uiomove(sc->waiting, hmuch, uio);
if (result)
return(result);
sc->nwaiting = hmuch;
}
return(0);
}
crypt_read(...)
{
struct crypt_softc *sc = ...
int s, result;
while (uio->uio_resid > 0) {
s = splsoftclock();
while (sc->nready == 0) {
tsleep(&sc->nready, PCATCH, "cryptread", 0);
}
splx(s);
sc->flags |= C_READBUSY;
hmuch = min(uio->uio_resid, sc->nready);
result = uiomove(sc->ready, hmuch, uio);
if (!result && (hmuch < sc->nready))
bcopy(sc->ready + hmuch, sc->ready,
sc->nready - hmuch);
sc->nready -= hmuch;
sc->flags &= ~C_READBUSY;
if (result)
return(result);
}
return(0);
}
crypt_timeout(...)
{
struct crypt_softc *sc = ...
if (crypt_card_ready_for_input()) {
if (sc->nwaiting == 0)
wakeup(&sc->nwaiting);
else
crypt_stuff_data_from_waitlist()
}
if (crypt_card_has_data()) {
if (!(sc->flags & C_READBUSY) && (sc->nready < CRYPT_CHUNK)) {
crypt_get_data_from_card()
wakeup(&sc->nready)
}
}
timeout(crypt_timeout, ...)
}
}
> > Your calls won't be preempted unless another is called from an
> > interrupt context.
>
> What about SMP?
Device drivers are currently exclusive. If you're really worried
about SMP, ask the SMP people about how to obtain a lock and wait
against one.
> > splsoftclock() is probably the one you want.
>
> Thanks. Still, I'd really appreciate knowing the difference between
> splsoftclock and splsofttty...
splsoftty() prevents soft tty interrupts (timeouts used for tty
processing). splsoftclock() prevents software clock (timer) interrupts.
> A working queue was my first take on this, but since, as it is, it will
> gain me nothing, I decided on my current model.
Fair enough.
--
\\ Sometimes you're ahead, \\ Mike Smith
\\ sometimes you're behind. \\ mike@smith.net.au
\\ The race is long, and in the \\ msmith@freebsd.org
\\ end it's only with yourself. \\
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199801231219.WAA00455>
