ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

内核自旋锁在释放锁之前启用抢占

2019-11-20 10:51:34  阅读:339  来源: 互联网

标签:scheduling locking kernel linux-kernel linux


当我与一些同事讨论Uni和SMP内核中的自旋锁的行为时,我们深入研究了代码,发现了一条使我们感到惊讶的行,而我们不知道为什么这样做.

简短的电话跟踪,以显示我们来自哪里:

spin_lock calls raw_spin_lock,

raw_spin_lock calls _raw_spin_lock

on a uni-processor system, _raw_spin_lock is #defined as __LOCK

__LOCK是一个定义:

#define __LOCK(lock) \
  do { preempt_disable(); ___LOCK(lock); } while (0)

到现在为止还挺好.我们通过增加内核任务的锁定计数器来禁用抢占.我认为这样做是为了提高性能:由于您不应该在很短的时间内持有自旋锁,因此您应该只完成关键部分而不要被打断,并且可能有另一个任务在等待您执行时将其调度切片转开.完.

但是,现在我们终于提出了我的问题.相应的解锁代码如下所示:

#define __UNLOCK(lock) \
  do { preempt_enable(); ___UNLOCK(lock); } while (0)

为什么要在___UNLOCK之前调用preempt_enable()?这对我们来说似乎很不直观,因为您可能在调用preempt_enable之后立即被抢占,而没有机会释放自旋锁.感觉这使整个preempt_disable / preempt_enable逻辑有些无效,尤其是因为preempt_disable在调用期间专门检查锁定计数器是否再次为0,然后调用调度程序.在我们看来,首先释放锁,然后减少锁计数器,从而有可能再次启用调度,将更加有意义.

我们缺少什么?在___UNLOCK之前而不是反过来调用preempt_enable的想法是什么?

解决方法:

您正在查看单处理器定义.正如spinlock_api_up.h中的注释所说(http://lxr.free-electrons.com/source/include/linux/spinlock_api_up.h#L21):

/*
 * In the UP-nondebug case there's no real locking going on, so the
 * only thing we have to do is to keep the preempt counts and irq
 * flags straight, to suppress compiler warnings of unused lock
 * variables, and to add the proper checker annotations:
 */

___LOCK和___UNLOCK宏用于注释目的,并且除非定义了__CHECKER __(由sparse定义),否则最终将被编译出来.

换句话说,preempt_enable()和preempt_disable()是在单个处理器中进行锁定的对象.

标签:scheduling,locking,kernel,linux-kernel,linux
来源: https://codeday.me/bug/20191120/2043484.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有