"scheduling while atomic: x/y/z"
其中 x 為行程的名稱 (current->comm)
y 為16進制的 preempt_count
z 為 PID
出現此訊息時,表示目前的 kernel task 是一個不可被中斷的行程,但卻被排程進入休眠。
以下為核心列印該錯誤訊息的程式片段:
/*
* schedule() is the main scheduler function.
*/
asmlinkage void __sched schedule(void)
{
long *switch_count;
task_t *prev, *next;
runqueue_t *rq;
prio_array_t *array;
struct list_head *queue;
unsigned long long now;
unsigned long run_time;
int cpu, idx;
/*
* 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 (likely(!current->exit_state)) {
if (unlikely(in_atomic())) {
printk(KERN_ERR "scheduling while atomic: "
"%s/0x%08x/%d\n",
current->comm, preempt_count(), current->pid);
dump_stack();
}
}
profile_hit(SCHED_PROFILING, __builtin_return_address(0));
... /* 以下略 */
}
定義於 kernel/sched.c
#if defined(CONFIG_PREEMPT) && !defined(CONFIG_PREEMPT_BKL)
# define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked())
#else
# define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != 0)
#endif
定義於 include/linux/hardirq.h
#define preempt_count() (current_thread_info()->preempt_count)
定義於 include/linux/preempt.h
當核心要進行 schedule 時,會先檢查目前是否為不可中斷的行程(in_atomic)
若為真,則印出 "scheduling while atomic" 的訊息,表示此時不應該做排程
而 in_atomic 則是判斷 kernel preemption 是否為關閉的狀態
也就是關閉 preemption 是為了讓行程能夠不被打斷的執行,直到完成其工作
換言之,開啟 preemption 就允許其他行程取代目前行程,故可進行排程
以下的程式片段在定義 CONFIG_PREEMPT 的核心會造成 "scheduling while atomic" 錯誤:
(若未定義 CONFIG_PREEMPT 就不是 in_atomic 的程序)
struct semaphore _sem;
spinlock_t _lock;
spin_lock_init( &_lock );
sema_init(&_sem, 0);
spin_lock( &_lock );
down_interruptible( &_sem ); /* 在 Spin lock 中休眠 */
spin_unlock( &_lock );
2010年3月1日 星期一
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言