|
DEFINE_RT_MUTEX(mutexname); // 静态申明实时互斥锁
rt_mutex_init(mutex); // 动态定义实时互斥锁
void rt_mutex_lock(struct rt_mutex *lock); // 申请锁,若申请不到,则深度睡眠
int rt_mutex_lock_interruptible(struct rt_mutex *lock); // 申请锁,若申请不到,则轻度睡眠
int rt_mutex_timed_lock(struct rt_mutex *lock, struct hrtimer_sleeper *timeout); // 申请锁,若申请不到,则睡眠等待一段时间
int rt_mutex_trylock(struct rt_mutex *lock); // 尝试获得锁,成功返回1,失败返回0
void rt_mutex_unlock(struct rt_mutex *lock); // 释放锁
seqlock_t seqlock;
// 初始化方法
DEFINE_SEQLOCK(x)
seplock_init(x)
// 写者写数据的方法
write_seqlock(&seqlock);
// 写数据
write_sequnlock(&seqlock);
// write_seqlock()变体
write_seqlock_bh() // 申请写锁并禁止当前处理器的软中断
write_seqlock_irq() // 申请写锁并禁止当前处理器的硬中断
write_seqlock_irqsave() // 申请写锁,保存但钱处理器的硬件中断状态并禁用处理器的硬中断
// 顺序读者读数据方法
unsigned int seq;
do {
seq = read_seqbegin(&seqlock);
// 读数据
} while(read_seqretry(&seqlock,seq));
// 读者读数据方法
read_seqlock_excl(&seqlock);
// 读数据
read_sequnlock_excl(&seqlock);
//read_seqlock_excl的变体
read_seqlock_excl_bh() //申请自旋锁,并禁止当前处理器的软中断
read_seqlock_excl_irq() //申请自旋锁,并禁止当前处理器的硬中断
read_seqlock_excl_irqsave() //申请自旋锁,保存当前处理器的硬中断状态,并禁用当前处理器的硬中断
// 写着空闲时,读者成为顺序读者,写这些,读者成为持锁着操作
db {
read_seqbegin_or_lock(&seqlock, &seq);
// 读数据
} while (need_seqretry(&seqlock, seq));
done_seqretry(&seqlock, seq);
//read_seqbegin_or_lock 变体
read_seqbegin_or_lock_irqsave() // 附加功能同read_seqlock_excl_irqsave(),都是在原有功能的基础上,
// 保存当前处理器的硬件中断状态,并禁用当前处理器的中断
// 定义方法
seqcount_t x = SEQCNT_ZERQ(x);
seqcount_init(s);
// 写数据方法
spin_lock(&mylock);
write_seqcount_begin(&sc);
// 写数据
write_seqcount_end(&sc);
spin_unlock(&mylock);
// 读数据方法
seqcount_t sc;
unsigned int seq;
do {
seq = read_seqcount_begin(&sc);
// 读数据
} while(read_seqcount_retry(&sc));
preempt_disable() // 禁用内核抢占入口
preempt_enable() // 抢占计数减1,若减到0,则重新调度进程
preempt_enable_no_resched() // 抢占计数减1,若减到0,不重新调度进程
local_bh_disable() // 禁止本处理器的软中断
local_bh_enable() // 使能本处理器的软中断
// 禁止本处理器的硬中断,不同点为save接口会将当前硬件中断状态保存至flags中后再去禁用硬中断
local_irq_disable()
local_irq_save(flags)
// 使能本处理器的硬中断
local_irq_enable()
local_irq_restore(flags)
需要注意的是,local_irq_disable和local_irq_enable不能嵌套使用,而local_irq_save和local_irq_restore可以嵌套使用。
// 静态申明每处理器变量
DEFINE_PER_CPU(type, name) // 声明普通每处理器变量
DEFINE_PER_CPU_FIRST(type, name) // 定义必须在每处理器变量集合中最先出现的变量
DEFINE_PER_CPU_ALIGNED(type, name) // 定义和处理器缓存对齐的每处理器变量
DEFINE_PER_CPU_PAGE_ALIGNED(type, name) // 定义和页长度对齐的每处理器变量
DEFINE_PER_CPU_READ_MOSTLY(type, name) // 定义以读为主的每处理器变量
// 若要每处理器变量能被其他内核模块使用,需要导出至符号表,接口如下:
EXPORT_PER_CPU_SYMBOL(var) // 允许任何内核模块引用
EXPORT_PER_CPU_SYMBOL_GPL(var) // 只允许使用GPL许可的内核模块使用
// 动态每处理器变量
void __percpu *__alloc_percpu_gfp(size_t size, size_t align, gfp_t gfp)
{
return pcpu_alloc(size, align, false, gfp);
}
void __percpu *__alloc_percpu(size_t size, size_t align)
{
return pcpu_alloc(size, align, false, GFP_KERNEL);
}
#define alloc_percpu_gfp(type, gfp) \
(typeof(type) __percpu *)__alloc_percpu_gfp(sizeof(type), \
__alignof__(type), gfp)
#define alloc_percpu(type) \
(typeof(type) __percpu *)__alloc_percpu(sizeof(type), \
__alignof__(type))
//访问每处理器变量
#define VERIFY_PERCPU_PTR(__p) \
({ \
__verify_pcpu_ptr(__p); \
(typeof(*(__p)) __kernel __force *)(__p); \
})
#define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); VERIFY_PERCPU_PTR(ptr); })
#define raw_cpu_ptr(ptr) per_cpu_ptr(ptr, 0)
#define this_cpu_ptr(ptr) raw_cpu_ptr(ptr) // 本质上为基地址加当前处理器的偏移值
#define get_cpu_var(var) \
(*({ \
preempt_disable(); \
this_cpu_ptr(&var); \
}))
#define get_cpu_ptr(var) \
({ \
preempt_disable(); \
this_cpu_ptr(var); \
})
// 每处理器计数器
// 动态初始化每处理器计数器
percpu_counter_init(fbc, value, gfp) // fbc: 计数器地址 value:初始值 gfp:标志位
// 计数累加到每处理器计数器
void percpu_counter_add(struct percpu_counter *fbc, s64 amount)
// 读取近似计数值入口
s64 percpu_counter_read(struct percpu_counter *fbc)
s64 percpu_counter_read_positive(struct percpu_counter *fbc) // 如果是负数,则返回0
//读取准确计数值入口
s64 percpu_counter_sum(struct percpu_counter *fbc)
s64 percpu_counter_sum_positive(struct percpu_counter *fbc) // 如果是负数,则返回0