O'Reilly logo

Linux Device Drivers, Second Edition by Alessandro Rubini, Jonathan Corbet

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Quick Reference

These symbols related to interrupt management were introduced in this chapter.

#include <linux/sched.h> , int request_irq(unsigned int irq, void (*handler)(), unsigned long flags, const char *dev_name, void *dev_id); , void free_irq(unsigned int irq, void *dev_id);

These calls are used to register and unregister an interrupt handler.

SA_INTERRUPT , SA_SHIRQ , SA_SAMPLE_RANDOM

Flags for request_irq. SA_INTERRUPT requests installation of a fast handler (as opposed to a slow one). SA_SHIRQ installs a shared handler, and the third flag asserts that interrupt timestamps can be used to generate system entropy.

/proc/interrupts , /proc/stat

These filesystem nodes are used to report information about hardware interrupts and installed handlers.

unsigned long probe_irq_on(void); , int probe_irq_off(unsigned long);

These functions are used by the driver when it has to probe to determine what interrupt line is being used by a device. The result of probe_irq_on must be passed back to probe_irq_off after the interrupt has been generated. The return value of probe_irq_off is the detected interrupt number.

void disable_irq(int irq); , void disable_irq_nosync(int irq); , void enable_irq(int irq);

A driver can enable and disable interrupt reporting. If the hardware tries to generate an interrupt while interrupts are disabled, the interrupt is lost forever. A driver using a shared handler must not use these functions.

DECLARE_TASKLET(name, function, arg); , tasklet_schedule(struct tasklet_struct *);

Utilities for dealing with tasklets. DECLARE_TASKLET declares a tasklet with the given name; when run, the given function will be called with arg. Use tasklet_schedule to schedule a tasklet for execution.

#include <linux/interrupt.h> , void mark_bh(int nr);

This function marks a bottom half for execution.

#include <linux/spinlock.h> , spinlock_t my_lock = SPINLOCK_UNLOCKED; , spin_lock_init(spinlock_t *lock); , spin_lock(spinlock_t *lock); , spin_lock_irqsave(spinlock_t *lock, unsigned long flags); , spin_lock_irq(spinlock_t *lock); , spin_lock_bh(spinlock_t *lock); , spin_unlock(spinlock_t *lock); , spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags); , spin_unlock_irq(spinlock_t *lock); , spin_unlock_bh(spinlock_t *lock); , spin_is_locked(spinlock_t *lock); , spin_trylock(spinlock_t *lock) , spin_unlock_wait(spinlock_t *lock);

Various utilities for using spinlocks.

rwlock_t my_lock = RW_LOCK_UNLOCKED; , read_lock(rwlock_t *lock); , read_lock_irqsave(rwlock_t *lock, unsigned long flags); , read_lock_irq(rwlock_t *lock); , read_lock_bh(rwlock_t *lock); , read_unlock(rwlock_t *lock); , read_unlock_irqrestore(rwlock_t *lock, unsigned long flags); , read_unlock_irq(rwlock_t *lock); , read_unlock_bh(rwlock_t *lock); , write_lock(rwlock_t *lock); , write_lock_irqsave(rwlock_t *lock, unsigned long flags); , write_lock_irq(rwlock_t *lock); , write_lock_bh(rwlock_t *lock); , write_unlock(rwlock_t *lock); , write_unlock_irqrestore(rwlock_t *lock, unsigned long flags); , write_unlock_irq(rwlock_t *lock); , write_unlock_bh(rwlock_t *lock);

The variations on locking and unlocking for reader-writer spinlocks.

#include <asm/bitops.h> , void set_bit(nr, void *addr); , void clear_bit(nr, void *addr); , void change_bit(nr, void *addr); , test_bit(nr, void *addr); , int test_and_set_bit(nr, void *addr); , int test_and_clear_bit(nr, void *addr); , int test_and_change_bit(nr, void *addr);

These functions atomically access bit values; they can be used for flags or lock variables. Using these functions prevents any race condition related to concurrent access to the bit.

#include <asm/atomic.h> , void atomic_add(atomic_t i, atomic_t *v); , void atomic_sub(atomic_t i, atomic_t *v); , void atomic_inc(atomic_t *v); , void atomic_dec(atomic_t *v); , int atomic_dec_and_test(atomic_t *v);

These functions atomically access integer variables. To achieve a clean compile, the atomic_t variables must be accessed only through these functions.

#include <linux/sched.h> , TASK_RUNNING , TASK_INTERRUPTIBLE , TASK_UNINTERRUPTIBLE

The most commonly used values for the state of the current task. They are used as hints for schedule.

set_current_state(int state);

Sets the current task state to the given value.

void add_wait_queue(struct wait_queue ** p, struct wait_queue * wait) , void remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait) , void __add_wait_queue(struct wait_queue ** p, struct wait_queue * wait) , void __remove_wait_queue(struct wait_queue ** p, struct wait_queue * wait)

The lowest-level functions that use wait queues. The leading underscores indicate a lower-level functionality. In this case, interrupt reporting must already be disabled in the processor.

wait_event(wait_queue_head_t queue, condition); , wait_event_interruptible(wait_queue_head_t queue, condition);

These macros wait on the given queue until the given condition evaluates true.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required