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>