0

I am reading LLDR3, having a question on P.271 in section "Implementing a Handler"

Bottom are codes I am having questions:

I see writer ( ISR ) and reader ( which is waken-up by ISR ) they are touching on same buffer ( short_queue ), since they are touching on the shared resource, doesn't it worry about the case where "short_i_read" got interrupted by the writer ISR while it is working on buffer?

I can understand ISR writer won't get interrupted since it is ISR and normally IRQ will be disabled until completion. But for buffer read "short_i_read" , I don't see any place to guarantee atomic operation.

The one thing I notice is :

  • buffer writer(ISR) only increment on short_head
  • buffer reader only increment on short_tail

Does that mean this code here let writer and reader only touch different variable to have it achieve kind of lock-free circular buffer?

irqreturn_t short_interrupt(int irq, void *dev_id, struct pt_regs *regs) {
    struct timeval tv;    
    int written;
    do_gettimeofday(&tv);
    /* Write a 16 byte record. Assume PAGE_SIZE is a multiple of 16 */
    written = sprintf((char *)short_head,"%08u.%06u\n", (int)(tv.tv_sec % 100000000), (int)(tv.tv_usec));    
    BUG_ON(written != 16);
    short_incr_bp(&short_head, written);
    wake_up_interruptible(&short_queue);
    /* awake any reading process */
    return IRQ_HANDLED; 
}


static inline void short_incr_bp(volatile unsigned long *index, int delta) {
    unsigned long new = *index + delta;
    barrier();  /* Don't optimize these two together */
    *index = (new >= (short_buffer + PAGE_SIZE)) ? short_buffer : new; 
}

ssize_t short_i_read (struct file *filp, char __user *buf, size_t count,     loff_t *f_pos) 
{
    int count0;
    DEFINE_WAIT(wait);
    while (short_head == short_tail) {
        prepare_to_wait(&short_queue, &wait, TASK_INTERRUPTIBLE);
        if (short_head == short_tail)
            schedule();
        finish_wait(&short_queue, &wait);
        if (signal_pending (current))  /* a signal arrived */
            return -ERESTARTSYS; /* tell the fs layer to handle it */    
    }    
    /* count0 is the number of readable data bytes */
    count0 = short_head - short_tail;
    if (count0 < 0) /* wrapped */
    count0 = short_buffer + PAGE_SIZE - short_tail;
    if (count0 < count) count = count0;
    if (copy_to_user(buf, (char *)short_tail, count))
        return -EFAULT;
    short_incr_bp (&short_tail, count); 
    return count; 
}

ch001
  • 69
  • 1
  • 4

0 Answers0