我在Linux下使用hrtimers时遇到了一些问题。我正在使用hrtimer如下:
hrtimer_init(&timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
timer.function = timer_master;
hrtimer_start(&timer, ktime_set(0, 50*1000000), HRTIMER_MODE_REL); //start tx 50ms after init
并在timer_master处理程序中:
hrtimer_forward_now(handle, ktime_set(0, 2400 * 1000));
当CPU尝试运行hrtimer_forward_now(handle,ktime_set(0,2400 * 1000))时; 我得到了以下calltrace:
[K 55.936212] ------------[ cut here ]------------
[K 55.941110] WARNING: at kernel/irq/handle.c:130 handle_irq_event_percpu+0x70/0x18c()
[K 55.949028] irq 5 handler ixp4xx_timer_interrupt+0x0/0x30 enabled interrupts
[K 55.956230] Modules linked in: ixp4xx_crypto ftdi_sio sg usbserial cdc_acm ebt_redirect ebt_mark ebt_vlan ebt_stp ebt_pkttype ebt_mark_m ebt_limit ebt_among ebt_802_3 ebtable_nat ebtable_filter
[K 56.038593] Backtrace:
[K 56.041185] [<c000bc84>] (dump_backtrace+0x0/0x114) from [<c01e8c68>] (dump_stack+0x18/0x1c)
[K 56.049847] r6:00000082 r5:c0248347 r4:c0299e80 r3:60000013
[K 56.055698] [<c01e8c50>] (dump_stack+0x0/0x1c) from [<c001550c>] (warn_slowpath_common+0x54/0x6c)
[K 56.064766] [<c00154b8>] (warn_slowpath_common+0x0/0x6c) from [<c00155c8>] (warn_slowpath_fmt+0x38/0x40)
[K 56.074432] r8:00000000 r7:00000000 r6:c02a8c40 r5:00000005 r4:c029d920
[K 56.081183] r3:00000009
[K 56.083937] [<c0015590>] (warn_slowpath_fmt+0x0/0x40) from [<c0044dd0>] (handle_irq_event_percpu+0x70/0x18c)
[K 56.093959] r3:00000005 r2:c024835b
[K 56.097681] [<c0044d60>] (handle_irq_event_percpu+0x0/0x18c) from [<c0044f1c>] (handle_irq_event+0x30/0x40)
[K 56.107623] [<c0044eec>] (handle_irq_event+0x0/0x40) from [<c00472e4>] (handle_level_irq+0xb4/0xc4)
[K 56.116851] r4:c02a8c40 r3:00020000
[K 56.120607] [<c0047230>] (handle_level_irq+0x0/0xc4) from [<c0044720>] (generic_handle_irq+0x30/0x4c)
[K 56.130011] r4:00000005 r3:c0047230
[K 56.133730] [<c00446f0>] (generic_handle_irq+0x0/0x4c) from [<c000992c>] (handle_IRQ+0x68/0x8c)
[K 56.142619] [<c00098c4>] (handle_IRQ+0x0/0x8c) from [<c00081d0>] (asm_do_IRQ+0x10/0x14)
[K 56.150791] r5:60000013 r4:c0009a8c
[K 56.154506] [<c00081c0>] (asm_do_IRQ+0x0/0x14) from [<c0008c70>] (__irq_svc+0x30/0xa0)
[K 56.162624] Exception stack(0xc0299f40 to 0xc0299f88)
[K 56.167830] 9f40: 00000000 c02aa630 c0299f88 60000013 c0298000 c029d0a4 c02b3ae8 c029d09c
[K 56.176193] 9f60: 00004000 69054041 002926a0 c0299f94 c0299f98 c0299f88 c0009c30 c0009a8c
[K 56.184546] 9f80: 60000013 ffffffff
[K 56.188168] [<c0009a64>] (default_idle+0x0/0x2c) from [<c0009c30>] (cpu_idle+0x64/0xac)
[K 56.196382] [<c0009bcc>] (cpu_idle+0x0/0xac) from [<c01e373c>] (rest_init+0x60/0x78)
[K 56.204292] r6:c0293f4c r5:c02b3ab4 r4:c029a0b0 r3:c029c458
[K 56.210133] [<c01e36dc>] (rest_init+0x0/0x78) from [<c027a79c>] (start_kernel+0x2a4/0x2f8)
[K 56.218628] [<c027a4f8>] (start_kernel+0x0/0x2f8) from [<00008040>] (0x8040)
[K 56.225831] ---[ end trace a126a312e2dce91f ]---
编辑:hrtimer的处理程序:
static enum hrtimer_restart timer_master(struct hrtimer *handle)
{
unsigned long flags;
if (st == t0h) {
st = t1;
hrtimer_forward_now(handle, ktime_set(0, 2400 * 1000));
} else if (st == t1) {
st = t2;
hrtimer_forward_now(handle, ktime_set(0, wdev->dwstream_timeslot * 1000));
proc1((unsigned long)wdev->dev);
} else if (st == t2) {
st = t0h;
hrtimer_forward_now(handle, ktime_set(0, (wdev->upstream_timeslot + 2 * delay)*1000));
}
return HRTIMER_RESTART;
}
和简化的proc1:
spin_lock_irq(&lock)
(...)
spin_unlock_irq(&lock)
看起来像spin_lock_irq()会弄得一团糟,但为什么呢?
我使用的是单核CPU:Intel IXP435。 谁知道我做错了什么?