Reading character on interrupt handler causes wait queue to wait forever

Viewed 62

I'm programming a driver for a serial communication device that works the following way:

1 - I call a read function from user space.

2 - The system enters in a busy wait until the first character arrives on the FIFO.

3 - A character arrives and the system reads it.

4 - Now, the system shall wait (in a non-busy waiting state) until the next character arrives, thus a waiting queue is being used.

5 - When a character arrives, the hardware raises an interruption. The handler of this interruption then wakes the reading process, which continues.

Initially, I had the following schema for the code:

read_function(int number) {
    busy_wait(!fifo_empty)
    for(i = 0, i < number) {
         char_read = global_buffer;
         wait_event_interruptible(queue,!fifo_empty);
    }

 irq_handler() {
    wake_up(queue);
    global_buffer = read_fifo();
    return IRQ_HANDLED;
 }

However, this had the following problem: After I read the fifo on the handler, the condition "fifo_empty" becomes true. This means that even though I woke up the process in a moment where it was false, before I exit the handler the condition will return back to true and then the reading process won't continue.

I then decided to remove the buffer, and put the read_fifo() call on the read function. However, this causes some problems, namely:

a) The flag that raises the interrupt doesn't go down before I do read_fifo. I'm seeing the interruption being called numerous times on the kernel messages, and the way the function behaves in terms of what is coming first is pretty random.

b) If a character arrives when the read function has not been called, the kernel crashes because the interrupt enters a loop.

c) For some reason, even after having typed number characters, the system won't leave the loop.

I would then like to know whether should I put the fifo_read call on the handler or the read. I strongly believe (based on other answers on this site) that it should be put on the handler. But then how can I wake the process? Obviously using some global variables would do the trick, but I am wondering if there is any better way to do it.

0 Answers
Related