diff options
-rw-r--r-- | drivers/parport/ieee1284.c | 4 | ||||
-rw-r--r-- | fs/aio.c | 5 | ||||
-rw-r--r-- | include/linux/poison.h | 7 | ||||
-rw-r--r-- | include/linux/timer.h | 23 | ||||
-rw-r--r-- | kernel/timer.c | 153 | ||||
-rw-r--r-- | lib/Kconfig.debug | 8 |
6 files changed, 187 insertions, 13 deletions
diff --git a/drivers/parport/ieee1284.c b/drivers/parport/ieee1284.c index 54a6ef72906e..0338b0912674 100644 --- a/drivers/parport/ieee1284.c +++ b/drivers/parport/ieee1284.c | |||
@@ -76,7 +76,7 @@ int parport_wait_event (struct parport *port, signed long timeout) | |||
76 | semaphore. */ | 76 | semaphore. */ |
77 | return 1; | 77 | return 1; |
78 | 78 | ||
79 | init_timer (&timer); | 79 | init_timer_on_stack(&timer); |
80 | timer.expires = jiffies + timeout; | 80 | timer.expires = jiffies + timeout; |
81 | timer.function = timeout_waiting_on_port; | 81 | timer.function = timeout_waiting_on_port; |
82 | port_from_cookie[port->number % PARPORT_MAX] = port; | 82 | port_from_cookie[port->number % PARPORT_MAX] = port; |
@@ -88,6 +88,8 @@ int parport_wait_event (struct parport *port, signed long timeout) | |||
88 | /* Timed out. */ | 88 | /* Timed out. */ |
89 | ret = 1; | 89 | ret = 1; |
90 | 90 | ||
91 | destroy_timer_on_stack(&timer); | ||
92 | |||
91 | return ret; | 93 | return ret; |
92 | } | 94 | } |
93 | 95 | ||
@@ -1078,9 +1078,7 @@ static void timeout_func(unsigned long data) | |||
1078 | 1078 | ||
1079 | static inline void init_timeout(struct aio_timeout *to) | 1079 | static inline void init_timeout(struct aio_timeout *to) |
1080 | { | 1080 | { |
1081 | init_timer(&to->timer); | 1081 | setup_timer_on_stack(&to->timer, timeout_func, (unsigned long) to); |
1082 | to->timer.data = (unsigned long)to; | ||
1083 | to->timer.function = timeout_func; | ||
1084 | to->timed_out = 0; | 1082 | to->timed_out = 0; |
1085 | to->p = current; | 1083 | to->p = current; |
1086 | } | 1084 | } |
@@ -1213,6 +1211,7 @@ retry: | |||
1213 | if (timeout) | 1211 | if (timeout) |
1214 | clear_timeout(&to); | 1212 | clear_timeout(&to); |
1215 | out: | 1213 | out: |
1214 | destroy_timer_on_stack(&to.timer); | ||
1216 | return i ? i : ret; | 1215 | return i ? i : ret; |
1217 | } | 1216 | } |
1218 | 1217 | ||
diff --git a/include/linux/poison.h b/include/linux/poison.h index a9c31be7052c..9f31683728fd 100644 --- a/include/linux/poison.h +++ b/include/linux/poison.h | |||
@@ -10,6 +10,13 @@ | |||
10 | #define LIST_POISON1 ((void *) 0x00100100) | 10 | #define LIST_POISON1 ((void *) 0x00100100) |
11 | #define LIST_POISON2 ((void *) 0x00200200) | 11 | #define LIST_POISON2 ((void *) 0x00200200) |
12 | 12 | ||
13 | /********** include/linux/timer.h **********/ | ||
14 | /* | ||
15 | * Magic number "tsta" to indicate a static timer initializer | ||
16 | * for the object debugging code. | ||
17 | */ | ||
18 | #define TIMER_ENTRY_STATIC ((void *) 0x74737461) | ||
19 | |||
13 | /********** mm/slab.c **********/ | 20 | /********** mm/slab.c **********/ |
14 | /* | 21 | /* |
15 | * Magic nums for obj red zoning. | 22 | * Magic nums for obj red zoning. |
diff --git a/include/linux/timer.h b/include/linux/timer.h index 979fefdeb862..d4ba79248a27 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/list.h> | 4 | #include <linux/list.h> |
5 | #include <linux/ktime.h> | 5 | #include <linux/ktime.h> |
6 | #include <linux/stddef.h> | 6 | #include <linux/stddef.h> |
7 | #include <linux/debugobjects.h> | ||
7 | 8 | ||
8 | struct tvec_base; | 9 | struct tvec_base; |
9 | 10 | ||
@@ -25,6 +26,7 @@ struct timer_list { | |||
25 | extern struct tvec_base boot_tvec_bases; | 26 | extern struct tvec_base boot_tvec_bases; |
26 | 27 | ||
27 | #define TIMER_INITIALIZER(_function, _expires, _data) { \ | 28 | #define TIMER_INITIALIZER(_function, _expires, _data) { \ |
29 | .entry = { .prev = TIMER_ENTRY_STATIC }, \ | ||
28 | .function = (_function), \ | 30 | .function = (_function), \ |
29 | .expires = (_expires), \ | 31 | .expires = (_expires), \ |
30 | .data = (_data), \ | 32 | .data = (_data), \ |
@@ -38,6 +40,17 @@ extern struct tvec_base boot_tvec_bases; | |||
38 | void init_timer(struct timer_list *timer); | 40 | void init_timer(struct timer_list *timer); |
39 | void init_timer_deferrable(struct timer_list *timer); | 41 | void init_timer_deferrable(struct timer_list *timer); |
40 | 42 | ||
43 | #ifdef CONFIG_DEBUG_OBJECTS_TIMERS | ||
44 | extern void init_timer_on_stack(struct timer_list *timer); | ||
45 | extern void destroy_timer_on_stack(struct timer_list *timer); | ||
46 | #else | ||
47 | static inline void destroy_timer_on_stack(struct timer_list *timer) { } | ||
48 | static inline void init_timer_on_stack(struct timer_list *timer) | ||
49 | { | ||
50 | init_timer(timer); | ||
51 | } | ||
52 | #endif | ||
53 | |||
41 | static inline void setup_timer(struct timer_list * timer, | 54 | static inline void setup_timer(struct timer_list * timer, |
42 | void (*function)(unsigned long), | 55 | void (*function)(unsigned long), |
43 | unsigned long data) | 56 | unsigned long data) |
@@ -47,6 +60,15 @@ static inline void setup_timer(struct timer_list * timer, | |||
47 | init_timer(timer); | 60 | init_timer(timer); |
48 | } | 61 | } |
49 | 62 | ||
63 | static inline void setup_timer_on_stack(struct timer_list *timer, | ||
64 | void (*function)(unsigned long), | ||
65 | unsigned long data) | ||
66 | { | ||
67 | timer->function = function; | ||
68 | timer->data = data; | ||
69 | init_timer_on_stack(timer); | ||
70 | } | ||
71 | |||
50 | /** | 72 | /** |
51 | * timer_pending - is a timer pending? | 73 | * timer_pending - is a timer pending? |
52 | * @timer: the timer in question | 74 | * @timer: the timer in question |
@@ -164,5 +186,4 @@ unsigned long __round_jiffies_relative(unsigned long j, int cpu); | |||
164 | unsigned long round_jiffies(unsigned long j); | 186 | unsigned long round_jiffies(unsigned long j); |
165 | unsigned long round_jiffies_relative(unsigned long j); | 187 | unsigned long round_jiffies_relative(unsigned long j); |
166 | 188 | ||
167 | |||
168 | #endif | 189 | #endif |
diff --git a/kernel/timer.c b/kernel/timer.c index f3d35d4ea42e..ceacc6626572 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
@@ -320,14 +320,130 @@ static void timer_stats_account_timer(struct timer_list *timer) | |||
320 | static void timer_stats_account_timer(struct timer_list *timer) {} | 320 | static void timer_stats_account_timer(struct timer_list *timer) {} |
321 | #endif | 321 | #endif |
322 | 322 | ||
323 | /** | 323 | #ifdef CONFIG_DEBUG_OBJECTS_TIMERS |
324 | * init_timer - initialize a timer. | 324 | |
325 | * @timer: the timer to be initialized | 325 | static struct debug_obj_descr timer_debug_descr; |
326 | * | 326 | |
327 | * init_timer() must be done to a timer prior calling *any* of the | 327 | /* |
328 | * other timer functions. | 328 | * fixup_init is called when: |
329 | * - an active object is initialized | ||
329 | */ | 330 | */ |
330 | void init_timer(struct timer_list *timer) | 331 | static int timer_fixup_init(void *addr, enum debug_obj_state state) |
332 | { | ||
333 | struct timer_list *timer = addr; | ||
334 | |||
335 | switch (state) { | ||
336 | case ODEBUG_STATE_ACTIVE: | ||
337 | del_timer_sync(timer); | ||
338 | debug_object_init(timer, &timer_debug_descr); | ||
339 | return 1; | ||
340 | default: | ||
341 | return 0; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | * fixup_activate is called when: | ||
347 | * - an active object is activated | ||
348 | * - an unknown object is activated (might be a statically initialized object) | ||
349 | */ | ||
350 | static int timer_fixup_activate(void *addr, enum debug_obj_state state) | ||
351 | { | ||
352 | struct timer_list *timer = addr; | ||
353 | |||
354 | switch (state) { | ||
355 | |||
356 | case ODEBUG_STATE_NOTAVAILABLE: | ||
357 | /* | ||
358 | * This is not really a fixup. The timer was | ||
359 | * statically initialized. We just make sure that it | ||
360 | * is tracked in the object tracker. | ||
361 | */ | ||
362 | if (timer->entry.next == NULL && | ||
363 | timer->entry.prev == TIMER_ENTRY_STATIC) { | ||
364 | debug_object_init(timer, &timer_debug_descr); | ||
365 | debug_object_activate(timer, &timer_debug_descr); | ||
366 | return 0; | ||
367 | } else { | ||
368 | WARN_ON_ONCE(1); | ||
369 | } | ||
370 | return 0; | ||
371 | |||
372 | case ODEBUG_STATE_ACTIVE: | ||
373 | WARN_ON(1); | ||
374 | |||
375 | default: | ||
376 | return 0; | ||
377 | } | ||
378 | } | ||
379 | |||
380 | /* | ||
381 | * fixup_free is called when: | ||
382 | * - an active object is freed | ||
383 | */ | ||
384 | static int timer_fixup_free(void *addr, enum debug_obj_state state) | ||
385 | { | ||
386 | struct timer_list *timer = addr; | ||
387 | |||
388 | switch (state) { | ||
389 | case ODEBUG_STATE_ACTIVE: | ||
390 | del_timer_sync(timer); | ||
391 | debug_object_free(timer, &timer_debug_descr); | ||
392 | return 1; | ||
393 | default: | ||
394 | return 0; | ||
395 | } | ||
396 | } | ||
397 | |||
398 | static struct debug_obj_descr timer_debug_descr = { | ||
399 | .name = "timer_list", | ||
400 | .fixup_init = timer_fixup_init, | ||
401 | .fixup_activate = timer_fixup_activate, | ||
402 | .fixup_free = timer_fixup_free, | ||
403 | }; | ||
404 | |||
405 | static inline void debug_timer_init(struct timer_list *timer) | ||
406 | { | ||
407 | debug_object_init(timer, &timer_debug_descr); | ||
408 | } | ||
409 | |||
410 | static inline void debug_timer_activate(struct timer_list *timer) | ||
411 | { | ||
412 | debug_object_activate(timer, &timer_debug_descr); | ||
413 | } | ||
414 | |||
415 | static inline void debug_timer_deactivate(struct timer_list *timer) | ||
416 | { | ||
417 | debug_object_deactivate(timer, &timer_debug_descr); | ||
418 | } | ||
419 | |||
420 | static inline void debug_timer_free(struct timer_list *timer) | ||
421 | { | ||
422 | debug_object_free(timer, &timer_debug_descr); | ||
423 | } | ||
424 | |||
425 | static void __init_timer(struct timer_list *timer); | ||
426 | |||
427 | void init_timer_on_stack(struct timer_list *timer) | ||
428 | { | ||
429 | debug_object_init_on_stack(timer, &timer_debug_descr); | ||
430 | __init_timer(timer); | ||
431 | } | ||
432 | EXPORT_SYMBOL_GPL(init_timer_on_stack); | ||
433 | |||
434 | void destroy_timer_on_stack(struct timer_list *timer) | ||
435 | { | ||
436 | debug_object_free(timer, &timer_debug_descr); | ||
437 | } | ||
438 | EXPORT_SYMBOL_GPL(destroy_timer_on_stack); | ||
439 | |||
440 | #else | ||
441 | static inline void debug_timer_init(struct timer_list *timer) { } | ||
442 | static inline void debug_timer_activate(struct timer_list *timer) { } | ||
443 | static inline void debug_timer_deactivate(struct timer_list *timer) { } | ||
444 | #endif | ||
445 | |||
446 | static void __init_timer(struct timer_list *timer) | ||
331 | { | 447 | { |
332 | timer->entry.next = NULL; | 448 | timer->entry.next = NULL; |
333 | timer->base = __raw_get_cpu_var(tvec_bases); | 449 | timer->base = __raw_get_cpu_var(tvec_bases); |
@@ -337,6 +453,19 @@ void init_timer(struct timer_list *timer) | |||
337 | memset(timer->start_comm, 0, TASK_COMM_LEN); | 453 | memset(timer->start_comm, 0, TASK_COMM_LEN); |
338 | #endif | 454 | #endif |
339 | } | 455 | } |
456 | |||
457 | /** | ||
458 | * init_timer - initialize a timer. | ||
459 | * @timer: the timer to be initialized | ||
460 | * | ||
461 | * init_timer() must be done to a timer prior calling *any* of the | ||
462 | * other timer functions. | ||
463 | */ | ||
464 | void init_timer(struct timer_list *timer) | ||
465 | { | ||
466 | debug_timer_init(timer); | ||
467 | __init_timer(timer); | ||
468 | } | ||
340 | EXPORT_SYMBOL(init_timer); | 469 | EXPORT_SYMBOL(init_timer); |
341 | 470 | ||
342 | void init_timer_deferrable(struct timer_list *timer) | 471 | void init_timer_deferrable(struct timer_list *timer) |
@@ -351,6 +480,8 @@ static inline void detach_timer(struct timer_list *timer, | |||
351 | { | 480 | { |
352 | struct list_head *entry = &timer->entry; | 481 | struct list_head *entry = &timer->entry; |
353 | 482 | ||
483 | debug_timer_deactivate(timer); | ||
484 | |||
354 | __list_del(entry->prev, entry->next); | 485 | __list_del(entry->prev, entry->next); |
355 | if (clear_pending) | 486 | if (clear_pending) |
356 | entry->next = NULL; | 487 | entry->next = NULL; |
@@ -405,6 +536,8 @@ int __mod_timer(struct timer_list *timer, unsigned long expires) | |||
405 | ret = 1; | 536 | ret = 1; |
406 | } | 537 | } |
407 | 538 | ||
539 | debug_timer_activate(timer); | ||
540 | |||
408 | new_base = __get_cpu_var(tvec_bases); | 541 | new_base = __get_cpu_var(tvec_bases); |
409 | 542 | ||
410 | if (base != new_base) { | 543 | if (base != new_base) { |
@@ -450,6 +583,7 @@ void add_timer_on(struct timer_list *timer, int cpu) | |||
450 | BUG_ON(timer_pending(timer) || !timer->function); | 583 | BUG_ON(timer_pending(timer) || !timer->function); |
451 | spin_lock_irqsave(&base->lock, flags); | 584 | spin_lock_irqsave(&base->lock, flags); |
452 | timer_set_base(timer, base); | 585 | timer_set_base(timer, base); |
586 | debug_timer_activate(timer); | ||
453 | internal_add_timer(base, timer); | 587 | internal_add_timer(base, timer); |
454 | /* | 588 | /* |
455 | * Check whether the other CPU is idle and needs to be | 589 | * Check whether the other CPU is idle and needs to be |
@@ -1086,11 +1220,14 @@ signed long __sched schedule_timeout(signed long timeout) | |||
1086 | 1220 | ||
1087 | expire = timeout + jiffies; | 1221 | expire = timeout + jiffies; |
1088 | 1222 | ||
1089 | setup_timer(&timer, process_timeout, (unsigned long)current); | 1223 | setup_timer_on_stack(&timer, process_timeout, (unsigned long)current); |
1090 | __mod_timer(&timer, expire); | 1224 | __mod_timer(&timer, expire); |
1091 | schedule(); | 1225 | schedule(); |
1092 | del_singleshot_timer_sync(&timer); | 1226 | del_singleshot_timer_sync(&timer); |
1093 | 1227 | ||
1228 | /* Remove the timer from the object tracker */ | ||
1229 | destroy_timer_on_stack(&timer); | ||
1230 | |||
1094 | timeout = expire - jiffies; | 1231 | timeout = expire - jiffies; |
1095 | 1232 | ||
1096 | out: | 1233 | out: |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 3e132b0a59cc..d2099f41aa1e 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -217,6 +217,14 @@ config DEBUG_OBJECTS_FREE | |||
217 | properly. This can make kmalloc/kfree-intensive workloads | 217 | properly. This can make kmalloc/kfree-intensive workloads |
218 | much slower. | 218 | much slower. |
219 | 219 | ||
220 | config DEBUG_OBJECTS_TIMERS | ||
221 | bool "Debug timer objects" | ||
222 | depends on DEBUG_OBJECTS | ||
223 | help | ||
224 | If you say Y here, additional code will be inserted into the | ||
225 | timer routines to track the life time of timer objects and | ||
226 | validate the timer operations. | ||
227 | |||
220 | config DEBUG_SLAB | 228 | config DEBUG_SLAB |
221 | bool "Debug slab memory allocations" | 229 | bool "Debug slab memory allocations" |
222 | depends on DEBUG_KERNEL && SLAB | 230 | depends on DEBUG_KERNEL && SLAB |