futex的pi-support,也就是为futex添加pi算法解决优先级逆转的能力,使用pi-support的futex又称为pi-futex。在linux内核的同步机制中,有一个pi算法的成例,就是rt_mutex实时锁。而futex的pi-support部分就是委托(代理)给rt_mutex进行实现的。

rtmutex,请参看前面的《linux 内核的rt_mutex (realtime互斥体)》。

non-pi futex,请参看前面的《linux 内核的futex》和《linux 内核的各种futex》。

为了让futex使用rt_mutex进行委托,futex设计中添加了一个futex_pi_state结构,这个结构组合了一个rt_mutex作为委托。并将futex_queue这个排队的entry结构添加对futex_pi_state和rt_mutex_waiter的关联,将futex的排队委托成rt_mutex的排队等待rt_mutex_waiter。同时 task_struct 也添加了pi_state_list链表,以维护确保进程(或线程)在持有pi-futex使用的rtmutex代理时退出,进行恢复。

图的上方为pi-futex添加的结构体,下方为non-pi futex使用的结构体。

pi-futex使用了robust-futex定义的锁规则,内核要求用户空间使用它所理解的锁规则,这样一来就可以将原本non-pi futex在用户空间进行的锁操作也委托给内核完成。所以在pi-support的futex系统调用操作 futex_lock_pi 以及 futex_unlock_pi ,还有pi-futex使用在requeue-pi中的futex系统调用操作 futex_wait_requeue_pi 都会在内核在修改用户空间的futex,完成锁操作。

正如这些操作的函数名称字面一样,futex_lock_pi 执行上锁操作(lock)和提供pi-support的排队(pi),而 futex_wait 只单单提供排队服务(wait)。futex_unlock_pi 执行解锁操作(unlock)和提供pi-support的排队唤醒(pi),而 futex_wake 只单单提供排队的唤醒(wake)。

当用户空间使用 futex_lock_pi 进行上锁的slowpath的场合中,内核从排队中唤醒后会尝试对pi-futex进行上锁(锁状态修改),失败后会再次到rt_mutex代理上排队等待。当内核对pi-futex上锁成功后就会返回用户空间,这时用户空间已经得到了内核上好的锁。

这里必须要注意,futex_lock_pi 和 futex_unlock_pi 都是临界区代码,必须被同步。释放pi-futex上的锁不能够像non-pi futex那样在用户空间任意自由地解锁,必须委托rt_mutex锁。由于pi-futex委托了rt_mutex,因此对pi-futex的trylock也不能non-pi futex那样简单地判断失败然后返回,必须进行rt_mutex的trylock委托,所以pi-futex的trylock在失败时,其开销比较大。

futex_lock_pi 和 futex_unlock_pi 在临界区同步使用的是futex_hash_bucket的保护锁,futex模块的共享等待队列。futex_lock_pi 只有在对rt_mutex进行委托调用(rt_mutex_timed_futex_lockrt_mutex_trylock)时才会离开临界区,之后又重新回到临界区。虽然pi-futex排队在rt_mutex锁上,但是它的lock和unlock临界区却使用futex模块的共享等待队列的保护锁同步,也就是说,它与跟它共享相同的共享等待队列的futex,都同步地进行futex系统调用。

下面临界区图示

为什么pi-futex在rt_mutex锁上面委托了排队,还要在futex_hash_bucket->chain上入队呢?futex_queue代表着一个futex的waiter,而futex系统调用并不使用额外的映射表维护pi-futex与rt_mutex委托锁的对应关系,而是将同一个pi-futex的所有futex_queue(等待entry)关联到rt_mutex委托锁上,就可以通过futex_key在futex_hash_bucket->chain上找出futex_queue,从而得到这个pi-futex委托的rt_mutex锁。对于futex系统调用来说,它可见的futex等待就是futex_hash_bucket以及入队其中的futex_queue。从futex_hash_bucket搜索出的第一个futex_queue,已经不能看作是第一个唤醒的等待了,必须委托给它关联的rt_mutex进行仲裁。futex_queue除了多对一关联到rt_mutex外,还一对一关联到rt_mutex_waiter。这时wake_futex_pi不是依据futex_queue来唤醒任务,而使用委托的rt_mutex锁的等待队列waiters上的rt_mutex_waiter来唤醒任务。当pi-futex的阻塞任务唤醒后,才会将自己的futex_queue移出futex_hash_bucket。所以可以看到futex_lock_pi在委托rt_mutex进行排队的前后,也生成了一个futex_queue进行futex_hash_bucket的入队和出队。

linux 内核的futex pi-support,即pi-futex使用rt_mutex委托的更多相关文章

  1. linux 内核的futex

    futex是linux内核为用户空间实现锁等同步机制而设计的同步排队(队列queueing)服务.在futex.c的注释中,futex起源于"Fast Userspace Mutex&quo ...

  2. linux 内核的各种futex

    futex 设计成用户空间快速锁操作,由用户空间实现fastpath,以及内核提供锁竞争排队仲裁服务,由用户空间使用futex系统调用来实现slowpath.futex系统调用提供了三种配对的调用接口 ...

  3. How To Install Linux & Nginx & MySQL & PHP (LEMP) stack on Raspberry Pi 3,Raspberry Pi 3,LEMP,Nginx,PHP, LEMP (not LNMP)

    1.   How To Install Linux & Nginx & MySQL & PHP (LEMP) stack on Raspberry Pi 3         R ...

  4. linux内核级同步机制--futex

    在面试中关于多线程同步,你必须要思考的问题 一文中,我们知道glibc的pthread_cond_timedwait底层是用linux futex机制实现的. 理想的同步机制应该是没有锁冲突时在用户态 ...

  5. linux内核数据结构学习总结

    目录 . 进程相关数据结构 ) struct task_struct ) struct cred ) struct pid_link ) struct pid ) struct signal_stru ...

  6. [中英对照]Linux kernel coding style | Linux内核编码风格

    Linux kernel coding style | Linux内核编码风格 This is a short document describing the preferred coding sty ...

  7. Linux内核编程规范与代码风格

    source: https://www.kernel.org/doc/html/latest/process/coding-style.html translated by trav, travmym ...

  8. 嵌入式Linux内核+根文件系统构建工具-Buildroot 快速入手指导【转】

    本文转载自:https://my.oschina.net/freeblues/blog/596448 嵌入式Linux内核+根文件系统构建工具-Buildroot 快速入手指导 buildroot 是 ...

  9. C 语言代码风格之 Linux 内核代码风格

    GitHub: https://github.com/storagezhang Emai: debugzhang@163.com 华为云社区:https://bbs.huaweicloud.com/b ...

随机推荐

  1. Android开发之NavigationView的使用

    NavigationView主要是和DrawerLayout框架结合使用,来完成抽屉导航实现侧边栏 引用一段官方文档的示例代码 <android.support.v4.widget.Drawer ...

  2. WKWebView代理方法解析

    一.前言 上一篇文章已经对WKWebView做了一个简单的介绍,主要对它的一些方法和属性做了一个简单的介绍,今天看一下WKWebView的两个协议:WKNavigationDelegate 和 WKU ...

  3. 创建keystone的catalog时提示:‘Internal Server Error (HTTP 500)’

    在生成keystone的catalog时: [root@controller ~]# openstack service create --name keystone --description &q ...

  4. iOS回顾笔记(09) -- Cell的添加、删除、更新、批量操作

    iOS回顾笔记(09) -- Cell的添加.删除.更新.批量操作 项目中经常有对UITableViewCell做各种操作的需求: 添加一个新的cell 删除某行cell 刷新cell上某行数据(如修 ...

  5. juddi学习一

    一.下载juddi 地址:https://mirrors.tuna.tsinghua.edu.cn/apache/juddi/juddi/3.3.4/ 二. 解压下载文件打开目录下的 进入bin目录, ...

  6. 性能调优之剖析OutOfMemoryError

    性能调优之剖析OutOfMemoryError   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询q ...

  7. [android] 手机卫士黑名单功能(ListView结合SQLite增删改)

    修改界面,在顶部横条上增加一个添加按钮,点击打开一个自定义对话框,输入电话号码和拦截模式保存到数据库 自定义对话框看这篇http://www.cnblogs.com/taoshihan/p/53703 ...

  8. Android系统结构

    从上图中可以看出,Android系统架构为四层结构,从上层到下层分别是应用程序层.应用程序框架层.系统运行库层以及Linux内核层,分别介绍如下: (1)Appliacation Android平台不 ...

  9. Learning to Rank简介

    Learning to Rank是采用机器学习算法,通过训练模型来解决排序问题,在Information Retrieval,Natural Language Processing,Data Mini ...

  10. /etc/postfix下 main.cf 配置文件详解

    postconf -n   #别名数据库(postalias/newaliases 命令生成) alias_database = hash:/etc/postfix/aliases   #别名表,列出 ...