Linux 内核完成接口

Linux 内核里面有一个函数wait_for_completion,这是一个内核同步机制的函数,同步机制如果是早期的读者应该看过我发的文章,如果没有看过的可以看看Linux 专辑文章里面找找。

既然是同步机制,主要的工作就是调用了这个函数,程序就会等另外的事件完成之后再继续下面的工作。

wait_for_completion 结构体

/** struct completion - structure used to maintain state for a "completion"** This is the opaque structure used to maintain the state for a "completion".* Completions currently use a FIFO to queue threads that have to wait for* the "completion" event.** See also:  complete(), wait_for_completion() (and friends _timeout,* _interruptible, _interruptible_timeout, and _killable), init_completion(),* reinit_completion(), and macros DECLARE_COMPLETION(),* DECLARE_COMPLETION_ONSTACK().*/
struct completion {unsigned int done;wait_queue_head_t wait;
};

结构体里面就两个东西,一个是 done,一个是队列wait。

还有他相关的函数

complete()
wait_for_completion() 
init_completion()
reinit_completion()
DECLARE_COMPLETION()
DECLARE_COMPLETION_ONSTACK().

如何使用?

先声明

struct completion bl_ready;
init_completion(&ts->bl_ready);

需要等待退出的线程

static irqreturn_t cyttsp_irq(int irq, void *handle)
{struct cyttsp *ts = handle;int error;/*退出的时候会设置为CY_BL_STATE*//*在这里做判断*/if (unlikely(ts->state == CY_BL_STATE)) {complete(&ts->bl_ready);goto out;}
}

退出时候调用

static int cyttsp_soft_reset(struct cyttsp *ts)
{unsigned long timeout;int retval;/* wait for interrupt to set ready completion */reinit_completion(&ts->bl_ready);/*退出的时候会设置为 CY_BL_STATE*/ts->state = CY_BL_STATE;enable_irq(ts->irq);retval = ttsp_send_command(ts, CY_SOFT_RESET_MODE);if (retval)goto out;timeout = wait_for_completion_timeout(&ts->bl_ready,msecs_to_jiffies(CY_DELAY_DFLT * CY_DELAY_MAX));retval = timeout ? 0 : -EIO;out:ts->state = CY_IDLE_STATE;disable_irq(ts->irq);return retval;
}

里面的实现细节

三个函数的流程

init_completion 初始化

我们看init 初始化的代码

static inline void init_completion(struct completion *x)
{x->done = 0;init_waitqueue_head(&x->wait);
}static inline void reinit_completion(struct completion *x)
{x->done = 0;
}

初始化的时候,把done这个变量设置为 0 。

wait_for_completion_timeout 的调用流程

static inline long __sched
do_wait_for_common(struct completion *x,long (*action)(long), long timeout, int state)
{/*如果done是0就跑到if里面去,也就说明我们等的事件还没完成*/if (!x->done) {DECLARE_WAITQUEUE(wait, current);__add_wait_queue_tail_exclusive(&x->wait, &wait);do {if (signal_pending_state(state, current)) {timeout = -ERESTARTSYS;break;}__set_current_state(state);spin_unlock_irq(&x->wait.lock);timeout = action(timeout);/*休眠timeout时间等待*/spin_lock_irq(&x->wait.lock);} while (!x->done && timeout);/*如果事件完成了就提出*/__remove_wait_queue(&x->wait, &wait);if (!x->done)return timeout;}x->done--;return timeout ?: 1;
}

内核里面有非常多这样的小代码,我觉得看这样的代码非常有意思,你需要不断的去揣摩它,品味它。

这段代码的主要工作就是在超时时间内判断done的值已经大于0,然后退出,退出的时候把done 减去1。

总结

文章里面的实例是从一个touch驱动里面提取出来的,它的目的是为了reset触摸屏的时候,确保中断线程已经完全退出了,在中断线程里面有操作touch I2C的操作,如果reset的时候,线程还没有跑完,驱动就会可能收到I2C报错的异常。

 error = request_threaded_irq(ts->irq, NULL, cyttsp_irq,IRQF_TRIGGER_FALLING | IRQF_ONESHOT,pdata->name, ts);

内核完成补丁

这份补丁是用来修复do_wait_for_common 这个函数的,看注释的作用就是用一行代码代替了几行代码。内核专家做了修正,贴出来方便大家加深理解。

Change do_wait_for_common() to use signal_pending_state() instead of
open coding.Signed-off-by: Oleg Nesterov <oleg@xxxxxxxxxx>--- 26-rc2/kernel/sched.c~1_SPS_WAIT_FOR 2008-07-22 18:36:58.000000000 +0400
+++ 26-rc2/kernel/sched.c 2008-07-24 19:54:12.000000000 +0400
@@ -4735,10 +4735,7 @@ do_wait_for_common(struct completion *x,
wait.flags |= WQ_FLAG_EXCLUSIVE;
__add_wait_queue_tail(&x->wait, &wait);
do {
- if ((state == TASK_INTERRUPTIBLE &&
- signal_pending(current)) ||
- (state == TASK_KILLABLE &&
- fatal_signal_pending(current))) {
+ if (signal_pending_state(state, current)) {
timeout = -ERESTARTSYS;
break;
}--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

嵌入式Linux

微信扫描二维码,关注我的公众号

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/467537.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 换行符 常量_6.java常量

Java中常量的分类&#xff1a;整数常量 &#xff1a; 所有整数小数常量 &#xff1a; 所有小数布尔常量 &#xff1a; 只有true和false字符常量 &#xff1a;使用’’引起来的单个字符字符串常量 &#xff1a;使用“”引起来的字符序列&#xff0c;“” 、“a” 、” ”null常…

关于测试

这是5月份和公司同仁做的分享&#xff0c;分享主题是关于测试&#xff0c;是我自己对于测试的一些认知&#xff0c;以及态度的转变。 目录 以怎样的心态面对测试 安全测试贯穿整个软件生命周期 总结 以怎样的心态面对测试 提问大家几个小问题&#xff1a; 你喜欢测试吗&#…

涨疯了,历史总是如此相似

2015年的股市&#xff0c;如果你经历过&#xff0c;那你一定会记忆犹新。最近的股市太猛了&#xff0c;写一篇文章纪念一下~mark上周五&#xff0c;在一个炎热的晚上&#xff0c;我跟4个股神在深圳坪洲的某个火锅店相遇&#xff0c;虽然他们都是富甲一方的富豪&#xff0c;虽然…

java基础语句_【Java基础-Java语言基础】

知识点&#xff1a;1.关键字  2.标识符  3.变量和常量一、关键字1.Java中的关键字有很多一共53个关键字有两个是保留字(java的关键字都是小写的&#xff01;&#xff01;)2.Java中的保留字(1)const  常量&#xff0c;数量(2)goto   转到3.Java的关键字(1)访问修饰符的关…

【BZOJ3514】Codechef MARCH14 GERALD07加强版 LCT+主席树

【BZOJ3514】Codechef MARCH14 GERALD07加强版 Description N个点M条边的无向图&#xff0c;询问保留图中编号在[l,r]的边的时候图中的联通块个数。 Input 第一行四个整数N、M、K、type&#xff0c;代表点数、边数、询问数以及询问是否加密。接下来M行&#xff0c;代表图中的每…

安卓9.0Sensor框架

前言本来如果只是给传感器写个驱动并提供能读取温湿度数据的节点&#xff0c;是一件比较轻松的事情&#xff0c;但是最近上层应用的同事要求我们按照安卓标准的流程来&#xff0c;这样他们就能通过注册一个服务直接读取传感器事件数据了。这样做的好处就是第三方的应用也能正常…

java ognl表达式_java -------ognl表达式入门

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼------------------------------------------------------------------------------------ognl:对象表达式语言&#xff0c;可以用一个表达式快速地访问一个对象的属性&#xff0c;还可以调用对象的方法--------------------------…

Theano 更多示例

Logistic函数 logistic函数的图&#xff0c;其中x在x轴上&#xff0c;s(x)在y轴上。 如果你想对双精度矩阵上的每个元素计算这个函数&#xff0c;这表示你想将这个函数应用到矩阵的每个元素上。 嗯&#xff0c;你是这样做的&#xff1a; xT.dmatrix(x) s1/(1T.exp(-x)) logisti…

SensorKernel层框架分析

接上文安卓9.0Sensor框架前言前面我们已经讲解了sensor框架中的framework到vendor层&#xff0c;这篇文章我们将会讲解kernel层的内容。不过不同的芯片平台&#xff0c;kernel层中的sensor框架是不同的&#xff0c;这里针对的是mt8167s平台。不过这里提醒一下&#xff0c;MTK平…

【习题 5-8 UVA - 230】Borrowers

【链接】 我是链接,点我呀:) 【题意】 在这里输入题意 【题解】 用mapset写个模拟就好。 3个区域 书架、桌子、别人的手上。 其中前两个区域的书都能借出去。 【代码】 #include <bits/stdc.h> using namespace std;set <pair<string, string> > mset1,mse…

java requestparams_java – 如何验证@RequestParams不为空?

我有一个计算器服务,从用户获取操作类型num1和num2.我需要验证用户是否实际输入了这些值,而不是将其留空.RequestMapping(value "/calculate")ResponseBodypublic CalculationResult calculate(RequestParam(name "op") String operation, RequestParam(…

Linux内核LED子系统、请务必看

前言LED子系统你要是说很难嘛&#xff0c;但是它就是控制一些简单的GPIO口&#xff0c;但是你要是说它很简单嘛&#xff0c;但是我也不见得一个初学者很快就能掌握&#xff0c;你如果是刚入门这部分的话&#xff0c;我觉得你还是要去仔细研究下这些驱动。前两天在网上看到一句话…

UVALive 4394 String painter

题目大意&#xff1a;有两个字符串A,B&#xff0c;一次刷可以把A串一段刷成同一个字母&#xff0c;问至少要刷几次才能把A串变成B串。串长≤100。 本来以为是个很简单的区间DP&#xff0c;后来发现直接区间DP是不行的&#xff0c;这玩意有后效性&#xff1a;刷完一整块之后这一…

centos 6.5 安装 lamp 后mysql不能启动_CentOS 6.5 系统 LAMP(Apache+MySQL+PHP)安装步骤

先来解释一下&#xff0c;什么是 LAMP。正如标题所言&#xff0c;LAMP 实际上就是 Linux、Apache、MySQL、PHP 四个名称的缩写&#xff0c;当然最后一个 “P” 还有其他说法是 Perl 或者 Python。不用多说了&#xff0c;本文讲解的就是 Linux、Apache、MySQL、PHP 这四个东西&a…

Redis连接实例

ECS Windows服务器 如果您本地需要通过公网访问 云数据库 Redis&#xff0c;可以在 ECS Windows 云服务器中通过 netsh 进行端口映射实现。 1. 登录 ECS Windows 服务器&#xff0c;在 CMD 执行以下命令。&#xff08;公网地址与 连接地址 请替换 为您的实际地址。&#xff09;…

什么是高内聚,低耦合?

高内聚&#xff0c;低耦合是一个老生常谈的话题&#xff0c;所以拿出来说一下我们在看Linux的一些资料&#xff0c;或者是在面试&#xff0c;又或者跟一个比较牛的大佬讨论技术的时候&#xff0c;可能会听到这个概念。所以&#xff0c;什么是高内聚&#xff0c;低耦合呢&#x…

java 8 兼容_甲骨文限制 Java 9 到 Java 8 的向后兼容性

在开发者们正兴奋着准备把 Java 8 工具包转向 Java 9 的时候&#xff0c;甲骨文的首席执行官提出了要限制两个版本的兼容性。在周一下午 OpenJDK 的邮件列表中的一封邮件中&#xff0c;甲骨文的 Java 平台的首席架构师 Mark Reinhold 指出会对 JDK8 增加更多变化(大概在 2014 年…

Web API 2 入门——创建ASP.NET Web API的帮助页面(谷歌翻译)

在这篇文章中 创建API帮助页面将帮助页面添加到现有项目添加API文档在敞篷下下一步作者&#xff1a;Mike Wasson 创建Web API时&#xff0c;创建帮助页面通常很有用&#xff0c;以便其他开发人员知道如何调用API。您可以手动创建所有文档&#xff0c;但最好尽可能自动生成。 为…

Linux fork的写时复制

这个问题是一个同学在知识星球里面提问的看下面的代码#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/wait.h> #includ…

从单片机工程师的角度看嵌入式Linux

前言 这篇文章简单我们来一起梳理嵌入式Linux的一些知识&#xff0c;方便于一些想跟我一样想要由单片机进阶到嵌入式Linux的朋友做一些参考学习。现在随着嵌入式Linux的教程不断增多&#xff0c;相信应该有不少学单片机的朋友开始折腾这个了吧~嵌入式Linux学哪些东西 1、认识Li…