一些内核进程调度API (4)

本文详细介绍了Linux内核中的几个关键进程调度API,包括`add_wait_queue`、`add_wait_queue_exclusive`用于向等待队列添加进程,`autoremove_wake_function`用于唤醒并移除等待队列中的进程,以及`complete`和`complete_all`用于批量唤醒进程。这些API在处理进程等待和唤醒机制时起着核心作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//实现将等待队列元素插入等待队列第一个元素的位置
//并设置这个元素的flags为 非WQ_FLAG_EXCLUSIVE ,代表此进程不是高优先级进程
void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
{
unsigned long flags;


wait->flags &= ~WQ_FLAG_EXCLUSIVE;
spin_lock_irqsave(&q->lock, flags);
__add_wait_queue(q, wait);
spin_unlock_irqrestore(&q->lock, flags);
}


//与 add_wait_queue 相反,将等待元素加入到等待队列的尾部
//并设置这个元素的flags为 WQ_FLAG_EXCLUSIVE , 代表此进程是高优先级进程
void add_wait_queue_exclusive(wait_queue_head_t *q, wait_queue_t *wait)
{
unsigned long flags;


wait->flags |= WQ_FLAG_EXCLUSIVE;
spin_lock_irqsave(&q->lock, flags);
__add_wait_queue_tail(q, wait);
spin_unlock_irqrestore(&q->lock, flags);
}


//唤醒等待队列中某一进程,唤醒成功后把它从等待队列中删除
/*wait 某个进程
  mode 处于如下状态的进程才能够被唤醒:TASK_ALL/TASK_NORMAL
                                       TASK_NORMAL:可中断或不可中断的等待状态的进程
   TASK_ALL:   TASK_NORMAL及暂停状态和跟踪状态的进程
  sync 0-非同步唤醒   非0-同步唤醒
  key  唤醒时执行函数,一般给NULL
  
  返回值:0-唤醒失败,并且进程没有从等待队列中删除,没有找到满足条件的进程
          1-唤醒成功,并且使进程由 其他状态,变为 TASK_RUNNING 态,获得CPU资源,从而被调度执行
*/
int autoremove_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
{
int ret = default_wake_function(wait, mode, sync, key);


if (ret)
list_del_init(&wait->task_list);
return ret;
}


//唤醒等待队列中的睡眠进程,记录唤醒次数,保存在 done 中
//唤醒不同步,按等待队列中元素顺序,一个一个唤醒,遇到flags字段为 WQ_FLAG_EXCLUSIVE ,则停止
//唤醒
#define WQ_FLAG_EXCLUSIVE 0x01  //等待队列的flags字段的值
#define WQ_FLAG_WOKEN 0x02
struct completion {
unsigned int done;      //等待队列的唤醒情况,代表等待队列中元素被唤醒的次数
wait_queue_head_t wait; //等待队列的头元素
};
void complete(struct completion *x)
{
unsigned long flags;


spin_lock_irqsave(&x->wait.lock, flags);
x->done++;
__wake_up_locked(&x->wait, TASK_NORMAL, 1);
spin_unlock_irqrestore(&x->wait.lock, flags);
}


//唤醒所有睡眠进程
/*与 complete 的区别:
  complete_all 的 done无法再代表唤醒次数
  complete_all 遇到flags为 WQ_FLAG_EXCLUSIVE ,不会再停下来,而是继续唤醒后面的进程
*/
void complete_all(struct completion *x)
{
unsigned long flags;


spin_lock_irqsave(&x->wait.lock, flags);
x->done += UINT_MAX/2;
__wake_up_locked(&x->wait, TASK_NORMAL, 0);
spin_unlock_irqrestore(&x->wait.lock, flags);
}
void __wake_up_locked(wait_queue_head_t *q, unsigned int mode, int nr)
{
__wake_up_common(q, mode, nr, 0, NULL);
}
static void __wake_up_common(wait_queue_head_t *q, unsigned int mode,
                 int nr_exclusive    , int wake_flags   , void *key)
{
wait_queue_t *curr, *next;


list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
unsigned flags = curr->flags;


if (curr->func(curr, mode, wake_flags, key) &&
(flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
break;
}
}




//查看等待队列是否有等待者,1-没有等待者 0-有等待者
bool completion_done(struct completion *x)
{
unsigned long flags;
int ret = 1;


spin_lock_irqsave(&x->wait.lock, flags);
if (!x->done)
ret = 0;
spin_unlock_irqrestore(&x->wait.lock, flags);
return ret;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值