Re: Problems writting a CHAR Driver with interruptible_sleep

Ingo Oeser (ingo.oeser@informatik.tu-chemnitz.de)
Fri, 13 Aug 1999 01:17:46 +0200 (CEST)


On Thu, 12 Aug 1999, Raul Dias wrote:

[wakeup before sleep problem]

Try using a short circular buffer for the data and modify your
routines as follows

> the read function has something like this:
> .....
> outb (ioport, 0xFF); /* Ask for data */
> interruptible_sleep_on (&wait_q); /* waits for the interrupt */
> data = inb (ioport); /* grabs the data */
move the above line into the ISR and modify like this:

down(&datasem);
cbuf[tail++] = inb (ioport);
if (tail > MAX_ELEMENTS) tail=0; /* that's, why it's circular ;) */
up(&datasem);

wake_up_interruptible(&wait_q);

/* check for ringbuffer overflows here! Delete the oldest
* element, if overflow and count it as an error.
*/


and in your read function sth. like this

down(&datasem);
if (head != tail)
data = cbuf[head++];
else
/* your reader EAGAIN as an error if in O_NONBLOCK */

if (head > MAX_ELEMENTS) head=0; /* that's, why it's circular ;) */
up(&datasem)

You can even readout the whole buffer or at least as much as fits
into of the buffer given to your read file operation.

remain = buflen; /* 3rd parameter of fops->read */
count = 0;

/* "*userbuf" is the 2nd parameter of fops->read
* and valid for writing "buflen" bytes into it
*/

down(&datasem);
while (remain && head != tail) {
userbuf[count++] = cbuf[head++];
if (head > MAX_ELEMENTS) head=0; /* that's, why it's circular ;) */
remain--;
};
up(&datasem)

My solution is _NOT_ considered optimal, but should work. I
assumed, that your "cbuf" is a _byte_ buffer and that you return
"count" as a result.

> I need the data as fast as I can get (that's fundamental in the
> project), so I am trying to avoid a delay loop, and I guess it would
> slow things a bit in the system also.

Hmm, you better design your hardware to have it wait (may be
still collecting data into a small FIFO?) until you ack the
interrupt or read the data inside the ISR _before_ you ack the
interrupt to the PIC[1] (as I suggested).

> What I need to solve this, is a way to detect (in the interrupt
> handler) that the function is not sleeping yet.

No, this is IMHO the wrong direction for solving your problem.

Hope this helps a bit and works ;)

Regards

Ingo Oeser

[1] Programmable Interrupt Controller.

-- 
Feel the power of the penguin - run linux@your.pc
<esc>:x

- 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/