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 |
