Messages in this thread | | | Date | Fri, 13 Aug 1999 01:17:46 +0200 (CEST) | From | Ingo Oeser <> | Subject | Re: Problems writting a CHAR Driver with interruptible_sleep (wait_queue) |
| |
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/
| |