Skip site navigation (1)Skip section navigation (2)
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>