首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么schedule()在使用默认的prepare_arch_switch()时不会导致死锁

为什么schedule()在使用默认的prepare_arch_switch()时不会导致死锁
EN

Stack Overflow用户
提问于 2015-11-28 04:27:47
回答 1查看 146关注 0票数 0

在Linux2.6.11.12中,在shedule()函数选择要运行的"next“任务之前,它将锁定运行队列

代码语言:javascript
复制
spin_lock_irq(&rq->lock);

在调用context_switch()执行上下文切换之前,它将调用prepare_arch_switch(),这在默认情况下是不操作的:

代码语言:javascript
复制
/*
 * Default context-switch locking:
 */
#ifndef prepare_arch_switch
# define prepare_arch_switch(rq, next)  do { } while (0)
# define finish_arch_switch(rq, next)   spin_unlock_irq(&(rq)->lock)
# define task_running(rq, p)        ((rq)->curr == (p))
#endif

也就是说,它将保存rq->lock直到switch_to()返回,然后宏finish_arch_switch()实际上会释放锁。

假设有任务A、B和C,现在A调用schedule()并切换到B(现在,rq->lock被锁定)。迟早,B会调用schedule()。此时,B将如何获得rq->lock,因为它被A锁定了?

也有一些依赖于拱的实现,例如:

代码语言:javascript
复制
/*
 * On IA-64, we don't want to hold the runqueue's lock during the low-level context-switch,
 * because that could cause a deadlock.  Here is an example by Erich Focht:
 *
 * Example:
 * CPU#0:
 * schedule()
 *    -> spin_lock_irq(&rq->lock)
 *    -> context_switch()
 *       -> wrap_mmu_context()
 *          -> read_lock(&tasklist_lock)
 *
 * CPU#1:
 * sys_wait4() or release_task() or forget_original_parent()
 *    -> write_lock(&tasklist_lock)
 *    -> do_notify_parent()
 *       -> wake_up_parent()
 *          -> try_to_wake_up()
 *             -> spin_lock_irq(&parent_rq->lock)
 *
 * If the parent's rq happens to be on CPU#0, we'll wait for the rq->lock
 * of that CPU which will not be released, because there we wait for the
 * tasklist_lock to become available.
 */
#define prepare_arch_switch(rq, next)       \
do {                                        \
    spin_lock(&(next)->switch_lock);        \
    spin_unlock(&(rq)->lock);               \
} while (0)
#define finish_arch_switch(rq, prev)    spin_unlock_irq(&(prev)->switch_lock)

在这种情况下,我非常肯定这个版本会做正确的事情,因为它在调用rq->lock之前先解锁context_switch()

但是默认的实现会发生什么呢?它怎么能做对的事?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-11-28 05:47:57

我在Linux2.6.32.68的context_switch()中找到了一条评论,它讲述了代码下面的故事:

代码语言:javascript
复制
/*
 * Since the runqueue lock will be released by the next
 * task (which is an invalid locking op but in the case
 * of the scheduler it's an obvious special-case), so we
 * do an early lockdep release here:
 */

然而,我们不会切换到锁定了lock的另一个任务,下一个任务将解锁它,如果下一个任务是新创建的,ret_from_fork()函数也将最终调用finish_task_switch()来解锁rq->lock

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33967687

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档