2

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.

Mölp
  • 142
  • 9
  • Usually, one should call wake_up only after having made changes that can impact the condition. Your code seems to do the exact opposite of that in the handler. This could be the cause for the alleged random behaviour. – embedded_dev Dec 01 '20 at 11:20
  • @embedded_dev the problem of random things happened was, as explained, not in the case of the pseudo code. – Mölp Dec 01 '20 at 11:23

0 Answers0