1.相关数据结构及函数如下:

struct thread_info中
{unisgned int preempt_count;//线程抢占引用计数器,为0才能被抢占
}

2.preempt_disable的定义

#define preempt_disable() \
do{ \inc_preempt_count(); \//增加preempt_countbarrier();    \//内存屏障
}while(0)

3.barrier:内存屏障
      内存屏障出现因为编译器gcc或现在的处理器常会自作聪明地对指令序列进行一些处理,比如数据缓存,读写指令乱序执行等等。如果优化对象是普通内存,那么一般会提升性能而且不会产生逻辑错误。但如果对 I/O操作进行类似优化很可能造成致命错误。
4. 常见的调度点
      1)进程被阻塞时比如申请资源时被阻塞
      2)调整参数时   比如通过sched_setscheduler() ,nice()等函数调整进程的调度策略,静态优先级时
      3)睡眠进程被唤醒时:比如wake_up唤醒等待队列中的进程时,如果该进程具有更高优先级则会设置当前进程TIF_NEED_RESCHED,如果允许内核态抢占,则会调度一次
      4)中断处理完时  如果中断处理过程中设置了TIF_NEED_SCHED标志,中断返回时,不论是要返回内核态还是用户态,都会发生一次抢占。当然,在这也会检查有没有软中断需要处理。
      5)执行了preempt_enable()函数。
5. linux下有两种调度方式:
      1)显式调度,进程自己因为缺少相应的所申请的资源,显式调用调度器,让出处理器,比如:内核申请的信号阻塞了,自旋锁锁住了。
      2)隐式调度,整个linux系统在运行过程中的非显示的调用调度器,这又分两种情况:
        A)用户态抢占调度  比如:在系统调用,中断处理,异常处理返回用户态时,该进程的时间片已经用完。
         B)内核态抢占调度  比如:当前内核态执行过程中事先没有禁止内核态抢占,有中断产生时,中断处理 又产生了更高级优先进程,那么就会直接抢占前面的内核态执行体。
6. 抢占式内核中有三处地方需要显示的禁用抢占:
      1) 操作Per-CPU变量的时候,比如smp_processor_id()就是这一类问题,但一个进程被抢占后重新调度,有可能调度到其他的CPU上去,这时定义的Per-CPU变量就会有问题。下面是一个例子:
      2) 必须保护CPU的状态。这类问题是体系结构依赖的。例如,在x86上,进入和退出FPU就是一种临界区,必须在禁抢占的情况下使用。
      3) 获得和释放锁必须在一个进程中实现。也就是说一个锁被一个进程持有,也必须在这个进程中释放。
7.禁用/使能抢占的函数主要有:
      1)spin_lock()/spin_unlock()  spin_lock_irq()/spin_unlock_irq()
      2)disable_preempt()/enable_preempt()(禁止或使能内核抢占)调用下面的inc_preempt_count()/dec_preempt_count(),并且加入了memory barrier。
     3)inc_preempt_count()/dec_preempt_count()
     4)get_cpu()/put_cpu()

preempt_disable宏相关推荐

  1. 【Linux 内核 内存管理】优化内存屏障 ③ ( 编译器屏障 | 禁止 / 开启内核抢占 与 方法保护临界区 | preempt_disable 禁止内核抢占源码 | 开启内核抢占源码 )

    文章目录 一.禁止 / 开启内核抢占 与 方法保护临界区 二.编译器优化屏障 三.preempt_disable 禁止内核抢占 源码 四.preempt_enable 开启内核抢占 源码 一.禁止 / ...

  2. LINUX内核内存屏障

    ================= LINUX内核内存屏障 ================= By: David Howells <dhowells@redhat.com> Paul E ...

  3. C++ 笔记(32)— 预处理、文件包含include、宏替换define、条件包含ifndef、define

    C/C++预处理器在源代码编译之前对其进行一些文本性质的操作. 它的主要任务包括删除注释 . 插入 #include 指令包含的文件的内容 . 定义和替换由 #defme 指令定义的符号以及确定代码的 ...

  4. OpenCV 笔记(04)— OpenCV2 升级到 OpenCV3/CV4 的改动(去掉 CV_前缀、使用新的前缀替换、使用新的命名空间宏)

    1. 由于宏名称的变更照成的"未声明的标识符"系列问题 有时候,遇到此类问题加入一句 #include <cv.h> 便可以让 OpenCV3 或者 OpenCV4 也 ...

  5. TensorRT宏碁自建云(BYOC, BuildYourOwnCloud)上集成

    TensorRT宏碁自建云(BYOC, BuildYourOwnCloud)上集成 这个PR增加了对分区.编译和运行TensorRT BYOC目标的支持. Building 有两个新的cmake标志: ...

  6. 打开word出现“您正试图运行的函数包含有宏或需要宏语言支持的内容。”的解决方法

    1.Word选项→加载bai项→管理→转到--,转到→把勾勾都取消→确定即可. 2.工具→宏->安全性→可靠发行商,将下方的选择框中的钩清空,再将宏安全性改为最高. 3.可能是初次安装Offic ...

  7. C++ #define(宏定义)的使用

    C++ 宏定义 #define命令是C++语言中的一个宏定义命令,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本. 宏定义的一般形式 #define <宏名& ...

  8. 宏使用 Tricks

    人为地定义一些"无意义"的宏(宏名本身有意义),以起到提升代码程序的可读性. 1. IN/OUT 指定参数用于输入还是输出: #define IN #define OUTvoid ...

  9. Keil中使用宏编译来定义DEBUG输出

    使用宏编译来格式化调试信息,是一个不错的方法,即可以在需要的时候打印出信息,还可以格式化我们所需要的输出. #define DEBUG 1 #if (DEBUG == 1) #define DBG(A ...

  10. 子程序调用与宏定义的异同_如何用数控系统进行简单的宏程序调用?老师傅告诉你,用G65就行...

    什么是简单调用?很多人都不知道吧,如果想要深入操作宏, 就先要学会变量,学会变量之担,再去操作宏,就会变得非常的简单,今天给大家分享如何用G65进行简单的宏程序调用. 用户宏的简单宏调用是指在主程序中 ...

最新文章

  1. 深入解析Python中的变量和赋值运算符
  2. Nature:实验室培育的大脑可以拥有意识吗?
  3. SQL Server中的锁的简单学习
  4. 10、MySQL存储引擎有哪些?
  5. 关于datediff(year,开始日期,结束日期)中year格式的说明,特别注意year两边不能加引号,否则报错...
  6. tensorflow中的log中数字的含义
  7. 聊聊 computed 影响性能的场景
  8. 查看未提交事务或sleep session最后执行的sql语句
  9. 【转】Python学习路线
  10. SQL Server CTE 递归查询全解
  11. Java虚拟机------JVM介绍
  12. 未來用工新趨勢_浅谈2019年灵活用工五大新趋势
  13. truffle Migration是什么
  14. XP 多国语言包 .
  15. Shiro保姆级教程
  16. 调用百度图像识别api处理网络图片(文字识别)
  17. Java操作excel自动生成水印背景
  18. 大咖云集!2018中国计算机大会在杭州举行
  19. Windows使用阿里云RAM访问控制API实现自建DDNS动态域名解析
  20. 华为音频编辑服务实时变声,多种音色随意变换

热门文章

  1. 读吴恩达算-EM算法笔记
  2. Android应用资源分析(老罗链接整理)
  3. swift中的category,扩展
  4. (最短路)17bupt新生赛——F. ch追妹
  5. vijos1053 用spfa判断是否存在负环
  6. 一个计算周次和本周时间范围的代码(c#)
  7. 线程同步(互斥锁与信号量的作用与区别)
  8. idea打包SpringBoot项目打包成jar包和war
  9. 二分图最大权匹配:Kuhn-Munkres算法
  10. [Unity] 在协程中等待指定的毫秒