Linux驱动之互斥锁

来源:互联网 发布:电子表格软件下载 编辑:程序博客网 时间:2024/06/17 10:47

互斥锁是为了替代信号量,修改于2.6.10-2.6.22。参考:http://blog.chinaunix.net/uid-26023319-id-2980285.html

描述:

/* * Simple, straightforward mutexes with strict semantics: * * - only one task can hold the mutex at a time * - only the owner can unlock the mutex * - multiple unlocks are not permitted * - recursive locking is not permitted * - a mutex object must be initialized via the API * - a mutex object must not be initialized via memset or copying * - task may not exit with mutex held * - memory areas where held locks reside must not be freed * - held mutexes must not be reinitialized * - mutexes may not be used in hardware or software interrupt *   contexts such as tasklets and timers * * These semantics are fully enforced when DEBUG_MUTEXES is * enabled. Furthermore, besides enforcing the above rules, the mutex * debugging code also implements a number of additional features * that make lock debugging easier and faster: * * - uses symbolic names of mutexes, whenever they are printed in debug output * - point-of-acquire tracking, symbolic lookup of function names * - list of all locks held in the system, printout of them * - owner tracking * - detects self-recursing locks and prints out all relevant info * - detects multi-task circular deadlocks and prints out all affected *   locks and tasks (and only those tasks) */struct mutex {/* 1: unlocked, 0: locked, negative: locked, possible waiters */atomic_tcount;spinlock_twait_lock;struct list_headwait_list;#if defined(CONFIG_DEBUG_MUTEXES) || defined(CONFIG_SMP)struct thread_info*owner;#endif#ifdef CONFIG_DEBUG_MUTEXESconst char *name;void*magic;#endif#ifdef CONFIG_DEBUG_LOCK_ALLOCstruct lockdep_mapdep_map;#endif};
可以看出互斥锁的实现还是给予自旋锁以及原子变量。

注意:不能嵌套锁,不能使用在tasklet或则timer这样的中断上下文中。

声明:

#define __MUTEX_INITIALIZER(lockname) \{ .count = ATOMIC_INIT(1) \, .wait_lock = __SPIN_LOCK_UNLOCKED(lockname.wait_lock) \, .wait_list = LIST_HEAD_INIT(lockname.wait_list) \__DEBUG_MUTEX_INITIALIZER(lockname) \__DEP_MAP_MUTEX_INITIALIZER(lockname) }#define DEFINE_MUTEX(mutexname) \struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)extern void __mutex_init(struct mutex *lock, const char *name, struct lock_class_key *key);


获取锁:

/*** * mutex_lock - acquire the mutex * @lock: the mutex to be acquired * * Lock the mutex exclusively for this task. If the mutex is not * available right now, it will sleep until it can get it. * * The mutex must later on be released by the same task that * acquired it. Recursive locking is not allowed. The task * may not exit without first unlocking the mutex. Also, kernel * memory where the mutex resides mutex must not be freed with * the mutex still locked. The mutex must first be initialized * (or statically defined) before it can be locked. memset()-ing * the mutex to 0 is not allowed. * * ( The CONFIG_DEBUG_MUTEXES .config option turns on debugging *   checks that will enforce the restrictions and will also do *   deadlock debugging. ) * * This function is similar to (but not equivalent to) down(). */void __sched mutex_lock(struct mutex *lock){might_sleep();/* * The locking fastpath is the 1->0 transition from * 'unlocked' into 'locked' state. */__mutex_fastpath_lock(&lock->count, __mutex_lock_slowpath);mutex_set_owner(lock);}

释放锁:

/*** * mutex_unlock - release the mutex * @lock: the mutex to be released * * Unlock a mutex that has been locked by this task previously. * * This function must not be used in interrupt context. Unlocking * of a not locked mutex is not allowed. * * This function is similar to (but not equivalent to) up(). */void __sched mutex_unlock(struct mutex *lock){/* * The unlocking fastpath is the 0->1 transition from 'locked' * into 'unlocked' state: */#ifndef CONFIG_DEBUG_MUTEXES/* * When debugging is enabled we must not clear the owner before time, * the slow path will always be taken, and that clears the owner field * after verifying that it was indeed current. */mutex_clear_owner(lock);#endif__mutex_fastpath_unlock(&lock->count, __mutex_unlock_slowpath);}

当然一般地有其他变体:

mutex_lock_interruptible 

mutex_lock_killable

mutex_lock_nested

mutex_lock_interruptible_nested

mutex_lock_killable_nested

mutex_trylock

0 0