1
2
3
4
5
6
7
8
9
10
11
12#include <linux/bug.h>
13#include <linux/timerqueue.h>
14#include <linux/rbtree.h>
15#include <linux/export.h>
16
17
18
19
20
21
22
23
24
25
26
27bool timerqueue_add(struct timerqueue_head *head, struct timerqueue_node *node)
28{
29 struct rb_node **p = &head->head.rb_node;
30 struct rb_node *parent = NULL;
31 struct timerqueue_node *ptr;
32
33
34 WARN_ON_ONCE(!RB_EMPTY_NODE(&node->node));
35
36 while (*p) {
37 parent = *p;
38 ptr = rb_entry(parent, struct timerqueue_node, node);
39 if (node->expires < ptr->expires)
40 p = &(*p)->rb_left;
41 else
42 p = &(*p)->rb_right;
43 }
44 rb_link_node(&node->node, parent, p);
45 rb_insert_color(&node->node, &head->head);
46
47 if (!head->next || node->expires < head->next->expires) {
48 head->next = node;
49 return true;
50 }
51 return false;
52}
53EXPORT_SYMBOL_GPL(timerqueue_add);
54
55
56
57
58
59
60
61
62
63
64bool timerqueue_del(struct timerqueue_head *head, struct timerqueue_node *node)
65{
66 WARN_ON_ONCE(RB_EMPTY_NODE(&node->node));
67
68
69 if (head->next == node) {
70 struct rb_node *rbn = rb_next(&node->node);
71
72 head->next = rb_entry_safe(rbn, struct timerqueue_node, node);
73 }
74 rb_erase(&node->node, &head->head);
75 RB_CLEAR_NODE(&node->node);
76 return head->next != NULL;
77}
78EXPORT_SYMBOL_GPL(timerqueue_del);
79
80
81
82
83
84
85
86
87
88
89struct timerqueue_node *timerqueue_iterate_next(struct timerqueue_node *node)
90{
91 struct rb_node *next;
92
93 if (!node)
94 return NULL;
95 next = rb_next(&node->node);
96 if (!next)
97 return NULL;
98 return container_of(next, struct timerqueue_node, node);
99}
100EXPORT_SYMBOL_GPL(timerqueue_iterate_next);
101