/src/open5gs/lib/core/ogs-timer.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2019 by Sukchan Lee <acetcom@gmail.com> |
3 | | * |
4 | | * This file is part of Open5GS. |
5 | | * |
6 | | * This program is free software: you can redistribute it and/or modify |
7 | | * it under the terms of the GNU Affero General Public License as published by |
8 | | * the Free Software Foundation, either version 3 of the License, or |
9 | | * (at your option) any later version. |
10 | | * |
11 | | * This program is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | * GNU General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License |
17 | | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
18 | | */ |
19 | | |
20 | | #include "ogs-core.h" |
21 | | |
22 | | #undef OGS_LOG_DOMAIN |
23 | 0 | #define OGS_LOG_DOMAIN __ogs_event_domain |
24 | | |
25 | | typedef struct ogs_timer_mgr_s { |
26 | | OGS_POOL(pool, ogs_timer_t); |
27 | | ogs_rbtree_t tree; |
28 | | } ogs_timer_mgr_t; |
29 | | |
30 | | static void add_timer_node( |
31 | | ogs_rbtree_t *tree, ogs_timer_t *timer, ogs_time_t duration) |
32 | 0 | { |
33 | 0 | ogs_rbnode_t **new = NULL; |
34 | 0 | ogs_rbnode_t *parent = NULL; |
35 | 0 | ogs_assert(tree); |
36 | 0 | ogs_assert(timer); |
37 | | |
38 | 0 | timer->timeout = ogs_get_monotonic_time() + duration; |
39 | |
|
40 | 0 | new = &tree->root; |
41 | 0 | while (*new) { |
42 | 0 | ogs_timer_t *this = ogs_rb_entry(*new, ogs_timer_t, rbnode); |
43 | |
|
44 | 0 | parent = *new; |
45 | 0 | if (timer->timeout < this->timeout) |
46 | 0 | new = &(*new)->left; |
47 | 0 | else |
48 | 0 | new = &(*new)->right; |
49 | 0 | } |
50 | |
|
51 | 0 | ogs_rbtree_link_node(timer, parent, new); |
52 | 0 | ogs_rbtree_insert_color(tree, timer); |
53 | 0 | } |
54 | | |
55 | | ogs_timer_mgr_t *ogs_timer_mgr_create(unsigned int capacity) |
56 | 0 | { |
57 | 0 | ogs_timer_mgr_t *manager = ogs_calloc(1, sizeof *manager); |
58 | 0 | if (!manager) { |
59 | 0 | ogs_error("ogs_calloc() failed"); |
60 | 0 | return NULL; |
61 | 0 | } |
62 | | |
63 | 0 | ogs_pool_init(&manager->pool, capacity); |
64 | | |
65 | 0 | return manager; |
66 | 0 | } |
67 | | |
68 | | void ogs_timer_mgr_destroy(ogs_timer_mgr_t *manager) |
69 | 0 | { |
70 | 0 | ogs_assert(manager); |
71 | | |
72 | 0 | ogs_pool_final(&manager->pool); |
73 | 0 | ogs_free(manager); |
74 | 0 | } |
75 | | |
76 | | ogs_timer_t *ogs_timer_add( |
77 | | ogs_timer_mgr_t *manager, void (*cb)(void *data), void *data) |
78 | 0 | { |
79 | 0 | ogs_timer_t *timer = NULL; |
80 | 0 | ogs_assert(manager); |
81 | | |
82 | 0 | ogs_pool_alloc(&manager->pool, &timer); |
83 | 0 | if (!timer) { |
84 | 0 | ogs_fatal("ogs_pool_alloc() failed"); |
85 | 0 | return NULL; |
86 | 0 | } |
87 | | |
88 | 0 | memset(timer, 0, sizeof *timer); |
89 | 0 | timer->cb = cb; |
90 | 0 | timer->data = data; |
91 | |
|
92 | 0 | timer->manager = manager; |
93 | |
|
94 | 0 | return timer; |
95 | 0 | } |
96 | | |
97 | | void ogs_timer_delete_debug(ogs_timer_t *timer, const char *file_line) |
98 | 0 | { |
99 | 0 | ogs_timer_mgr_t *manager; |
100 | 0 | ogs_assert(timer); |
101 | 0 | manager = timer->manager; |
102 | 0 | ogs_assert(manager); |
103 | | |
104 | 0 | ogs_timer_stop(timer); |
105 | |
|
106 | 0 | ogs_pool_free(&manager->pool, timer); |
107 | 0 | } |
108 | | |
109 | | void ogs_timer_start_debug( |
110 | | ogs_timer_t *timer, ogs_time_t duration, const char *file_line) |
111 | 0 | { |
112 | 0 | ogs_timer_mgr_t *manager = NULL; |
113 | 0 | ogs_assert(timer); |
114 | 0 | ogs_assert(duration); |
115 | | |
116 | 0 | manager = timer->manager; |
117 | 0 | ogs_assert(manager); |
118 | | |
119 | 0 | if (timer->running == true) |
120 | 0 | ogs_rbtree_delete(&manager->tree, timer); |
121 | |
|
122 | 0 | timer->running = true; |
123 | 0 | add_timer_node(&manager->tree, timer, duration); |
124 | 0 | } |
125 | | |
126 | | void ogs_timer_stop_debug(ogs_timer_t *timer, const char *file_line) |
127 | 0 | { |
128 | 0 | ogs_timer_mgr_t *manager = NULL; |
129 | 0 | ogs_assert(timer); |
130 | 0 | manager = timer->manager; |
131 | 0 | ogs_assert(manager); |
132 | | |
133 | 0 | if (timer->running == false) |
134 | 0 | return; |
135 | | |
136 | 0 | timer->running = false; |
137 | 0 | ogs_rbtree_delete(&manager->tree, timer); |
138 | 0 | } |
139 | | |
140 | | ogs_time_t ogs_timer_mgr_next(ogs_timer_mgr_t *manager) |
141 | 0 | { |
142 | 0 | ogs_time_t current; |
143 | 0 | ogs_rbnode_t *rbnode = NULL; |
144 | 0 | ogs_assert(manager); |
145 | | |
146 | 0 | current = ogs_get_monotonic_time(); |
147 | 0 | rbnode = ogs_rbtree_first(&manager->tree); |
148 | 0 | if (rbnode) { |
149 | 0 | ogs_timer_t *this = ogs_rb_entry(rbnode, ogs_timer_t, rbnode); |
150 | 0 | if (this->timeout > current) { |
151 | 0 | return (this->timeout - current); |
152 | 0 | } else { |
153 | 0 | return OGS_NO_WAIT_TIME; |
154 | 0 | } |
155 | 0 | } |
156 | | |
157 | 0 | return OGS_INFINITE_TIME; |
158 | 0 | } |
159 | | |
160 | | void ogs_timer_mgr_expire(ogs_timer_mgr_t *manager) |
161 | 0 | { |
162 | 0 | OGS_LIST(list); |
163 | 0 | ogs_lnode_t *lnode; |
164 | |
|
165 | 0 | ogs_time_t current; |
166 | 0 | ogs_rbnode_t *rbnode; |
167 | 0 | ogs_timer_t *this; |
168 | 0 | ogs_assert(manager); |
169 | | |
170 | 0 | current = ogs_get_monotonic_time(); |
171 | |
|
172 | 0 | ogs_rbtree_for_each(&manager->tree, rbnode) { |
173 | 0 | this = ogs_rb_entry(rbnode, ogs_timer_t, rbnode); |
174 | |
|
175 | 0 | if (this->timeout > current) |
176 | 0 | break; |
177 | | |
178 | 0 | ogs_list_add(&list, &this->lnode); |
179 | 0 | } |
180 | | |
181 | | /* You should not perform a delete on a timer using ogs_timer_delete() |
182 | | * in a callback function this->cb(). */ |
183 | 0 | ogs_list_for_each(&list, lnode) { |
184 | 0 | this = ogs_rb_entry(lnode, ogs_timer_t, lnode); |
185 | 0 | ogs_timer_stop(this); |
186 | 0 | if (this->cb) |
187 | 0 | this->cb(this->data); |
188 | 0 | } |
189 | 0 | } |