Skip to content

Commit

Permalink
lockdep: Reintroduce generation count to make BFS faster
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Ming Lei authored and Ingo Molnar committed Aug 2, 2009
1 parent bb97a91 commit e351b66
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 5 deletions.
1 change: 1 addition & 0 deletions include/linux/lockdep.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ struct lock_class {

struct lockdep_subclass_key *key;
unsigned int subclass;
unsigned int dep_gen_id;

/*
* IRQ/softirq usage tracking bits:
Expand Down
11 changes: 6 additions & 5 deletions kernel/lockdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -861,14 +861,15 @@ struct circular_queue {
};

static struct circular_queue lock_cq;
static unsigned long bfs_accessed[BITS_TO_LONGS(MAX_LOCKDEP_ENTRIES)];

unsigned int max_bfs_queue_depth;

static unsigned int lockdep_dependency_gen_id;

static inline void __cq_init(struct circular_queue *cq)
{
cq->front = cq->rear = 0;
bitmap_zero(bfs_accessed, MAX_LOCKDEP_ENTRIES);
lockdep_dependency_gen_id++;
}

static inline int __cq_empty(struct circular_queue *cq)
Expand Down Expand Up @@ -914,7 +915,7 @@ static inline void mark_lock_accessed(struct lock_list *lock,
nr = lock - list_entries;
WARN_ON(nr >= nr_list_entries);
lock->parent = parent;
set_bit(nr, bfs_accessed);
lock->class->dep_gen_id = lockdep_dependency_gen_id;
}

static inline unsigned long lock_accessed(struct lock_list *lock)
Expand All @@ -923,7 +924,7 @@ static inline unsigned long lock_accessed(struct lock_list *lock)

nr = lock - list_entries;
WARN_ON(nr >= nr_list_entries);
return test_bit(nr, bfs_accessed);
return lock->class->dep_gen_id == lockdep_dependency_gen_id;
}

static inline struct lock_list *get_lock_parent(struct lock_list *child)
Expand Down Expand Up @@ -3604,7 +3605,7 @@ void __init lockdep_info(void)
sizeof(struct lock_chain) * MAX_LOCKDEP_CHAINS +
sizeof(struct list_head) * CHAINHASH_SIZE) / 1024
#ifdef CONFIG_PROVE_LOCKING
+ sizeof(struct circular_queue) + sizeof(bfs_accessed)
+ sizeof(struct circular_queue)
#endif
);

Expand Down

0 comments on commit e351b66

Please sign in to comment.