BUG Fixed:中断上下文申请内存

Table of Contents

今天客户反应我们的驱动在运行中还是会Oops,奇怪了。因为这个驱动我们之前是在我们自己的一个板子上做的,稳定性之类的已经验证过了,虽然现在的运行环境不是我们自己的版本,既然驱动正常加载,怎么还会出问题呢。

下面的是Oops信息:

BUG: scheduling while atomic: swapper/0/0x40010100
Modules linked in: drv

Pid: 0, comm:              swapper
CPU: 0    Not tainted  (2.6.33.5 #19)
PC is at __rcu_process_callbacks+0x68/0x3a0
LR is at __rcu_process_callbacks+0x68/0x3a0
pc : [<c0065820>]    lr : [<c0065820>]    psr: a0000013
sp : c02c3eb0  ip : c02c3eb0  fp : c02c3ed8
r10: c02e2660  r9 : 0000000a  r8 : c02cd5c8
r7 : 00000001  r6 : 00000024  r5 : c02cd708  r4 : c02cd5c8
r3 : 00000002  r2 : c02c2000  r1 : a0000013  r0 : c02cd5c8
Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernel
Control: 0005317f  Table: 21edc000  DAC: 00000017
[<c0027de4>] (show_regs+0x0/0x4c) from [<c0038678>] (__schedule_bug+0x48/0x5c)
r4:c02c3e68
[<c0038630>] (__schedule_bug+0x0/0x5c) from [<c022b964>] (schedule+0x4c/0x2bc)
r4:c02c2000
[<c022b918>] (schedule+0x0/0x2bc) from [<c00386b0>] (__cond_resched+0x24/0x34)
[<c003868c>] (__cond_resched+0x0/0x34) from [<c022bc68>] (_cond_resched+0x30/0x40)
r4:c1d8e180
[<c022bc38>] (_cond_resched+0x0/0x40) from [<c0086890>] (__kmalloc+0x5c/0xe0)
[<c0086834>] (__kmalloc+0x0/0xe0) from [<bf000130>] (init_rx_dma+0x1c/0x98 [drv])
r7:00000000 r6:00000012 r5:c1d8e180 r4:c1d8e180
[<c0062684>] (handle_IRQ_event+0x0/0x114) from [<c00649c8>] (handle_level_irq+0xf0/0x10c)
r8:c02cd5c8 r7:00000001 r6:00000017 r5:00000017 r4:c02ca028
[<c00648d8>] (handle_level_irq+0x0/0x10c) from [<c0026074>] (asm_do_IRQ+0x74/0xa0)
r5:c02c3f50 r4:00000017
[<c0026000>] (asm_do_IRQ+0x0/0xa0) from [<c0026a68>] (__irq_svc+0x28/0x60)

先google下吧,关键字"BUG: scheduling while atomic",在这里找到的答案。原来malloc内存时,参数GFP_KERNEL是可能会阻塞的,所以不能在中断上下文使用GFP_KERNEL申请内存,而只能使用GFP_ATOMIC。

详见LDD CH8 Allocating Memory

The most commonly used flag, GFP_KERNEL, means that the allocation (internally performed by calling, eventually, __get_free_pages, which is the source of the GFP_ prefix) is performed on behalf of a process running in kernel space. In other words, this means that the calling function is executing a system call on behalf of a process. Using GFP_KERNEL means that kmalloc can put the current process to sleep waiting for a page when called in low-memory situations. A function that allocates memory using GFP_KERNEL must, therefore, be reentrant and cannot be running in atomic context. While the current process sleeps, the kernel takes proper action to locate some free memory, either by flushing buffers to disk or by swapping out memory from a user process.

  • GFP_ATOMIC
    Used to allocate memory from interrupt handlers and other code outside of a process context. Never sleeps.
  • GFP_KERNEL
    Normal allocation of kernel memory. May sleep.
  • GFP_USER
    Used to allocate memory for user-space pages; it may sleep.
  • GFP_HIGHUSER
    Like GFP_USER, but allocates from high memory, if any. High memory is described in the next subsection.
  • GFP_NOIO
  • GFP_NOFS
    These flags function like GFP_KERNEL, but they add restrictions on what the kernel can do to satisfy the request. A GFP_NOFS allocation is not allowed to perform any filesystem calls, while GFP_NOIO disallows the initiation of any I/O at all.
    They are used primarily in the filesystem and virtual memory code where an allocation may be allowed to sleep, but recursive filesystem calls would be a bad idea.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.