diff options
author | Ming Lei <tom.leiming@gmail.com> | 2009-07-22 10:48:09 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-08-02 09:41:37 -0400 |
commit | e351b660fddd4df76cc4635f896d311ed0ff3752 (patch) | |
tree | 380a67c875a4454bd47a8ce6ddd159432863646e | |
parent | bb97a91e2549a7f2df9c21d32542582f549ab3ec (diff) |
lockdep: Reintroduce generation count to make BFS faster
We still can apply DaveM's generation count optimization to
BFS, based on the following idea:
- before doing each BFS, increase the global generation id
by 1
- if one node in the graph has been visited, mark it as
visited by storing the current global generation id into
the node's dep_gen_id field
- so we can decide if one node has been visited already, by
comparing the node's dep_gen_id with the global generation id.
By applying DaveM's generation count optimization to current
implementation of BFS, we gain the following advantages:
- we save MAX_LOCKDEP_ENTRIES/8 bytes memory;
- we remove the bitmap_zero(bfs_accessed, MAX_LOCKDEP_ENTRIES);
in each BFS, which is very time-consuming since
MAX_LOCKDEP_ENTRIES may be very large.(16384UL)
Signed-off-by: Ming Lei <tom.leiming@gmail.com>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: "David S. Miller" <davem@davemloft.net>
LKML-Reference: <1248274089-6358-1-git-send-email-tom.leiming@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | include/linux/lockdep.h | 1 | ||||
-rw-r--r-- | kernel/lockdep.c | 11 |
2 files changed, 7 insertions, 5 deletions
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index 47d42eff6124..9ccf0e286b2a 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h | |||
@@ -58,6 +58,7 @@ struct lock_class { | |||
58 | 58 | ||
59 | struct lockdep_subclass_key *key; | 59 | struct lockdep_subclass_key *key; |
60 | unsigned int subclass; | 60 | unsigned int subclass; |
61 | unsigned int dep_gen_id; | ||
61 | 62 | ||
62 | /* | 63 | /* |
63 | * IRQ/softirq usage tracking bits: | 64 | * IRQ/softirq usage tracking bits: |
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 0bb246e21cd7..2b443b5090a1 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -861,14 +861,15 @@ struct circular_queue { | |||
861 | }; | 861 | }; |
862 | 862 | ||
863 | static struct circular_queue lock_cq; | 863 | static struct circular_queue lock_cq; |
864 | static unsigned long bfs_accessed[BITS_TO_LONGS(MAX_LOCKDEP_ENTRIES)]; | ||
865 | 864 | ||
866 | unsigned int max_bfs_queue_depth; | 865 | unsigned int max_bfs_queue_depth; |
867 | 866 | ||
867 | static unsigned int lockdep_dependency_gen_id; | ||
868 | |||
868 | static inline void __cq_init(struct circular_queue *cq) | 869 | static inline void __cq_init(struct circular_queue *cq) |
869 | { | 870 | { |
870 | cq->front = cq->rear = 0; | 871 | cq->front = cq->rear = 0; |
871 | bitmap_zero(bfs_accessed, MAX_LOCKDEP_ENTRIES); | 872 | lockdep_dependency_gen_id++; |
872 | } | 873 | } |
873 | 874 | ||
874 | static inline int __cq_empty(struct circular_queue *cq) | 875 | static inline int __cq_empty(struct circular_queue *cq) |
@@ -914,7 +915,7 @@ static inline void mark_lock_accessed(struct lock_list *lock, | |||
914 | nr = lock - list_entries; | 915 | nr = lock - list_entries; |
915 | WARN_ON(nr >= nr_list_entries); | 916 | WARN_ON(nr >= nr_list_entries); |
916 | lock->parent = parent; | 917 | lock->parent = parent; |
917 | set_bit(nr, bfs_accessed); | 918 | lock->class->dep_gen_id = lockdep_dependency_gen_id; |
918 | } | 919 | } |
919 | 920 | ||
920 | static inline unsigned long lock_accessed(struct lock_list *lock) | 921 | static inline unsigned long lock_accessed(struct lock_list *lock) |
@@ -923,7 +924,7 @@ static inline unsigned long lock_accessed(struct lock_list *lock) | |||
923 | 924 | ||
924 | nr = lock - list_entries; | 925 | nr = lock - list_entries; |
925 | WARN_ON(nr >= nr_list_entries); | 926 | WARN_ON(nr >= nr_list_entries); |
926 | return test_bit(nr, bfs_accessed); | 927 | return lock->class->dep_gen_id == lockdep_dependency_gen_id; |
927 | } | 928 | } |
928 | 929 | ||
929 | static inline struct lock_list *get_lock_parent(struct lock_list *child) | 930 | static inline struct lock_list *get_lock_parent(struct lock_list *child) |
@@ -3604,7 +3605,7 @@ void __init lockdep_info(void) | |||
3604 | sizeof(struct lock_chain) * MAX_LOCKDEP_CHAINS + | 3605 | sizeof(struct lock_chain) * MAX_LOCKDEP_CHAINS + |
3605 | sizeof(struct list_head) * CHAINHASH_SIZE) / 1024 | 3606 | sizeof(struct list_head) * CHAINHASH_SIZE) / 1024 |
3606 | #ifdef CONFIG_PROVE_LOCKING | 3607 | #ifdef CONFIG_PROVE_LOCKING |
3607 | + sizeof(struct circular_queue) + sizeof(bfs_accessed) | 3608 | + sizeof(struct circular_queue) |
3608 | #endif | 3609 | #endif |
3609 | ); | 3610 | ); |
3610 | 3611 | ||