Simplify the timerqueue code by using cached rbtrees and rely on the tree leftmost node semantics to get the timer with earliest expiration time. This is a drop in conversion, and therefore semantics remain untouched. The runtime overhead of cached rbtrees is be pretty much the same as the current head->next method, noting that when removing the leftmost node, a common operation for the timerqueue, the rb_next(leftmost) is O(1) as well, so the next timer will either be the right node or its parent. Therefore no extra pointer chasing. Finally, the size of the struct timerqueue_head remains the same. Passes several hours of rcutorture.
Showing the changes to include/linux/timerqueue.h (1 of 2 files). Show all
Unified · Split
| @@ -12,8 +12,7 @@ struct timerqueue_node { · 11 unmodified lines | |||
| 12 | }; | 12 | }; |
| 13 | 13 | ||
| 14 | struct timerqueue_head { | 14 | struct timerqueue_head { |
| 15 | struct rb_root head; | 15 | struct rb_root_cached rb_root; |
| 16 | struct timerqueue_node *next; | ||
| 17 | }; | 16 | }; |
| 18 | 17 | ||
| 19 | 18 | ||
| @@ -29,13 +28,14 @@ extern struct timerqueue_node *timerqueue_iterate_next( · 9 unmodified lines | |||
| 29 | * | 28 | * |
| 30 | * @head: head of timerqueue | 29 | * @head: head of timerqueue |
| 31 | * | 30 | * |
| 32 | * Returns a pointer to the timer node that has the | 31 | * Returns a pointer to the timer node that has the earliest expiration time. |
| 33 | * earliest expiration time. | ||
| 34 | */ | 32 | */ |
| 35 | static inline | 33 | static inline |
| 36 | struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head) | 34 | struct timerqueue_node *timerqueue_getnext(struct timerqueue_head *head) |
| 37 | { | 35 | { |
| 38 | return head->next; | 36 | struct rb_node *leftmost = rb_first_cached(&head->rb_root); |
| 37 | |||
| 38 | return rb_entry(leftmost, struct timerqueue_node, node); | ||
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | static inline void timerqueue_init(struct timerqueue_node *node) | 41 | static inline void timerqueue_init(struct timerqueue_node *node) |
| @@ -45,7 +45,6 @@ static inline void timerqueue_init(struct timerqueue_node *node) · 3 unmodified lines | |||
| 45 | 45 | ||
| 46 | static inline void timerqueue_init_head(struct timerqueue_head *head) | 46 | static inline void timerqueue_init_head(struct timerqueue_head *head) |
| 47 | { | 47 | { |
| 48 | head->head = RB_ROOT; | 48 | head->rb_root = RB_ROOT_CACHED; |
| 49 | head->next = NULL; | ||
| 50 | } | 49 | } |
| 51 | #endif /* _LINUX_TIMERQUEUE_H */ | 50 | #endif /* _LINUX_TIMERQUEUE_H */ |