본문 바로가기

Linux/Device Driver

seqlock

전역 변수를 이용해서 인터럽트를 할 경우 동기를 맞추기 위해 인터럽트의 금지와 해제를 이용한다.
이를 처리하는 루틴을 수행 할 때 특정 데이터가 인터럽트 서비스 함수에서 변경되어 이후 처리 루틴
에 영향을 미칠수 있기 때문에 예기치 못한 결과를 발생하게 된다. 이를 방지하기 위해서


// -----------------------------------------------------------------

kernel 2.6 에서 seqlock_t 구조체를 제공한다.

#include <linux/seqlock.h>

// 제어용 변수
seqlock_t the_lock = SEQLOCK_UNLOCKED;
unsigned int seq;

// 데이터 변경 루틴
write_seqlock(&the_lock);
// data change routine
write_sequnlock(&the_lock);

// 데이터 취득 루틴
do
{
    seq = read_seqbegin(&the_lock);
    // data value process routine
}
while read_seqretry(&the_lock, seq);

// example --------------------------------------------------------

seqlock_t the_lock = SEQLOCK_UNLOCKED;
unsigned int seq;

unsigned char ReadData = 0;
irqreturn_t xxx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
    write_seqlock(&the_lock);
    ReadData = inb(IN_ADDR);
    write_sequnlock(&the_lock);
    return IRQ_HANDLED;
}

ssize_t xxx_read(struct fiel *filp, char *buf, size_t count, loff_t *f_pos)
{
    do
    {
        seq = read_seqbegin(&the_lock);
        if(ReadData)
        {
            // process routine
        }
        outb(ReadData | 0x80);
    }
    while read_seqretry(&the_lock, seq);

    return 1;
}