文章目录
10. 原子变量(atomic_t)
- 头文件
#include <linux/types.h>
// -> <linuc/atomic.h>
// -> <asm-generic/atomic64.h>
- 结构体
/* 32bit */
typedef LONG atomic_t;
#define LONG .wordk
/* 64bit */
typedef struct {
long long counter;
} atomic64_t;
- 实例
#ifdef _TEST_ATOMIC_32
/* 32bit */
int val_a = 0;
atomic_t a = ATOMIC_INIT(0);// int a = 32;
// set / read
atomic_set(&a, 32); // a = 100;
val_a = atomic_read(&a); // VAL = a;
// add / sub
atomic_add(1, &a); // a = a + 1;
atomic_sub(2, &a); // a = a - 1;
// inc / dec
atomic_inc(&a); // a++;
atomic_dec(&a); // a--;
#else
/* 64bit */
u64 val_b = 0; // unsigned long long val_b = 0;
atomic64_t b = ATOMIC64_INIT(0); // unsigned long long b = 0;
// set / read
atomic64_set(&b, 64); // b = 64
val_b = atomic64_read(&b); // VAL = b;
// add / sub
atomic64_add(1, &b); // b = b + 1;
atomic64_sub(2, &b); // b = b - 1;
// inc / dec
atomic64_inc(&b); // b++;
atomic64_dec(&b); // b--;
#endif
- 备注
32bit与64bit有两套接口,但是部分API是通用的,
底层实现都是靠barrier(),
不同长度的数据读取也可以靠类型转换来实现。
20. 自旋锁(spinlock_t)
- 头文件
#include <linux/spinlock_types.h> // for spinlock
- 结构体
typedef struct spinlock {
union {
struct raw_spinlock rlock;
};
} spinlock_t;
- 实例
#include <linux/spinlock_types.h>
static DEFINE_SPINLOCK(vga_lock); // init
{
unsigned long flags;
spin_lock_irqsave(&test_spinlock, flags);
{
// do something
}
spin_unlock_irqrestore(&test_spinlock, flags);
}
#if 0
{/* in irq */
spin_lock();
spin_unlock();
}
#endif
- 备注
- 临界代码中不要调用会引起系统调度的代码,即不要把cpu让出去
- 中断肯定会导致嵌套,而锁又不能做系统调度,两者量结合会导致死锁,所以需要屏蔽中断。
2.1 调用_irqsave()、_irqrestore()做中断现场的保存和恢复
2.2 中断中直接调用,不需要处理中断- 头文件会有嵌套,这里的头文件只是最终的头文件,下面不再赘述
21. 读写锁(rwlock_t)
- 头文件
#include <linux/rwlock_types.h> // for rwlock
- 结构体
typedef struct {
arch_rwlock_t raw_lock;
} rwlock_t;
- 实例
#include <linux/rwlock_types.h>
static DEFINE_RWLOCK(test_rwlock); // init
{
unsigned long flags;
/* read lock */
read_lock_irqsave(&test_rwlock, flags);
{
// read something
}
read_unlock_irqrestore(&test_rwlock, flags);
/* write lock */
write_lock_irqsave(&test_rwlock, flags);
{
// write something
}
write_unlock_irqrestore(&test_rwlock, flags);
}
- 备注
- 自旋锁解决了 读-读、读-写、写-写的竞态,但是读-读是可以并发的,所以引入了读写锁
- 与自旋锁在使用上的区别在于,定义了将读-写分成了两部分API,由程序员分类处理读写
22. 顺序锁(seqlock_t)
- 头文件
#include <linuc/seqlock.h> // for seqlock
- 结构体
typedef struct {
struct seqcount seqcount;
spinlock_t lock;
} seqlock_t;
- 实例
#include <linuc/seqlock.h>
static DEFINE_SEQLOCK(test_seqlock); // init
{
unsigned long flags;
/* read seqlock */
{
unsigned seq;
retry:
seq = read_seqbegin(&test_seqlock);
{
// read something
}
if(read_seqretry(&test_seqlock, seq))
goto retry;
}
/* write seqlock */
write_seqlock_irqsave(&test_seqlock, flags);
{
// write something
}
write_sequnlock_irqrestore(&test_seqlock, flags);
}
- 备注
- 顺序锁在读写锁的基础上,又允许了写-写的并发,其实现逻辑如下:
1.1 写:获取锁,写操作,释放锁(写操作会修改序号,给读取函数来判断)
1.2 读:先获取一个序号,读操作,判断之前的序号是否变化,如果变化了重新执行“获取-读取-判断”
30. 信号量(semaphore)
- 头文件
#include <linux/semaphore.h>
- 结构体
struct semaphore {
raw_spinlock_t lock;
unsigned int count;
struct list_head wait_list;
};
#define __SEMAPHORE_INITIALIZER(name, n) \
{ \
.lock = __RAW_SPIN_LOCK_UNLOCKED((name).lock), \
.count = n, \
.wait_list = LIST_HEAD_INIT((name).wait_list), \
}
#define DEFINE_SEMAPHORE(name) \
struct semaphore name = __SEMAPHORE_INITIALIZER(name, 1)
- 实例
#include <linux/semaphore.h>
static DEFINE_SEMAPHORE(test_sem); // cnt = 1
down(&test_sem);
// down_trylock(&test_sem); // return 0 if success; else return 1
// down_interruptible(&test_sem); // return 0 if success; else return -EINTR
{
/* do something */
}
up(&test_sem);
- remarks
31. 互斥体(mutex)
- 头文件
#include <linux/mutex.h>
- 结构体
struct mutex {
/* 1: unlocked, 0: locked, negative: locked, possible waiters */
atomic_t count;
spinlock_t wait_lock;
struct list_head wait_list;
};
#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)
- 实例
#include <linux/mutex.h>
static DEFINE_MUTEX(test_mutex);
mutex_lock(&test_mutex);
// mutex_trylock(&test_mutex); // return 1 if success; else return 0
// mutex_lock_interruptible(&test_mutex); // return 0 if success; else return !0
{
/* do something */
}
// mutex_is_locked(&test_mutex); // return 1 if success; else return 0
mutex_unlock(&test_mutex);
本文含有隐藏内容,请 开通VIP 后查看