同步原语 API¶
本文档介绍 NoobKernel 同步机制的主要 API。
自旋锁¶
#include <sync/spinlock.h>
// 锁类型
typedef struct {
const char *name;
volatile u64 locked;
} spinlock_t;
// 静态初始化
#define SPINLOCK_INITIALIZER(n) \
(spinlock_t){.name = n, .locked = 0}
// 获取锁
void spinlock_acquire(spinlock_t *lock);
// 释放锁
void spinlock_release(spinlock_t *lock);
// 检查是否持有锁
int spinlock_holding(spinlock_t *lock);
使用示例¶
static spinlock_t my_lock = SPINLOCK_INITIALIZER("my_lock");
void protected_operation(void) {
spinlock_acquire(&my_lock);
// 临界区代码
shared_data++;
spinlock_release(&my_lock);
}
锁的注意事项¶
- 获取锁时自动关中断:避免中断处理函数中的死锁
- 持锁时间要短:不要在持锁时进行 I/O 或睡眠
- 避免嵌套锁:如果必须嵌套,确保顺序一致
原子操作(32位)¶
#include <sync/atomic.h>
// 原子类型
typedef struct {
volatile int32_t counter;
} atomic_t;
// 初始化
#define ATOMIC_INIT(i) {(i)}
// 读取
int32_t atomic_read(const atomic_t *v);
// 设置
void atomic_set(atomic_t *v, int32_t i);
// 加并返回新值
int32_t atomic_add_return(int32_t i, atomic_t *v);
// 减并返回新值
int32_t atomic_sub_return(int32_t i, atomic_t *v);
// 加并返回旧值
int32_t atomic_fetch_add(int32_t i, atomic_t *v);
// 递增
int32_t atomic_inc(atomic_t *v);
// 递减
int32_t atomic_dec(atomic_t *v);
// 比较交换
int32_t atomic_cmpxchg(atomic_t *v, int32_t old_val, int32_t new_val);
// 交换
int32_t atomic_xchg(atomic_t *v, int32_t new_val);
原子操作(64位)¶
#include <sync/atomic.h>
typedef struct {
volatile int64_t counter;
} atomic64_t;
#define ATOMIC64_INIT(i) {(i)}
int64_t atomic64_read(const atomic64_t *v);
void atomic64_set(atomic64_t *v, int64_t i);
int64_t atomic64_add_return(int64_t i, atomic64_t *v);
int64_t atomic64_sub_return(int64_t i, atomic64_t *v);
int64_t atomic64_fetch_add(int64_t i, atomic64_t *v);
int64_t atomic64_inc(atomic64_t *v);
int64_t atomic64_dec(atomic64_t *v);
int64_t atomic64_cmpxchg(atomic64_t *v, int64_t old_val, int64_t new_val);
int64_t atomic64_xchg(atomic64_t *v, int64_t new_val);
使用示例¶
static atomic_t counter = ATOMIC_INIT(0);
void increment(void) {
atomic_inc(&counter);
}
int get_count(void) {
return atomic_read(&counter);
}
// 比较交换
int old = atomic_read(&counter);
if (old == 10) {
atomic_cmpxchg(&counter, 10, 20);
}
指针原子操作¶
#include <sync/atomic.h>
typedef atomic64_t atomic_ptr_t;
#define ATOMIC_PTR_INIT(i) ATOMIC64_INIT((int64_t)(uintptr_t)(i))
void *atomic_ptr_read(const atomic_ptr_t *v);
void atomic_ptr_set(atomic_ptr_t *v, void *p);
void *atomic_ptr_xchg(atomic_ptr_t *v, void *new_ptr);
void *atomic_ptr_cmpxchg(atomic_ptr_t *v, void *old_ptr, void *new_ptr);
无锁栈示例¶
struct node {
int value;
struct node *next;
};
static atomic_ptr_t stack_top = ATOMIC_PTR_INIT(NULL);
void push(struct node *n) {
struct node *old_top;
do {
old_top = atomic_ptr_read(&stack_top);
n->next = old_top;
} while (atomic_ptr_cmpxchg(&stack_top, old_top, n) != old_top);
}
struct node *pop(void) {
struct node *top;
do {
top = atomic_ptr_read(&stack_top);
if (!top) return NULL;
} while (atomic_ptr_cmpxchg(&stack_top, top, top->next) != top);
return top;
}
内存屏障¶
// 编译器屏障
#define barrier() asm volatile("" ::: "memory")
// 使用 GCC 内置原子操作时已包含屏障
// SEQ_CST:全序一致性
// ACQUIRE:读屏障
// RELEASE:写屏障
READ_ONCE / WRITE_ONCE¶
防止编译器优化:
#define READ_ONCE(x) __atomic_load_n(&(x), __ATOMIC_RELAXED)
#define WRITE_ONCE(x, val) __atomic_store_n(&(x), (val), __ATOMIC_RELAXED)
使用场景¶
// 防止编译器假设变量不变
int flag = 0;
// 等待 flag 变化
while (!READ_ONCE(flag)) {
cpu_relax();
}
// 设置 flag
WRITE_ONCE(flag, 1);
中断控制¶
#include <trap/trap.h>
// 关中断
void intr_off(void);
// 开中断
void intr_on(void);
// 恢复中断状态
void restore_intr(u64 old);
与锁配合¶
自旋锁获取时自动关中断,释放时恢复:
void spinlock_acquire_bare(spinlock_t *lock) {
intr_off(); // 关中断
// ... 等待锁
}
void spinlock_release_bare(spinlock_t *lock) {
// ... 释放锁
intr_on(); // 开中断
}
最佳实践¶
保护共享数据¶
static int shared_data;
static spinlock_t data_lock = SPINLOCK_INITIALIZER("data");
void update_data(int new_value) {
spinlock_acquire(&data_lock);
shared_data = new_value;
spinlock_release(&data_lock);
}
原子计数¶
static atomic_t active_count = ATOMIC_INIT(0);
void task_start(void) {
atomic_inc(&active_count);
}
void task_end(void) {
atomic_dec(&active_count);
}
bool has_active_tasks(void) {
return atomic_read(&active_count) > 0;
}
避免死锁¶
// 错误:不同顺序获取锁
void foo(void) {
spinlock_acquire(&lock_a);
spinlock_acquire(&lock_b);
// ...
}
void bar(void) {
spinlock_acquire(&lock_b); // 死锁风险
spinlock_acquire(&lock_a);
// ...
}
// 正确:固定顺序
void foo(void) {
spinlock_acquire(&lock_a);
spinlock_acquire(&lock_b);
// ...
}
void bar(void) {
spinlock_acquire(&lock_a); // 先获取 lock_a
spinlock_acquire(&lock_b);
// ...
}
减少锁粒度¶
// 错误:锁粒度太大
void process_all(void) {
spinlock_acquire(&big_lock);
for (int i = 0; i < 1000; i++) {
process_item(i);
}
spinlock_release(&big_lock);
}
// 正确:锁粒度小
void process_all(void) {
for (int i = 0; i < 1000; i++) {
spinlock_acquire(&item_lock);
process_item(i);
spinlock_release(&item_lock);
}
}