Skip to content

同步原语 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);
}

锁的注意事项

  1. 获取锁时自动关中断:避免中断处理函数中的死锁
  2. 持锁时间要短:不要在持锁时进行 I/O 或睡眠
  3. 避免嵌套锁:如果必须嵌套,确保顺序一致

原子操作(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);
    }
}