技术标签: completion Linux内核 Linux linux
在内核编程中常有这样的场景,在当前线程中创建一个线程,并且等待它完成之后再继续执行。通常可以用信号量来解决它,也可以用completion机制来解决。
使用completion比使用信号量简单。
使用completion可以一次性唤醒所有等待进程,而用信号量会比较麻烦。
The basic summary is that we had this (fairly common) way of waiting for certain events by having a locked semaphore on the stack of the waiter, and then having the waiter do a "down()" which caused it to block until the thing it was waiting for did an "up()".
This works fairly well, but it has a really small (and quite unlikely) race on SMP, that is not so much a race of the idea itself, as of the implementation of the semaphores. We could have fixed the semaphores, but there were a few reasons not to:
CompletionsA common pattern in kernel programming involves initiating some activity outside of the current thread, then waiting for that activity to complete. This activity can be the creation of a new kernel thread or user-space process, a request to an existing process, or some sort of hardware-based action. It such cases, it can be tempting to use a semaphore for synchronization of the two tasks, with code such as: struct semaphore sem; init_MUTEX_LOCKED(&sem); start_external_task(&sem); down(&sem); The external task can then call up(&sem) when its work is done. As is turns out, semaphores are not the best tool to use in this situation. In normal use, code attempting to lock a semaphore finds that semaphore available almost all the time; if there is significant contention for the semaphore, performance suffers and the locking scheme needs to be reviewed. So semaphores have been heavily optimized for the "available" case. When used to communicate task completion in the way shown above, however, the thread calling down will almost always have to wait; performance will suffer accordingly. Semaphores can also be subject to a (difficult) race condition when used in this way if they are declared as automatic variables. In some cases, the semaphore could vanish before the process calling up is finished with it. |
/*
* Completions 目前使用先进先出的队列来存放等待‘completion’的事件
*/
struct completion {
unsigned int done;
wait_queue_head_t wait;
};
(1) 定义completion
struct completion my_completion;
(2) 初始化completion
init_completion(&my_completion);/*动态创建一个completion*/
DECLEARE_COMPLETION(my_completion);/*(包含定义)静态初始化completion*/
(3) 等待completion
/*This waits to be signaled for completion of a specific task. It is NOT interruptible and there is no timeout.*/
void wait_for_completion(struct completion *c);
/*This waits for completion of a specific task to be signaled. It is interruptible.*/
int wait_for_completion_interruptible(struct completion *x);
/*This waits to be signaled for completion of a specific task. It can be
* interrupted by a kill signal.
*/
int wait_for_completion_killable(struct completion *x);
/*This waits for either a completion of a specific task to be signaled or for a
* specified timeout to expire. The timeout is in jiffies. It is not
* interruptible.
*/
unsigned long wait_for_completion_timeout(struct completion *x,
unsigned long timeout);
/** This waits for either a completion of a specific task to be signaled or for a
* specified timeout to expire. It is interruptible. The timeout is in jiffies.
*/
long wait_for_completion_interruptible_timeout(
struct completion *x, unsigned long timeout);
/*This waits for either a completion of a specific task to be
* signaled or for a specified timeout to expire. It can be
* interrupted by a kill signal. The timeout is in jiffies.
*/
long wait_for_completion_killable_timeout(
struct completion *x, unsigned long timeout);
(4) 唤醒completion
void complete(struct completion *c);/*唤醒一个等待的Thread*/
void complete_all(struct completion *c);/*唤醒所有等待此completion的Threads*/
[1] http://stackoverflow.com/questions/4764945/difference-between-completion-variables-and-semaphores
一 VIM打开文件操作:sp file1 分屏打开文件:vsp file1 水平分屏打开文件:e file1 在当前窗口中打开文件使用ctrl + w + 方向键进行切换打开ftp服务器上的文件::e ftp://192.168.10.76/abc.txt保存(如果不存在则创建)::w ftp://192.168.10.76/abc.txt读取::r ftp
Android手势滑动Tab //MainActivity.javapublic class MainActivity extends TabActivity { private static final int SWIPE_MIN_DISTANCE = 120; private static final int SWIPE_MAX_OFF_PATH = 250;...
依赖记得加:implementation 'com.android.support:recyclerview-v7:28.0.0'你的可能是这样的 <android.support.v7.widget.RecyclerView 这才是对的 <androidx.recyclerview.widget.RecyclerView xxx xxx .../>...
前言 Android自带的组件比较丑陋(个人感觉),自己写组件比较复杂,而且必须熟悉android应用层开发的一些机制,如绘制、回调,所以非迫不得已的情况下还是不要自己写组件,因为怕考虑不周全导致譬如性能或异常方面的问题,你自己写也会耗费不少时间。个人觉得采用第三方UI是个不错的选择,尤其是你需要比较复杂的UI组件,而且又比较赶项目的时候。优缺点当然第三方UI组件不全是...
ftp服务器网页空白 内容精选换一换BINDIR为Cntlm的启动目录,/opt/cntlm/etc为Cntlm的配置文件目录,/opt/cntlm/share/man为Cntlm的帮助指南目录。打开cntlm.conf文件。vi /opt/cntlm/etc/cntlm.conf修改文件中如下内容后,保存退出。配置项说明如表1所示。cntlm.conf配置项说明配置项说明BINDIR为Cntlm...
题目:对10个数进行排序。方法一:# -*- coding:utf-8 -*-list = []for i in range(5): a = input('请输入整数:') list.append(a)print listlist.sort()#利用现有的函数方法print list结果为:请输入整数:1请输入整数:2311请输入整数:12请输入...
一、什么是diff算法1、linux中的diff命令,比如diff one.txt two.txt。结果是展示出两个文件的不同。在同一文件夹下面建立两个txt文件,只要内容不完全相同就可以,然后执行diff命令2、git diff查看一个文件的两个版本的区别假设我们修改了上述的log1.txt,然后执行git diff log1.txt二、vdom为何用diff...
决策树又称为判定树,是运用于分类的一种树结构。决策树(decision tree)是一个树结构(可以是二叉树或非二叉树)。其每个非叶节点表示一个特征属性上的测试,每个分支代表这个特征属性在某个值域上的输出,而每个叶节点存放一个类别。使用决策树进行决策的过程就是从根节点开始,测试待分类项中相应的特征属性,并按照其值选择输出分支,直到到达叶子节点,将叶子节点存放的类别作为决策结果。...
回转数法判断一个点是否在多边形内部
论剑mud辅助工具主要包含自动升级、自动主线、支线、自动拜师、自动学技能等多种功能,让你轻松追上老玩家的等级,该脚本是基于叉叉助手运行的,支持手机和模拟器的使用,需要这款软件的朋友赶快来下载吧!论剑mud辅助工具说明:脚本名称:论剑mud脚本脚本适用平台:IOS、安卓脚本主要功能:自动挂机升级、自动任务、拜师学技能脚本使用方法:1.进入游戏2.进入需要自动点击的关卡3.运行脚本脚本安装方法:1、从...
Tian Ji -- The Horse RacingTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 24826 Accepted Submission(s): 7234Problem DescriptionH
[@]TOC1.同一张表内的两列数据找不同值并标记1.1对比A,B列数据:1.2.方法一:快捷键:ctrl+G(1)选中两列(2)快捷键:ctrl+G,弹出定位框,选择定位条件(3)选择“行内容差异单元格”(4)点击确定后,会圈出不一样的值,点击填充或者设置字体颜色进行标记即可。1.2 方法二:利用条件格式(1)选中要标记的那一列(2)选择“条件格式”,再选择“使用公式确定要设置格式的单元格”,在“规则说明”中填写公式,选择格式。(<>:不等于)(3)点击确定,