Chinaunix首页 | 论坛 | 博客
  • 博客访问: 712118
  • 博文数量: 165
  • 博客积分: 8218
  • 博客等级: 中将
  • 技术积分: 1749
  • 用 户 组: 普通用户
  • 注册时间: 2008-09-07 19:48
文章分类

全部博文(165)

文章存档

2014年(4)

2011年(3)

2010年(6)

2009年(43)

2008年(109)

分类: LINUX

2008-12-28 21:22:07

Race conditions come about as a result of shared access to resources. When two
threads of execution* have a reason to work with the same data structures (or hard-
ware resources), the potential for mixups always exists. So the first rule of thumb to
keep in mind as you design your driver is to avoid shared resources whenever possi-
ble. If there is no concurrent access, there can be no race conditions. So carefully-
written kernel code should have a minimum of sharing. The most obvious applica-
tion of this idea is to avoid the use of global variables. If you put a resource in a place
where more than one thread of execution can find it, there should be a strong reason
for doing so.
Quick Reference
This chapter has introduced a substantial set of symbols for the management of con-
currency. The most important of these are summarized here:
#include
    The include file that defines semaphores and the operations on them.
DECLARE_MUTEX(name);
DECLARE_MUTEX_LOCKED(name);
    Two macros for declaring and initializing a semaphore used in mutual exclusion
    mode.
void init_MUTEX(struct semaphore *sem);
void init_MUTEX_LOCKED(struct semaphore *sem);
    These two functions can be used to initialize a semaphore at runtime.
void down(struct semaphore *sem);
int down_interruptible(struct semaphore *sem);
int down_trylock(struct semaphore *sem);
void up(struct semaphore *sem);
    Lock and unlock a semaphore. down puts the calling process into an uninter-
    ruptible sleep if need be; down_interruptible, instead, can be interrupted by a sig-
    nal. down_trylock does not sleep; instead, it returns immediately if the
    semaphore is unavailable. Code that locks a semaphore must eventually unlock
    it with up.
struct rw_semaphore;
init_rwsem(struct rw_semaphore *sem);
    The reader/writer version of semaphores and the function that initializes it.
void down_read(struct rw_semaphore *sem);
int down_read_trylock(struct rw_semaphore *sem);
void up_read(struct rw_semaphore *sem);
    Functions for obtaining and releasing read access to a reader/writer semaphore.
void down_write(struct rw_semaphore *sem)
int down_write_trylock(struct rw_semaphore *sem)
void up_write(struct rw_semaphore *sem)
void downgrade_write(struct rw_semaphore *sem)
    Functions for managing write access to a reader/writer semaphore.
#include
DECLARE_COMPLETION(name);
init_completion(struct completion *c);
INIT_COMPLETION(struct completion c);
    The include file describing the Linux completion mechanism, and the normal
    methods for initializing completions. INIT_COMPLETION should be used only to
    reinitialize a completion that has been previously used.
void wait_for_completion(struct completion *c);
    Wait for a completion event to be signalled.
void complete(struct completion *c);
void complete_all(struct completion *c);
    Signal a completion event. complete wakes, at most, one waiting thread, while
    complete_all wakes all waiters.
void complete_and_exit(struct completion *c, long retval);
    Signals a completion event by calling complete and calls exit for the current
    thread.
#include
spinlock_t lock = SPIN_LOCK_UNLOCKED;
spin_lock_init(spinlock_t *lock);
    The include file defining the spinlock interface and the two ways of initializing
    locks.
void spin_lock(spinlock_t *lock);
void spin_lock_irqsave(spinlock_t *lock, unsigned long flags);
void spin_lock_irq(spinlock_t *lock);
void spin_lock_bh(spinlock_t *lock);
    The various ways of locking a spinlock and, possibly, disabling interrupts.
int spin_trylock(spinlock_t *lock);
int spin_trylock_bh(spinlock_t *lock);
    Nonspinning versions of the above functions; these return 0 in case of failure to
    obtain the lock, nonzero otherwise.
void spin_unlock(spinlock_t *lock);
void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags);
void spin_unlock_irq(spinlock_t *lock);
void spin_unlock_bh(spinlock_t *lock);
    The corresponding ways of releasing a spinlock.
rwlock_t lock = RW_LOCK_UNLOCKED
rwlock_init(rwlock_t *lock);
    The two ways of initializing reader/writer locks.
void read_lock(rwlock_t *lock);
void read_lock_irqsave(rwlock_t *lock, unsigned long flags);
void read_lock_irq(rwlock_t *lock);
void read_lock_bh(rwlock_t *lock);
    Functions for obtaining read access to a reader/writer lock.
void read_unlock(rwlock_t *lock);
void read_unlock_irqrestore(rwlock_t *lock, unsigned long flags);
void read_unlock_irq(rwlock_t *lock);
void read_unlock_bh(rwlock_t *lock);
    Functions for releasing read access to a reader/writer spinlock.
void write_lock(rwlock_t *lock);
void write_lock_irqsave(rwlock_t *lock, unsigned long flags);
void write_lock_irq(rwlock_t *lock);
void write_lock_bh(rwlock_t *lock);
    Functions for obtaining write access to a reader/writer lock.
void write_unlock(rwlock_t *lock);
void write_unlock_irqrestore(rwlock_t *lock, unsigned long flags);
void write_unlock_irq(rwlock_t *lock);
void write_unlock_bh(rwlock_t *lock);
    Functions for releasing write access to a reader/writer spinlock.
#include
atomic_t v = ATOMIC_INIT(value);
void atomic_set(atomic_t *v, int i);
int atomic_read(atomic_t *v);
void atomic_add(int i, atomic_t *v);
void atomic_sub(int i, atomic_t *v);
void atomic_inc(atomic_t *v);
void atomic_dec(atomic_t *v);
int atomic_inc_and_test(atomic_t *v);
int atomic_dec_and_test(atomic_t *v);
int atomic_sub_and_test(int i, atomic_t *v);
int atomic_add_negative(int i, atomic_t *v);
int atomic_add_return(int i, atomic_t *v);
int atomic_sub_return(int i, atomic_t *v);
int atomic_inc_return(atomic_t *v);
int atomic_dec_return(atomic_t *v);
    Atomically access integer variables. The atomic_t variables must be accessed
    only through these functions.
#include
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);
    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
seqlock_t lock = SEQLOCK_UNLOCKED;
seqlock_init(seqlock_t *lock);
    The include file defining seqlocks and the two ways of initializing them.
unsigned int read_seqbegin(seqlock_t *lock);
unsigned int read_seqbegin_irqsave(seqlock_t *lock, unsigned long flags);
int read_seqretry(seqlock_t *lock, unsigned int seq);
int read_seqretry_irqrestore(seqlock_t *lock, unsigned int seq, unsigned long
  flags);
    Functions for obtaining read access to a seqlock-protected resources.
void write_seqlock(seqlock_t *lock);
void write_seqlock_irqsave(seqlock_t *lock, unsigned long flags);
void write_seqlock_irq(seqlock_t *lock);
void write_seqlock_bh(seqlock_t *lock);
int write_tryseqlock(seqlock_t *lock);
    Functions for obtaining write access to a seqlock-protected resource.
void write_sequnlock(seqlock_t *lock);
void write_sequnlock_irqrestore(seqlock_t *lock, unsigned long flags);
void write_sequnlock_irq(seqlock_t *lock);
void write_sequnlock_bh(seqlock_t *lock);
    Functions for releasing write access to a seqlock-protected resource.
#include
    The include file required to use the read-copy-update (RCU) mechanism.
void rcu_read_lock;
void rcu_read_unlock;
    Macros for obtaining atomic read access to a resource protected by RCU.
void call_rcu(struct rcu_head *head, void (*func)(void *arg), void *arg);
    Arranges for a callback to run after all processors have been scheduled and an
    RCU-protected resource can be safely freed.
阅读(567) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~