Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 95292
b: refs/heads/master
c: c6f3a97
h: refs/heads/master
v: v3
  • Loading branch information
Thomas Gleixner authored and Linus Torvalds committed Apr 30, 2008
1 parent e9c0878 commit cfc4086
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 14 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 691cc54c7d28542434d2b3ee4ddbad6a99312dec
refs/heads/master: c6f3a97f86a5c97be0ca255976110bb9c3cfe669
4 changes: 3 additions & 1 deletion trunk/drivers/parport/ieee1284.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ int parport_wait_event (struct parport *port, signed long timeout)
semaphore. */
return 1;

init_timer (&timer);
init_timer_on_stack(&timer);
timer.expires = jiffies + timeout;
timer.function = timeout_waiting_on_port;
port_from_cookie[port->number % PARPORT_MAX] = port;
Expand All @@ -88,6 +88,8 @@ int parport_wait_event (struct parport *port, signed long timeout)
/* Timed out. */
ret = 1;

destroy_timer_on_stack(&timer);

return ret;
}

Expand Down
5 changes: 2 additions & 3 deletions trunk/fs/aio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1078,9 +1078,7 @@ static void timeout_func(unsigned long data)

static inline void init_timeout(struct aio_timeout *to)
{
init_timer(&to->timer);
to->timer.data = (unsigned long)to;
to->timer.function = timeout_func;
setup_timer_on_stack(&to->timer, timeout_func, (unsigned long) to);
to->timed_out = 0;
to->p = current;
}
Expand Down Expand Up @@ -1213,6 +1211,7 @@ static int read_events(struct kioctx *ctx,
if (timeout)
clear_timeout(&to);
out:
destroy_timer_on_stack(&to.timer);
return i ? i : ret;
}

Expand Down
7 changes: 7 additions & 0 deletions trunk/include/linux/poison.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@
#define LIST_POISON1 ((void *) 0x00100100)
#define LIST_POISON2 ((void *) 0x00200200)

/********** include/linux/timer.h **********/
/*
* Magic number "tsta" to indicate a static timer initializer
* for the object debugging code.
*/
#define TIMER_ENTRY_STATIC ((void *) 0x74737461)

/********** mm/slab.c **********/
/*
* Magic nums for obj red zoning.
Expand Down
23 changes: 22 additions & 1 deletion trunk/include/linux/timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <linux/list.h>
#include <linux/ktime.h>
#include <linux/stddef.h>
#include <linux/debugobjects.h>

struct tvec_base;

Expand All @@ -25,6 +26,7 @@ struct timer_list {
extern struct tvec_base boot_tvec_bases;

#define TIMER_INITIALIZER(_function, _expires, _data) { \
.entry = { .prev = TIMER_ENTRY_STATIC }, \
.function = (_function), \
.expires = (_expires), \
.data = (_data), \
Expand All @@ -38,6 +40,17 @@ extern struct tvec_base boot_tvec_bases;
void init_timer(struct timer_list *timer);
void init_timer_deferrable(struct timer_list *timer);

#ifdef CONFIG_DEBUG_OBJECTS_TIMERS
extern void init_timer_on_stack(struct timer_list *timer);
extern void destroy_timer_on_stack(struct timer_list *timer);
#else
static inline void destroy_timer_on_stack(struct timer_list *timer) { }
static inline void init_timer_on_stack(struct timer_list *timer)
{
init_timer(timer);
}
#endif

static inline void setup_timer(struct timer_list * timer,
void (*function)(unsigned long),
unsigned long data)
Expand All @@ -47,6 +60,15 @@ static inline void setup_timer(struct timer_list * timer,
init_timer(timer);
}

static inline void setup_timer_on_stack(struct timer_list *timer,
void (*function)(unsigned long),
unsigned long data)
{
timer->function = function;
timer->data = data;
init_timer_on_stack(timer);
}

/**
* timer_pending - is a timer pending?
* @timer: the timer in question
Expand Down Expand Up @@ -164,5 +186,4 @@ unsigned long __round_jiffies_relative(unsigned long j, int cpu);
unsigned long round_jiffies(unsigned long j);
unsigned long round_jiffies_relative(unsigned long j);


#endif
153 changes: 145 additions & 8 deletions trunk/kernel/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,14 +320,130 @@ static void timer_stats_account_timer(struct timer_list *timer)
static void timer_stats_account_timer(struct timer_list *timer) {}
#endif

/**
* init_timer - initialize a timer.
* @timer: the timer to be initialized
*
* init_timer() must be done to a timer prior calling *any* of the
* other timer functions.
#ifdef CONFIG_DEBUG_OBJECTS_TIMERS

static struct debug_obj_descr timer_debug_descr;

/*
* fixup_init is called when:
* - an active object is initialized
*/
void init_timer(struct timer_list *timer)
static int timer_fixup_init(void *addr, enum debug_obj_state state)
{
struct timer_list *timer = addr;

switch (state) {
case ODEBUG_STATE_ACTIVE:
del_timer_sync(timer);
debug_object_init(timer, &timer_debug_descr);
return 1;
default:
return 0;
}
}

/*
* fixup_activate is called when:
* - an active object is activated
* - an unknown object is activated (might be a statically initialized object)
*/
static int timer_fixup_activate(void *addr, enum debug_obj_state state)
{
struct timer_list *timer = addr;

switch (state) {

case ODEBUG_STATE_NOTAVAILABLE:
/*
* This is not really a fixup. The timer was
* statically initialized. We just make sure that it
* is tracked in the object tracker.
*/
if (timer->entry.next == NULL &&
timer->entry.prev == TIMER_ENTRY_STATIC) {
debug_object_init(timer, &timer_debug_descr);
debug_object_activate(timer, &timer_debug_descr);
return 0;
} else {
WARN_ON_ONCE(1);
}
return 0;

case ODEBUG_STATE_ACTIVE:
WARN_ON(1);

default:
return 0;
}
}

/*
* fixup_free is called when:
* - an active object is freed
*/
static int timer_fixup_free(void *addr, enum debug_obj_state state)
{
struct timer_list *timer = addr;

switch (state) {
case ODEBUG_STATE_ACTIVE:
del_timer_sync(timer);
debug_object_free(timer, &timer_debug_descr);
return 1;
default:
return 0;
}
}

static struct debug_obj_descr timer_debug_descr = {
.name = "timer_list",
.fixup_init = timer_fixup_init,
.fixup_activate = timer_fixup_activate,
.fixup_free = timer_fixup_free,
};

static inline void debug_timer_init(struct timer_list *timer)
{
debug_object_init(timer, &timer_debug_descr);
}

static inline void debug_timer_activate(struct timer_list *timer)
{
debug_object_activate(timer, &timer_debug_descr);
}

static inline void debug_timer_deactivate(struct timer_list *timer)
{
debug_object_deactivate(timer, &timer_debug_descr);
}

static inline void debug_timer_free(struct timer_list *timer)
{
debug_object_free(timer, &timer_debug_descr);
}

static void __init_timer(struct timer_list *timer);

void init_timer_on_stack(struct timer_list *timer)
{
debug_object_init_on_stack(timer, &timer_debug_descr);
__init_timer(timer);
}
EXPORT_SYMBOL_GPL(init_timer_on_stack);

void destroy_timer_on_stack(struct timer_list *timer)
{
debug_object_free(timer, &timer_debug_descr);
}
EXPORT_SYMBOL_GPL(destroy_timer_on_stack);

#else
static inline void debug_timer_init(struct timer_list *timer) { }
static inline void debug_timer_activate(struct timer_list *timer) { }
static inline void debug_timer_deactivate(struct timer_list *timer) { }
#endif

static void __init_timer(struct timer_list *timer)
{
timer->entry.next = NULL;
timer->base = __raw_get_cpu_var(tvec_bases);
Expand All @@ -337,6 +453,19 @@ void init_timer(struct timer_list *timer)
memset(timer->start_comm, 0, TASK_COMM_LEN);
#endif
}

/**
* init_timer - initialize a timer.
* @timer: the timer to be initialized
*
* init_timer() must be done to a timer prior calling *any* of the
* other timer functions.
*/
void init_timer(struct timer_list *timer)
{
debug_timer_init(timer);
__init_timer(timer);
}
EXPORT_SYMBOL(init_timer);

void init_timer_deferrable(struct timer_list *timer)
Expand All @@ -351,6 +480,8 @@ static inline void detach_timer(struct timer_list *timer,
{
struct list_head *entry = &timer->entry;

debug_timer_deactivate(timer);

__list_del(entry->prev, entry->next);
if (clear_pending)
entry->next = NULL;
Expand Down Expand Up @@ -405,6 +536,8 @@ int __mod_timer(struct timer_list *timer, unsigned long expires)
ret = 1;
}

debug_timer_activate(timer);

new_base = __get_cpu_var(tvec_bases);

if (base != new_base) {
Expand Down Expand Up @@ -450,6 +583,7 @@ void add_timer_on(struct timer_list *timer, int cpu)
BUG_ON(timer_pending(timer) || !timer->function);
spin_lock_irqsave(&base->lock, flags);
timer_set_base(timer, base);
debug_timer_activate(timer);
internal_add_timer(base, timer);
/*
* Check whether the other CPU is idle and needs to be
Expand Down Expand Up @@ -1086,11 +1220,14 @@ signed long __sched schedule_timeout(signed long timeout)

expire = timeout + jiffies;

setup_timer(&timer, process_timeout, (unsigned long)current);
setup_timer_on_stack(&timer, process_timeout, (unsigned long)current);
__mod_timer(&timer, expire);
schedule();
del_singleshot_timer_sync(&timer);

/* Remove the timer from the object tracker */
destroy_timer_on_stack(&timer);

timeout = expire - jiffies;

out:
Expand Down
8 changes: 8 additions & 0 deletions trunk/lib/Kconfig.debug
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,14 @@ config DEBUG_OBJECTS_FREE
properly. This can make kmalloc/kfree-intensive workloads
much slower.

config DEBUG_OBJECTS_TIMERS
bool "Debug timer objects"
depends on DEBUG_OBJECTS
help
If you say Y here, additional code will be inserted into the
timer routines to track the life time of timer objects and
validate the timer operations.

config DEBUG_SLAB
bool "Debug slab memory allocations"
depends on DEBUG_KERNEL && SLAB
Expand Down

0 comments on commit cfc4086

Please sign in to comment.