aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/lockdep.c
diff options
context:
space:
mode:
authorHitoshi Mitake <mitake@dcl.info.waseda.ac.jp>2010-10-05 05:01:51 -0400
committerIngo Molnar <mingo@elte.hu>2010-10-18 12:44:25 -0400
commit620162505e5d46bc4494b1761743e4b0b3bf8e16 (patch)
tree462e6d2ecdcfdaa117c5b926325a0ce1d565571e /kernel/lockdep.c
parentf2f108eb4511f22a6f7568090cfcf4e7b2dc0f62 (diff)
lockdep: Add improved subclass caching
Current lockdep_map only caches one class with subclass == 0, and looks up hash table of classes when subclass != 0. It seems that this has no problem because the case of subclass != 0 is rare. But locks of struct rq are acquired with subclass == 1 when task migration is executed. Task migration is high frequent event, so I modified lockdep to cache subclasses. I measured the score of perf bench sched messaging. This patch has slightly but certain (order of milli seconds or 10 milli seconds) effect when lots of tasks are running. I'll show the result in the tail of this description. NR_LOCKDEP_CACHING_CLASSES specifies how many classes can be cached in the instances of lockdep_map. I discussed with Peter Zijlstra in LinuxCon Japan about this approach and he taught me that caching every subclasses(8) is cleary waste of memory. So number of cached classes should be configurable. === Score comparison of benchmarks === # "min" means best score, and "max" means worst score for i in `seq 1 10`; do ./perf bench -f simple sched messaging; done before: min: 0.565000, max: 0.583000, avg: 0.572500 after: min: 0.559000, max: 0.568000, avg: 0.563300 # with more processes for i in `seq 1 10`; do ./perf bench -f simple sched messaging -g 40; done before: min: 2.274000, max: 2.298000, avg: 2.286300 after: min: 2.242000, max: 2.270000, avg: 2.259700 Signed-off-by: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp> Cc: Frederic Weisbecker <fweisbec@gmail.com> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <1286269311-28336-2-git-send-email-mitake@dcl.info.waseda.ac.jp> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/lockdep.c')
-rw-r--r--kernel/lockdep.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c
index 84baa71cfda5..bc4d32871f9a 100644
--- a/kernel/lockdep.c
+++ b/kernel/lockdep.c
@@ -774,7 +774,9 @@ out_unlock_set:
774 raw_local_irq_restore(flags); 774 raw_local_irq_restore(flags);
775 775
776 if (!subclass || force) 776 if (!subclass || force)
777 lock->class_cache = class; 777 lock->class_cache[0] = class;
778 else if (subclass < NR_LOCKDEP_CACHING_CLASSES)
779 lock->class_cache[subclass] = class;
778 780
779 if (DEBUG_LOCKS_WARN_ON(class->subclass != subclass)) 781 if (DEBUG_LOCKS_WARN_ON(class->subclass != subclass))
780 return NULL; 782 return NULL;
@@ -2679,7 +2681,11 @@ static int mark_lock(struct task_struct *curr, struct held_lock *this,
2679void lockdep_init_map(struct lockdep_map *lock, const char *name, 2681void lockdep_init_map(struct lockdep_map *lock, const char *name,
2680 struct lock_class_key *key, int subclass) 2682 struct lock_class_key *key, int subclass)
2681{ 2683{
2682 lock->class_cache = NULL; 2684 int i;
2685
2686 for (i = 0; i < NR_LOCKDEP_CACHING_CLASSES; i++)
2687 lock->class_cache[i] = NULL;
2688
2683#ifdef CONFIG_LOCK_STAT 2689#ifdef CONFIG_LOCK_STAT
2684 lock->cpu = raw_smp_processor_id(); 2690 lock->cpu = raw_smp_processor_id();
2685#endif 2691#endif
@@ -2750,10 +2756,10 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass,
2750 if (lock->key == &__lockdep_no_validate__) 2756 if (lock->key == &__lockdep_no_validate__)
2751 check = 1; 2757 check = 1;
2752 2758
2753 if (!subclass) 2759 if (subclass < NR_LOCKDEP_CACHING_CLASSES)
2754 class = lock->class_cache; 2760 class = lock->class_cache[subclass];
2755 /* 2761 /*
2756 * Not cached yet or subclass? 2762 * Not cached?
2757 */ 2763 */
2758 if (unlikely(!class)) { 2764 if (unlikely(!class)) {
2759 class = register_lock_class(lock, subclass, 0); 2765 class = register_lock_class(lock, subclass, 0);
@@ -2918,7 +2924,7 @@ static int match_held_lock(struct held_lock *hlock, struct lockdep_map *lock)
2918 return 1; 2924 return 1;
2919 2925
2920 if (hlock->references) { 2926 if (hlock->references) {
2921 struct lock_class *class = lock->class_cache; 2927 struct lock_class *class = lock->class_cache[0];
2922 2928
2923 if (!class) 2929 if (!class)
2924 class = look_up_lock_class(lock, 0); 2930 class = look_up_lock_class(lock, 0);
@@ -3559,7 +3565,12 @@ void lockdep_reset_lock(struct lockdep_map *lock)
3559 if (list_empty(head)) 3565 if (list_empty(head))
3560 continue; 3566 continue;
3561 list_for_each_entry_safe(class, next, head, hash_entry) { 3567 list_for_each_entry_safe(class, next, head, hash_entry) {
3562 if (unlikely(class == lock->class_cache)) { 3568 int match = 0;
3569
3570 for (j = 0; j < NR_LOCKDEP_CACHING_CLASSES; j++)
3571 match |= class == lock->class_cache[j];
3572
3573 if (unlikely(match)) {
3563 if (debug_locks_off_graph_unlock()) 3574 if (debug_locks_off_graph_unlock())
3564 WARN_ON(1); 3575 WARN_ON(1);
3565 goto out_restore; 3576 goto out_restore;