分类: LINUX
2011-04-13 19:37:43
相关内核源文件说明
/*
* include/linux/spinlock.h - 通用的 spinlock/rwlock 声明
*
* here's the role of the various spinlock/rwlock related include files:
*
* on SMP builds:
*
* asm/spinlock_types.h: 包括 raw_spinlock_t/raw_rwlock_t 类型定义和初始化方法
*
* linux/spinlock_types.h:定义通用的类型和初始化方法
* asm/spinlock.h: 包含 __raw_spin_*()/etc. 这些个底层的实现,多数是汇编代码
*
* (也被引用在 UP-debug builds:)
*
* linux/spinlock_api_smp.h: 包含_spin_*() APIs的原型
*
* linux/spinlock.h: 建立最终的 spin_*() APIs.
*
* on UP builds:
*
* linux/spinlock_type_up.h:
* 包含通用的、简单的UP spinlock类型
*
* linux/spinlock_types.h:
* defines the generic type and initializers
*
* linux/spinlock_up.h:
* contains the __raw_spin_*()/etc. version of UP
* builds. (which are NOPs on non-debug, non-preempt
* builds)
*
* (included on UP-non-debug builds:)
*
* linux/spinlock_api_up.h:
* builds the _spin_*() APIs.
*
* linux/spinlock.h: builds the final spin_*() APIs.
*/
两种情况:
一、SMP、支持抢占
1、结构
/*=========spinlock_t===================*/
typedef struct {
volatile unsigned int slock;
} raw_spinlock_t;
typedef struct {
raw_spinlock_t raw_lock;
#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP)
unsigned int break_lock;
#endif
#ifdef CONFIG_DEBUG_SPINLOCK
unsigned int magic, owner_cpu;
void *owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
} spinlock_t;
/*=========rwlock_t===================*/
typedef struct {
volatile unsigned int lock;
} raw_rwlock_t;
typedef struct {
raw_rwlock_t raw_lock;
#if defined(CONFIG_PREEMPT) && defined(CONFIG_SMP)
unsigned int break_lock;
#endif
#ifdef CONFIG_DEBUG_SPINLOCK
unsigned int magic, owner_cpu;
void *owner;
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
} rwlock_t;
2、接口举例
(a),
spin_lock
#define spin_lock(lock) _spin_lock(lock)
void __lockfunc _spin_lock(spinlock_t *lock)
{
preempt_disable(); /*禁止抢占*/
spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
_raw_spin_lock(lock); /* 请求锁 */
}
# define _raw_spin_lock(lock) __raw_spin_lock(&(lock)->raw_lock)
static inline void __raw_spin_lock(raw_spinlock_t *lock)
{
asm(__raw_spin_lock_string : "+m" (lock->slock) : : "memory");
}
#define __raw_spin_lock_string \
"\n1:\t" \
LOCK_PREFIX " ; decb %0\n\t" \
"jns 3f\n" \
"2:\t" \
"rep;nop\n\t" \
"cmpb $0,%0\n\t" \
"jle 2b\n\t" \
"jmp 1b\n" \
"3:\n\t"
/*
把lock->slock的值减一,判断是否为负(jns指令判断SF标志),若非负(占有锁),跳到标号3 处,退出;若为负(等待锁),执行标号2处的代码,循环执行空指令,并比较slock和0的值,如果小于等于0,继续循环,否则(锁的持有者已经释放它,slock的值被设置为1,见下边unlock)跳到标号1处,重新尝试获取锁。
*/
(b)
spin_unlock
# define spin_unlock(lock) _spin_unlock(lock)
void __lockfunc _spin_unlock(spinlock_t *lock)
{
spin_release(&lock->dep_map, 1, _RET_IP_);
_raw_spin_unlock(lock);/* 释放锁 */
preempt_enable();/* 开启抢占 */
}
# define _raw_spin_unlock(lock) __raw_spin_unlock(&(lock)->raw_lock)
static inline void __raw_spin_unlock(raw_spinlock_t *lock)
{
char oldval = 1;
__asm__ __volatile__(
__raw_spin_unlock_string
);
}
#define __raw_spin_unlock_string \
"xchgb %b0, %1" \
:"=q" (oldval), "+m" (lock->slock) \
:"0" (oldval) : "memory"
/* 把slock的最后字节设置为1 */
static inline int __raw_spin_trylock(raw_spinlock_t *lock)
{
char oldval;
__asm__ __volatile__(
"xchgb %b0,%1"
:"=q" (oldval), "+m" (lock->slock)
:"0" (0) : "memory");
return oldval > 0;
}
/*
倘若如上的锁机制用在不支持抢占和只有一个处理器的系统中,会导致死锁(请求者空转,占有者没机会释放锁),所以在UP系统中建立的spinlock锁大不一样(空空如也)。
*/
二、UP,不支持抢占
// include/linux/spinlock_types_up.h
Typedef strutc { } raw_spinlock_t;
Typedef struct { }raw_rwlock_t;
// include/linux/spinlock_api_up.h
#define _spin_lock(lock) __LOCK(lock)
#define _spin_trylock(lock) ({ __LOCK(lock); 1})
#define _spin_lock_irq(lock) __LOCK_IRQ(lock)
#define __LOCK_IRQ(lock) \
Do{local_irq_disable(); __LOCK(lock); } while(0)
//禁止抢占
#define __LOCK(lock) \
Do { preempt_disable(); __acquire(lock); (void)(lock); } while(0)
#define _spin_unlock(lock) _UNLOCK(lock)
#define __UNLOCK(lock) \
Do{ preempt_enable(); __release(); (void)(lock); } while(0)