diff options
author | Ingo Molnar <mingo@elte.hu> | 2006-07-10 07:44:04 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-07-10 16:24:14 -0400 |
commit | d6d897cec29252b8d0785198cfa6ca16d30c739d (patch) | |
tree | 01b138b10c7afa0e88e9720be3d3616e4f0bccc1 /kernel | |
parent | 55794a412fdf9af1744800e5020a4ec6b21e3cdc (diff) |
[PATCH] lockdep: core, reduce per-lock class-cache size
lockdep_map is embedded into every lock, which blows up data structure
sizes all around the kernel. Reduce the class-cache to be for the default
class only - that is used in 99.9% of the cases and even if we dont have a
class cached, the lookup in the class-hash is lockless.
This change reduces the per-lock dep_map overhead by 56 bytes on 64-bit
platforms and by 28 bytes on 32-bit platforms.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/lockdep.c | 87 |
1 files changed, 54 insertions, 33 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index c1f34addd003..9bad17884513 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -1104,7 +1104,7 @@ extern void __error_too_big_MAX_LOCKDEP_SUBCLASSES(void); | |||
1104 | * itself, so actual lookup of the hash should be once per lock object. | 1104 | * itself, so actual lookup of the hash should be once per lock object. |
1105 | */ | 1105 | */ |
1106 | static inline struct lock_class * | 1106 | static inline struct lock_class * |
1107 | register_lock_class(struct lockdep_map *lock, unsigned int subclass) | 1107 | look_up_lock_class(struct lockdep_map *lock, unsigned int subclass) |
1108 | { | 1108 | { |
1109 | struct lockdep_subclass_key *key; | 1109 | struct lockdep_subclass_key *key; |
1110 | struct list_head *hash_head; | 1110 | struct list_head *hash_head; |
@@ -1148,7 +1148,26 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass) | |||
1148 | */ | 1148 | */ |
1149 | list_for_each_entry(class, hash_head, hash_entry) | 1149 | list_for_each_entry(class, hash_head, hash_entry) |
1150 | if (class->key == key) | 1150 | if (class->key == key) |
1151 | goto out_set; | 1151 | return class; |
1152 | |||
1153 | return NULL; | ||
1154 | } | ||
1155 | |||
1156 | /* | ||
1157 | * Register a lock's class in the hash-table, if the class is not present | ||
1158 | * yet. Otherwise we look it up. We cache the result in the lock object | ||
1159 | * itself, so actual lookup of the hash should be once per lock object. | ||
1160 | */ | ||
1161 | static inline struct lock_class * | ||
1162 | register_lock_class(struct lockdep_map *lock, unsigned int subclass) | ||
1163 | { | ||
1164 | struct lockdep_subclass_key *key; | ||
1165 | struct list_head *hash_head; | ||
1166 | struct lock_class *class; | ||
1167 | |||
1168 | class = look_up_lock_class(lock, subclass); | ||
1169 | if (likely(class)) | ||
1170 | return class; | ||
1152 | 1171 | ||
1153 | /* | 1172 | /* |
1154 | * Debug-check: all keys must be persistent! | 1173 | * Debug-check: all keys must be persistent! |
@@ -1163,6 +1182,9 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass) | |||
1163 | return NULL; | 1182 | return NULL; |
1164 | } | 1183 | } |
1165 | 1184 | ||
1185 | key = lock->key->subkeys + subclass; | ||
1186 | hash_head = classhashentry(key); | ||
1187 | |||
1166 | __raw_spin_lock(&hash_lock); | 1188 | __raw_spin_lock(&hash_lock); |
1167 | /* | 1189 | /* |
1168 | * We have to do the hash-walk again, to avoid races | 1190 | * We have to do the hash-walk again, to avoid races |
@@ -1209,8 +1231,8 @@ register_lock_class(struct lockdep_map *lock, unsigned int subclass) | |||
1209 | out_unlock_set: | 1231 | out_unlock_set: |
1210 | __raw_spin_unlock(&hash_lock); | 1232 | __raw_spin_unlock(&hash_lock); |
1211 | 1233 | ||
1212 | out_set: | 1234 | if (!subclass) |
1213 | lock->class[subclass] = class; | 1235 | lock->class_cache = class; |
1214 | 1236 | ||
1215 | DEBUG_LOCKS_WARN_ON(class->subclass != subclass); | 1237 | DEBUG_LOCKS_WARN_ON(class->subclass != subclass); |
1216 | 1238 | ||
@@ -1914,7 +1936,7 @@ void lockdep_init_map(struct lockdep_map *lock, const char *name, | |||
1914 | } | 1936 | } |
1915 | lock->name = name; | 1937 | lock->name = name; |
1916 | lock->key = key; | 1938 | lock->key = key; |
1917 | memset(lock->class, 0, sizeof(lock->class[0])*MAX_LOCKDEP_SUBCLASSES); | 1939 | lock->class_cache = NULL; |
1918 | } | 1940 | } |
1919 | 1941 | ||
1920 | EXPORT_SYMBOL_GPL(lockdep_init_map); | 1942 | EXPORT_SYMBOL_GPL(lockdep_init_map); |
@@ -1928,8 +1950,8 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, | |||
1928 | unsigned long ip) | 1950 | unsigned long ip) |
1929 | { | 1951 | { |
1930 | struct task_struct *curr = current; | 1952 | struct task_struct *curr = current; |
1953 | struct lock_class *class = NULL; | ||
1931 | struct held_lock *hlock; | 1954 | struct held_lock *hlock; |
1932 | struct lock_class *class; | ||
1933 | unsigned int depth, id; | 1955 | unsigned int depth, id; |
1934 | int chain_head = 0; | 1956 | int chain_head = 0; |
1935 | u64 chain_key; | 1957 | u64 chain_key; |
@@ -1947,8 +1969,11 @@ static int __lock_acquire(struct lockdep_map *lock, unsigned int subclass, | |||
1947 | return 0; | 1969 | return 0; |
1948 | } | 1970 | } |
1949 | 1971 | ||
1950 | class = lock->class[subclass]; | 1972 | if (!subclass) |
1951 | /* not cached yet? */ | 1973 | class = lock->class_cache; |
1974 | /* | ||
1975 | * Not cached yet or subclass? | ||
1976 | */ | ||
1952 | if (unlikely(!class)) { | 1977 | if (unlikely(!class)) { |
1953 | class = register_lock_class(lock, subclass); | 1978 | class = register_lock_class(lock, subclass); |
1954 | if (!class) | 1979 | if (!class) |
@@ -2449,48 +2474,44 @@ void lockdep_free_key_range(void *start, unsigned long size) | |||
2449 | 2474 | ||
2450 | void lockdep_reset_lock(struct lockdep_map *lock) | 2475 | void lockdep_reset_lock(struct lockdep_map *lock) |
2451 | { | 2476 | { |
2452 | struct lock_class *class, *next, *entry; | 2477 | struct lock_class *class, *next; |
2453 | struct list_head *head; | 2478 | struct list_head *head; |
2454 | unsigned long flags; | 2479 | unsigned long flags; |
2455 | int i, j; | 2480 | int i, j; |
2456 | 2481 | ||
2457 | raw_local_irq_save(flags); | 2482 | raw_local_irq_save(flags); |
2458 | __raw_spin_lock(&hash_lock); | ||
2459 | 2483 | ||
2460 | /* | 2484 | /* |
2461 | * Remove all classes this lock has: | 2485 | * Remove all classes this lock might have: |
2486 | */ | ||
2487 | for (j = 0; j < MAX_LOCKDEP_SUBCLASSES; j++) { | ||
2488 | /* | ||
2489 | * If the class exists we look it up and zap it: | ||
2490 | */ | ||
2491 | class = look_up_lock_class(lock, j); | ||
2492 | if (class) | ||
2493 | zap_class(class); | ||
2494 | } | ||
2495 | /* | ||
2496 | * Debug check: in the end all mapped classes should | ||
2497 | * be gone. | ||
2462 | */ | 2498 | */ |
2499 | __raw_spin_lock(&hash_lock); | ||
2463 | for (i = 0; i < CLASSHASH_SIZE; i++) { | 2500 | for (i = 0; i < CLASSHASH_SIZE; i++) { |
2464 | head = classhash_table + i; | 2501 | head = classhash_table + i; |
2465 | if (list_empty(head)) | 2502 | if (list_empty(head)) |
2466 | continue; | 2503 | continue; |
2467 | list_for_each_entry_safe(class, next, head, hash_entry) { | 2504 | list_for_each_entry_safe(class, next, head, hash_entry) { |
2468 | for (j = 0; j < MAX_LOCKDEP_SUBCLASSES; j++) { | 2505 | if (unlikely(class == lock->class_cache)) { |
2469 | entry = lock->class[j]; | 2506 | __raw_spin_unlock(&hash_lock); |
2470 | if (class == entry) { | 2507 | DEBUG_LOCKS_WARN_ON(1); |
2471 | zap_class(class); | 2508 | goto out_restore; |
2472 | lock->class[j] = NULL; | ||
2473 | break; | ||
2474 | } | ||
2475 | } | 2509 | } |
2476 | } | 2510 | } |
2477 | } | 2511 | } |
2478 | |||
2479 | /* | ||
2480 | * Debug check: in the end all mapped classes should | ||
2481 | * be gone. | ||
2482 | */ | ||
2483 | for (j = 0; j < MAX_LOCKDEP_SUBCLASSES; j++) { | ||
2484 | entry = lock->class[j]; | ||
2485 | if (!entry) | ||
2486 | continue; | ||
2487 | __raw_spin_unlock(&hash_lock); | ||
2488 | DEBUG_LOCKS_WARN_ON(1); | ||
2489 | raw_local_irq_restore(flags); | ||
2490 | return; | ||
2491 | } | ||
2492 | |||
2493 | __raw_spin_unlock(&hash_lock); | 2512 | __raw_spin_unlock(&hash_lock); |
2513 | |||
2514 | out_restore: | ||
2494 | raw_local_irq_restore(flags); | 2515 | raw_local_irq_restore(flags); |
2495 | } | 2516 | } |
2496 | 2517 | ||