--- linux-2.6.24/kernel/lockdep.c 2008-02-25 15:32:05.000000000 -0800 +++ linux-2.6.24.working/kernel/lockdep.c 2008-03-13 14:02:14.000000000 -0700 @@ -40,6 +40,7 @@ #include #include #include +#include #include @@ -179,6 +180,9 @@ lock_time_add(&pcs->read_holdtime, &stats.read_holdtime); lock_time_add(&pcs->write_holdtime, &stats.write_holdtime); + stats.stolen += pcs->stolen; + stats.spinnable += pcs->spinnable; + for (i = 0; i < ARRAY_SIZE(stats.bounces); i++) stats.bounces[i] += pcs->bounces[i]; } @@ -2854,13 +2858,21 @@ } static void -__lock_contended(struct lockdep_map *lock, unsigned long ip) +__lock_note_common(struct lockdep_map *dep_map, + void (*blockfn) (struct lockdep_map *dep_map, + struct held_lock *hlock, + unsigned long ip, int i + __LOCKDEP_TS_DECL), + unsigned long ip + __LOCKDEP_TS_DECL) { struct task_struct *curr = current; struct held_lock *hlock, *prev_hlock; - struct lock_class_stats *stats; unsigned int depth; - int i, point; + int i; + + if (!dep_map) + return; depth = curr->lockdep_depth; if (DEBUG_LOCKS_WARN_ON(!depth)) @@ -2874,14 +2886,30 @@ */ if (prev_hlock && prev_hlock->irq_context != hlock->irq_context) break; - if (hlock->instance == lock) + if (hlock->instance == dep_map) goto found_it; prev_hlock = hlock; } - print_lock_contention_bug(curr, lock, ip); + print_lock_contention_bug(curr, dep_map, ip); return; found_it: + blockfn(dep_map, hlock, ip, i __LOCKDEP_TS_PARAM); +} + +atomic_t spinnables_total = {.counter = 0}, + contentions_total = {.counter = 0}, + stolen_total = {.counter = 0}; + +static void +___lock_note_contended(struct lockdep_map *dep_map, + struct held_lock *hlock, + unsigned long ip, int i + __LOCKDEP_TS_DECL) +{ + struct lock_class_stats *stats; + int point; + hlock->waittime_stamp = sched_clock(); point = lock_contention_point(hlock->class, ip); @@ -2889,42 +2917,38 @@ stats = get_lock_stats(hlock->class); if (point < ARRAY_SIZE(stats->contention_point)) stats->contention_point[i]++; - if (lock->cpu != smp_processor_id()) + if (dep_map->cpu != smp_processor_id()) stats->bounces[bounce_contended + !!hlock->read]++; +#ifdef CONFIG_PREEMPT_RT + if (likely(_owner) && task_spinnable(_owner)) { + stats->spinnable++; + atomic_inc(&spinnables_total); + } + + atomic_inc(&contentions_total); +#endif put_lock_stats(stats); } static void -__lock_acquired(struct lockdep_map *lock) +__lock_note_contended(struct lockdep_map *dep_map, + unsigned long ip + __LOCKDEP_TS_DECL) +{ + __lock_note_common(dep_map, ___lock_note_contended, ip __LOCKDEP_TS_PARAM); +} + +static void +___lock_note_acquired(struct lockdep_map *lock, + struct held_lock *hlock, + unsigned long ip, int i + __LOCKDEP_TS_DECL) { - struct task_struct *curr = current; - struct held_lock *hlock, *prev_hlock; struct lock_class_stats *stats; - unsigned int depth; u64 now; s64 waittime = 0; - int i, cpu; - - depth = curr->lockdep_depth; - if (DEBUG_LOCKS_WARN_ON(!depth)) - return; - - prev_hlock = NULL; - for (i = depth-1; i >= 0; i--) { - hlock = curr->held_locks + i; - /* - * We must not cross into another context: - */ - if (prev_hlock && prev_hlock->irq_context != hlock->irq_context) - break; - if (hlock->instance == lock) - goto found_it; - prev_hlock = hlock; - } - print_lock_contention_bug(curr, lock, _RET_IP_); - return; + int cpu; -found_it: cpu = smp_processor_id(); if (hlock->waittime_stamp) { now = sched_clock(); @@ -2946,7 +2970,58 @@ lock->cpu = cpu; } -void lock_contended(struct lockdep_map *lock, unsigned long ip) +static void +__lock_note_acquired(struct lockdep_map *lock, + unsigned long ip + __LOCKDEP_TS_DECL) +{ + __lock_note_common(lock, ___lock_note_acquired, ip __LOCKDEP_TS_PARAM); + //__lock_note_common(lock, ___lock_note_acquired, _RET_IP_ __LOCKDEP_TS_PARAM); +} + +static void +___lock_note_stolen(struct lockdep_map *lock, + struct held_lock *hlock, + unsigned long ip, int i + __LOCKDEP_TS_DECL) +{ + struct lock_class_stats *stats; + + stats = get_lock_stats(hlock->class); + stats->stolen++; + atomic_inc(&stolen_total); + put_lock_stats(stats); +} + +static void +__lock_note_stolen(struct lockdep_map *lock, + unsigned long ip + __LOCKDEP_TS_DECL) +{ + __lock_note_common(lock, ___lock_note_stolen, _RET_IP_ __LOCKDEP_TS_PARAM); +} + +void lock_note_stolen(struct lockdep_map *dep_map) +{ + unsigned long flags; + + if (unlikely(!lock_stat)) + return; + + if (unlikely(current->lockdep_recursion)) + return; + + raw_local_irq_save(flags); + check_flags(flags); + current->lockdep_recursion = 1; + __lock_note_stolen(dep_map, 0 __LOCKDEP_TS_NULL); + current->lockdep_recursion = 0; + raw_local_irq_restore(flags); +} +EXPORT_SYMBOL_GPL(lock_note_stolen); + +void lock_note_contended( struct lockdep_map *dep_map, + unsigned long ip __LOCKDEP_TS_DECL) { unsigned long flags; @@ -2959,13 +3034,13 @@ raw_local_irq_save(flags); check_flags(flags); current->lockdep_recursion = 1; - __lock_contended(lock, ip); + __lock_note_contended(dep_map, ip __LOCKDEP_TS_PARAM); current->lockdep_recursion = 0; raw_local_irq_restore(flags); } -EXPORT_SYMBOL_GPL(lock_contended); +EXPORT_SYMBOL_GPL(lock_note_contended); -void lock_acquired(struct lockdep_map *lock) +void lock_note_acquired(struct lockdep_map *lock) { unsigned long flags; @@ -2978,11 +3053,11 @@ raw_local_irq_save(flags); check_flags(flags); current->lockdep_recursion = 1; - __lock_acquired(lock); + __lock_note_acquired(lock, 0 __LOCKDEP_TS_NULL); current->lockdep_recursion = 0; raw_local_irq_restore(flags); } -EXPORT_SYMBOL_GPL(lock_acquired); +EXPORT_SYMBOL_GPL(lock_note_acquired); #endif /* --- linux-2.6.24/kernel/lockdep_proc.c 2008-01-24 14:58:37.000000000 -0800 +++ linux-2.6.24.working/kernel/lockdep_proc.c 2008-03-13 00:08:32.000000000 -0700 @@ -418,9 +418,12 @@ seq_printf(m, " %14s", num); } -static void seq_lock_time(struct seq_file *m, struct lock_time *lt) +static void seq_lock_time(struct seq_file *m, struct lock_time *lt, int header, unsigned long spinnables, unsigned long steals) { seq_printf(m, "%14lu", lt->nr); + if (header) { + seq_printf(m, " [%lu, %lu]", spinnables, steals); + } seq_time(m, lt->min); seq_time(m, lt->max); seq_time(m, lt->total); @@ -432,6 +435,7 @@ struct lock_class *class; struct lock_class_stats *stats; int i, namelen; + int spinnables = 1; class = data->class; stats = &data->stats; @@ -468,18 +472,21 @@ seq_printf(m, "%40s:", name); seq_printf(m, "%14lu ", stats->bounces[bounce_contended_write]); - seq_lock_time(m, &stats->write_waittime); + seq_lock_time(m, &stats->write_waittime, spinnables, stats->spinnable, stats->stolen); + if (spinnables) { + spinnables = 0; + } seq_printf(m, " %14lu ", stats->bounces[bounce_acquired_write]); - seq_lock_time(m, &stats->write_holdtime); + seq_lock_time(m, &stats->write_holdtime, 0, 0, 0); seq_puts(m, "\n"); } if (stats->read_holdtime.nr) { seq_printf(m, "%38s-R:", name); seq_printf(m, "%14lu ", stats->bounces[bounce_contended_read]); - seq_lock_time(m, &stats->read_waittime); + seq_lock_time(m, &stats->read_waittime, spinnables, stats->spinnable, stats->stolen); seq_printf(m, " %14lu ", stats->bounces[bounce_acquired_read]); - seq_lock_time(m, &stats->read_holdtime); + seq_lock_time(m, &stats->read_holdtime, 0, 0, 0); seq_puts(m, "\n"); } @@ -513,15 +520,22 @@ } } +extern atomic_t spinnables_total, contentions_total, stolen_total; +atomic_t cpu_range_error = {.counter = 0}; + static void seq_header(struct seq_file *m) { seq_printf(m, "lock_stat version 0.2\n"); + seq_printf(m, "spinnables_total = %u\n", atomic_read(&spinnables_total)); + seq_printf(m, "contentions_total = %u\n", atomic_read(&contentions_total)); + seq_printf(m, "stolen_total = %u\n", atomic_read(&stolen_total)); + seq_printf(m, "cpu range error = %u\n", atomic_read(&cpu_range_error)); seq_line(m, '-', 0, 40 + 1 + 10 * (14 + 1)); seq_printf(m, "%40s %14s %14s %14s %14s %14s %14s %14s %14s " "%14s %14s\n", "class name", "con-bounces", - "contentions", + "contentions [adapt,steals]", "waittime-min", "waittime-max", "waittime-total",