从0到1 simple wait queue

90 阅读1分钟

最近看了swait.c (simple wait queue)的源码,尝试自己实现一下

1、背景

要实现以下目标:

(1) 不满足等待条件一直等待,不可被打断

(2) 并发正确的等待队列

(3) timeout机制

kernel 5.15

2、实现

(1) 先来实现目标1 2

//队列头和队列节点
struct swait_queue_head {
	raw_spinlock_t		lock;
	struct list_head	task_list;
};

struct swait_queue {
	struct task_struct	*task;
	struct list_head	task_list;
};
//无需返回值
void swait_event_uninterruptable(swait_queue_head *wq, func_t condition) {
    swait_queue __wait;
    
    spin_lock(wq->lock);
    list_add(__wait.task_list, &wq->task_list);
    spin_unlock(wq->lock);
    
    for (;;) {
        if(condition)
            break;
        //设置线程状态,每次被唤醒都需要重新设置    
        set_current_state()
        scheduler();
    }
    
    spin_lock(wq->lock);
    list_del(__wait.task_list);
    spin_unlock(wq->lock);
}

(2) timeout实现,目标3

//需要返回值确定是成功还是timeout
// 0 timeout
// !0 success
long swait_event_uninterruptable(swait_queue_head *wq, func_t condition, long timeout) {
    swait_queue __wait;
    long __ret = timeout;    
    
    spin_lock(wq->lock);
    list_add(&__wait.task_list, &wq->task_list);
    spin_unlock(wq->lock);
    
    for (;;) {
        //防止condition = true && __ret == 0 返回值不对的情况
        if(condition && !__ret)
            __ret = 1;
        //等待条件为true 或者 超时
        if(condition || !__ret) {
            break;
        }
            
        //设置线程状态,每次被唤醒都需要重新设置    
        set_current_state()
        //返回到timeout还有多少时间
        __ret = scheduler_timeout(__ret);
    }
    
    spin_lock(wq->lock);
    list_del(&__wait.task_list);
    spin_unlock(wq->lock);    
    
    return __ret;
}

3、 todo

(1) swait还有

interruptable(涉及信号)

exclusive

两个维度,有兴趣再研究吧

源码里用一个宏实现了所有维度的函数,抽象的比较好

(2) 有simple wait queue 就必然有真正的wait queue,实现肯定比这个复杂,swait.c开头的注释里也说了