BUG: scheduling while atomic 分析【转】
本文转载自:https://blog.csdn.net/cfy_phonex/article/details/12090943
遇到一个典型的schedule问题。
- <3>[26578.636839] C1 [ swapper/1] BUG: scheduling while atomic: swapper/1/0/0x00000002
- <6>[26578.636869] C0 [ kworker/u:1] CPU1 is up
- <4>[26578.636900] C1 [ swapper/1] Modules linked in: bcm15500_i2c_ts
- <4>[26578.636961] C1 [ swapper/1] [<c00146d0>] (unwind_backtrace+0x0/0x11c) from [<c0602684>] (__schedule+0x70/0x6e0)
- <4>[26578.636991] C1 [ swapper/1] [<c0602684>] (__schedule+0x70/0x6e0) from [<c06030ec>] (schedule_preempt_disabled+0x14/0x20)
- <4>[26578.637052] C1 [ swapper/1] [<c06030ec>] (schedule_preempt_disabled+0x14/0x20) from [<c000f05c>] (cpu_idle+0xf0/0x104)
- <4>[26578.637083] C1 [ swapper/1] [<c000f05c>] (cpu_idle+0xf0/0x104) from [<c05e98e0>] (cpu_die+0x2c/0x5c)
- <3>[26578.637510] C1 [ swapper/1] BUG: scheduling while atomic: swapper/1/0/0x00000002
- <4>[26578.637510] C1 [ swapper/1] Modules linked in: bcm15500_i2c_ts
- <4>[26578.637602] C1 [ swapper/1] [<c00146d0>] (unwind_backtrace+0x0/0x11c) from [<c0602684>] (__schedule+0x70/0x6e0)
- <4>[26578.637663] C1 [ swapper/1] [<c0602684>] (__schedule+0x70/0x6e0) from [<c06030ec>] (schedule_preempt_disabled+0x14/0x20)
- <4>[26578.637724] C1 [ swapper/1] [<c06030ec>] (schedule_preempt_disabled+0x14/0x20) from [<c000f05c>] (cpu_idle+0xf0/0x104)
- <4>[26578.637754] C1 [ swapper/1] [<c000f05c>] (cpu_idle+0xf0/0x104) from [<c05e98e0>] (cpu_die+0x2c/0x5c)
- <3>[26578.648069] C1 [ swapper/1] BUG: scheduling while atomic: swapper/1/0/0x00000002
查看源代码
- /*
- * __schedule() is the main scheduler function.
- */
- static void __sched __schedule(void)
- {
- struct task_struct *prev, *next;
- unsigned long *switch_count;
- struct rq *rq;
- int cpu;
- need_resched:
- preempt_disable();
- cpu = smp_processor_id();
- rq = cpu_rq(cpu);
- rcu_note_context_switch(cpu);
- prev = rq->curr;
- schedule_debug(prev);
- ....
- }
- /*
- * Print scheduling while atomic bug:
- */
- static noinline void __schedule_bug(struct task_struct *prev)
- {
- if (oops_in_progress)
- return;
- printk(KERN_ERR "BUG: scheduling while atomic: %s/%d/0x%08x\n",
- prev->comm, prev->pid, preempt_count());
- debug_show_held_locks(prev);
- print_modules();
- if (irqs_disabled())
- print_irqtrace_events(prev);
- dump_stack();
- }
- /*
- * Various schedule()-time debugging checks and statistics:
- */
- static inline void schedule_debug(struct task_struct *prev)
- {
- /*
- * Test if we are atomic. Since do_exit() needs to call into
- * schedule() atomically, we ignore that path for now.
- * Otherwise, whine if we are scheduling when we should not be.
- */
- if (unlikely(in_atomic_preempt_off() && !prev->exit_state))
- __schedule_bug(prev);
- rcu_sleep_check();
- profile_hit(SCHED_PROFILING, __builtin_return_address(0));
- schedstat_inc(this_rq(), sched_count);
- }
可以看出, 满足如下条件将会打印该出错信息
unlikely(in_atomic_preempt_off() && !prev->exit_state
为0表示TASK_RUNNING状态,当前进程在运行; 并且处于原子状态,,那么就不能切换给其它的进程
Linux/include/linux/sched.h
- /*
- * Task state bitmask. NOTE! These bits are also
- * encoded in fs/proc/array.c: get_task_state().
- *
- * We have two separate sets of flags: task->state
- * is about runnability, while task->exit_state are
- * about the task exiting. Confusing, but this way
- * modifying one set can't modify the other one by
- * mistake.
- */
- #define TASK_RUNNING 0
- #define TASK_INTERRUPTIBLE 1
- #define TASK_UNINTERRUPTIBLE 2
- #define __TASK_STOPPED 4
- #define __TASK_TRACED 8
- /* in tsk->exit_state */
- #define EXIT_ZOMBIE 16
- #define EXIT_DEAD 32
- /* in tsk->state again */
- #define TASK_DEAD 64
- #define TASK_WAKEKILL 128
- #define TASK_WAKING 256
- #define TASK_STATE_MAX 512
- kernel/include/linux/hardirq.h
- #if defined(CONFIG_PREEMPT_COUNT)
- # define PREEMPT_CHECK_OFFSET 1
- #else
- # define PREEMPT_CHECK_OFFSET 0
- #endif
- /*
- * Are we running in atomic context? WARNING: this macro cannot
- * always detect atomic context; in particular, it cannot know about
- * held spinlocks in non-preemptible kernels. Thus it should not be
- * used in the general case to determine whether sleeping is possible.
- * Do not use in_atomic() in driver code.
- */
- #define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != 0)
- /*
- * Check whether we were atomic before we did preempt_disable():
- * (used by the scheduler, *after* releasing the kernel lock)
- */
- #define in_atomic_preempt_off() \
- ((preempt_count() & ~PREEMPT_ACTIVE) != PREEMPT_CHECK_OFFSET)
结论整理
linux内核打印"BUG: scheduling while atomic"和"bad: scheduling from the idle thread"错误的时候,
通常是在中断处理函数中调用了可以休眠的函数,如semaphore,mutex,sleep之类的可休眠的函数,
而linux内核要求在中断处理的时候,不允许系统调度,不允许抢占,要等到中断处理完成才能做其他事情。
因此,要充分考虑中断处理的时间,一定不能太久。
另外一个能产生此问题的是在idle进程里面,做了不该做的事情。现在Linux用于很多手持式设备,为了降低功耗,
通常的作法是在idle进程里面降低CPU或RAM的频率、关闭一些设备等等。要保证这些动作的原子性才能确保
不发生"bad: scheduling from the idle thread"这样的错误!
禁止内核抢占是指内核不会主动的抢占你的process,但是现在是你在自己的程序中主动call schedule(),
kernel并不能阻止你这么作。
Scheduling while atomic" means that a thread has called schedule() during an operation which is supposed to be atomic (ie uninterrupted).
- 190 NOTE: ***** WARNING *****
- 191 NEVER SLEEP IN A COMPLETION HANDLER. These are normally called
- 192 during hardware interrupt processing. If you can, defer substantial
- 193 work to a tasklet (bottom half) to keep system latencies low. You'll
- 194 probably need to use spinlocks to protect data structures you manipulate
- 195 in completion handlers.
- GFP_ATOMIC is used when
- (a) you are inside a completion handler, an interrupt, bottom half, tasklet or timer, or
- (b) you are holding a spinlock or rwlock (does not apply to semaphores), or
- (c) current->state != TASK_RUNNING, this is the case only after you've changed it.
BUG: scheduling while atomic 分析【转】的更多相关文章
- linux内核打印"BUG: scheduling while atomic
linux内核打印"BUG: scheduling while atomic"和"bad: scheduling from the idle thread"错误 ...
- BUG: scheduling while atomic: events/0/4/总结
对于Linux内核来说,Oops就意外着内核出了异常,此时会将产生异常时CPU的状态,出错的指令地址.数据地址及其他寄存器,函数调用的顺序甚至是栈里面的内容都打印出来,然后根据异常的严重程度来决定下一 ...
- Android BroadcastAnyWhere(Google Bug 17356824)漏洞具体分析
Android BroadcastAnyWhere(Google Bug 17356824)漏洞具体分析 作者:简行(又名 低端码农) 继上次Android的LaunchAnyWhere组件安全漏洞后 ...
- 线上BUG:MySQL死锁分析实战
原文链接:线上BUG:MySQL死锁分析实战 1 线上告警 我们不需要关注截图中得其他信息,只要能看到打印得org.springframework.dao.DeadlockLoserDataAcces ...
- [技术讨论]关于前几天公布的京东bug上的问题分析
1. 起因 前两天我公布了一个京东微信端截取到的三张图.并简单阐述了这三张图中的bug发现过程: 有朋友的评价是图中这种,可实际上.他应该是没有看出来这个bug代表的内容有多少.今天心血来潮决定具体 ...
- 一个友盟BUG的思考和分析:Invalid update
1.友盟错误信息 Invalid update: invalid number of rows . The number of rows contained ) must be equal to th ...
- BUG的定位与分析思路
一般来说bug大多数存在于3个模块: 1.前台界面,包括界面的显示,兼容性,数据提交的判断,页面的跳转等等,这些bug基本都是一眼可见的,不太需要定位,当然也不排除一些特殊情况,本身数据传过来的时候就 ...
- scheduling while atomic 出现的错误
产生这种情况的原因: 1.当中断发生时,出现了调度做法, 2.另一个是spin_lock 里调用sleep, 让出调度, 另外线程又进行spin_lock, 导致死锁. 相关问题的链接 1.为 ...
- scheduling while atomic和bad: scheduling from the idle thread(转)
https://blog.csdn.net/shanzhizi/article/details/22949121 https://blog.csdn.net/wwwtovvv/article/deta ...
随机推荐
- Java安全API
java提供了完整的密码学API,我们可以结合密码学相关的概念来系统的学习这些API. 1.密码学简介(crypto) 密码学通俗来说就是研究如何对信息进行加密和破密,如果不是专门研究信息安全,通常我 ...
- iOS-如何在项目中使用CocoaPods
1.打开终端. 2.将项目文件夹拖入到cd空格 后面. 3.回车,看下现在的路径是. 4.我们输入vim podfile回车,建立Podfile文件. 5.进到这个界面,我们再按i编辑--你会看到下面 ...
- 认识tornado(一)
tornado 源码包中 demos 目录下包含一些示例程序,就从最简单的 helloworld.py 来看一个 tornado 应用程序的代码结构. 完整的实例程序如下: 01 #!/usr/bin ...
- c语言加密算法头文件下载(base64、md5、sha1)
1.base64 网上有一份开头就是 // Encoding lookup table char base64encode_lut[] = { 的base64.h, 在loadrunner中加密有b ...
- Zend Studio 中创建简单的phpfile模板和xhtml类phpfile模板
<!--简单的phpfile模板,带有创建时间和作者--><?php/*** ==============================================* @dat ...
- 使用CocoaPods配置管理开源项目
今天从GitHub下载了MMProcessHUB,想先看看demo,但是不巧的是作者是用CocoaPods配置的,需要安装CocoaPods,CocoaPods是一个第三方的类库管理工具.找了一篇很详 ...
- Python菜鸟之路:Django 文件上传的几种方式
方式一:通过form表单中,html input 标签的“file”完成 # 前端代码uoload.html <form method="post" action=" ...
- django 表单系统 之 forms.ModelForm
继承forms.ModelForm类实现django的表单系统 有时,我们在前端定义的<form>表单和后端定义的model结构基本上是一样的,那么我们可以直接在后端定义model后,定义 ...
- Vue(3)- 安装脚手架、过滤器、生命周期的钩子函数、vue-router基本使用
一.安装脚手架 1.下载node.js,本文下载版本为node-v8.12.0-x64.msi,一键式安装. 2.安装完成后,打开终端,输入node,可进入node环境(两次ctrl+c退出),如下图 ...
- 重读C库之宏定义
1.如何编写头文件.h? //file--func1.h #ifndef __FUNC1_H //__func1_h //可小写可大写 #define __FUNC1_H //__func1_h .. ...