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);
#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);
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);
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.