【问题排查】implicit declaration of function ‘interruptible_sleep_on‘处理

当前内核版本:3.18.y

源代码对应的内核版本:2.6.37


问题

移植代码的时候报错:

341:3: error: implicit declaration of function 'interruptible_sleep_on' [-Werror=implicit-function-declaration]
   interruptible_sleep_on (&tty->read_wait);
   ^

一样是比较两个版本的内核源码,发现interruptible_sleep_on这个函数在新的内核中已经被去掉了。

单纯的百度搜索不到任何有用的信息...还有没有什么办法?


思路

这里提供一个办法,可以尝试在官方的内核源码的git提交日志中,搜索一些有用的信息。

Ps:这里前提肯定是用git下载linux内核源码了,需要对git有一定的熟悉度。

附上linux源码官网:https://www.kernel.org/

【开发工具】【git】通过关键字搜索对应的git提交日志


分析

通过"git log --grep=interruptible_sleep_on"命令,找到git提交日志,并查到相关信息:

commit 76ae0536ddc0aa576f2aac11f0f82d0fd60b522c
Author: Arnd Bergmann <arnd@arndb.de>
Date:   Wed Feb 26 12:01:49 2014 +0100

    parport: fix interruptible_sleep_on race
    
    The interruptible_sleep_on function is can still lead to the
    deadlock mentioned in the comment above the caller, and we want
    to remove it soon, so replace it now with the race-free
    wait_event_interruptible.
    
    Signed-off-by: Arnd Bergmann <arnd@arndb.de>
    Cc: Andrew Morton <akpm@osdl.org>
    Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

根据提交日志上的内容,明白了原因是interruptible_sleep_on函数仍然会导致死锁,因此被删除了,解决办法是立即使用无竞争的wait_event_interruptible替换它。

对应的替换函数:

【include/linux/wait.h】
#define __wait_event_interruptible(wq, condition)			\
	___wait_event(wq, condition, TASK_INTERRUPTIBLE, 0, 0,		\
		      schedule())

/**
 * wait_event_interruptible - sleep until a condition gets true
 * @wq: the waitqueue to wait on
 * @condition: a C expression for the event to wait for
 *
 * The process is put to sleep (TASK_INTERRUPTIBLE) until the
 * @condition evaluates to true or a signal is received.
 * The @condition is checked each time the waitqueue @wq is woken up.
 *
 * wake_up() has to be called after changing any variable that could
 * change the result of the wait condition.
 *
 * The function will return -ERESTARTSYS if it was interrupted by a
 * signal and 0 if @condition evaluated to true.
 */
#define wait_event_interruptible(wq, condition)				\
({									\
	int __ret = 0;							\
	if (!(condition))						\
		__ret = __wait_event_interruptible(wq, condition);	\
	__ret;								\
})

再看看interruptible_sleep_on函数的定义,做一个比较:

void __sched interruptible_sleep_on(wait_queue_head_t *q)
{
	sleep_on_common(q, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
}

Ps:新的wait_event_interruptible函数多了一个参数...就需要我们实际替换的时候,注意更多地方。


实例

讲下我实际的代码中是如何替换的。

私有结构体中添加成员,对应condition。
	bool              write_done;
	wait_queue_head_t write_wait;

在wake_up_interruptible函数之前设置write_done:
	trans->write_done = true;
	wake_up_interruptible (&trans->write_wait);
 
 在原先的interruptible_sleep_on函数处,替换为wait_event_interruptible:
     trans->write_done = false;
     wait_event_interruptible(trans->write_wait, trans->write_done);

搞定~

相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页