Commit | Line | Data |
---|---|---|
8c0b8894 PP |
1 | /* |
2 | * clock-class-priority-map.c | |
3 | * | |
4 | * Copyright 2017 Philippe Proulx <pproulx@efficios.com> | |
5 | * | |
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 | * of this software and associated documentation files (the "Software"), to deal | |
8 | * in the Software without restriction, including without limitation the rights | |
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | * copies of the Software, and to permit persons to whom the Software is | |
11 | * furnished to do so, subject to the following conditions: | |
12 | * | |
13 | * The above copyright notice and this permission notice shall be included in | |
14 | * all copies or substantial portions of the Software. | |
15 | * | |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
22 | * SOFTWARE. | |
23 | */ | |
24 | ||
330cb9e0 PP |
25 | #define BT_LOG_TAG "CC-PRIO-MAP" |
26 | #include <babeltrace/lib-logging-internal.h> | |
27 | ||
8c0b8894 PP |
28 | #include <babeltrace/graph/clock-class-priority-map.h> |
29 | #include <babeltrace/graph/clock-class-priority-map-internal.h> | |
30 | #include <babeltrace/ctf-ir/clock-class.h> | |
31 | #include <babeltrace/ctf-ir/clock-class-internal.h> | |
32 | #include <babeltrace/babeltrace-internal.h> | |
3d9990ac | 33 | #include <babeltrace/compiler-internal.h> |
8c0b8894 | 34 | #include <babeltrace/ref.h> |
8b45963b PP |
35 | #include <babeltrace/assert-internal.h> |
36 | #include <babeltrace/assert-pre-internal.h> | |
9ac68eb1 | 37 | #include <stdint.h> |
330cb9e0 | 38 | #include <inttypes.h> |
8c0b8894 PP |
39 | #include <glib.h> |
40 | ||
41 | static | |
42 | void bt_clock_class_priority_map_destroy(struct bt_object *obj) | |
43 | { | |
44 | struct bt_clock_class_priority_map *cc_prio_map = (void *) obj; | |
45 | ||
330cb9e0 PP |
46 | BT_LOGD("Destroying component class priority map object: addr=%p", |
47 | cc_prio_map); | |
48 | ||
8c0b8894 | 49 | if (cc_prio_map->entries) { |
330cb9e0 | 50 | BT_LOGD("Putting clock classes."); |
8c0b8894 PP |
51 | g_ptr_array_free(cc_prio_map->entries, TRUE); |
52 | } | |
53 | ||
54 | if (cc_prio_map->prios) { | |
55 | g_hash_table_destroy(cc_prio_map->prios); | |
56 | } | |
57 | ||
58 | g_free(cc_prio_map); | |
59 | } | |
60 | ||
61 | struct bt_clock_class_priority_map *bt_clock_class_priority_map_create() | |
62 | { | |
63 | struct bt_clock_class_priority_map *cc_prio_map = NULL; | |
64 | ||
330cb9e0 PP |
65 | BT_LOGD_STR("Creating clock class priority map object."); |
66 | ||
8c0b8894 PP |
67 | cc_prio_map = g_new0(struct bt_clock_class_priority_map, 1); |
68 | if (!cc_prio_map) { | |
330cb9e0 | 69 | BT_LOGE_STR("Failed to allocate one clock class priority map."); |
8c0b8894 PP |
70 | goto error; |
71 | } | |
72 | ||
1d7bf349 PP |
73 | bt_object_init_shared(&cc_prio_map->base, |
74 | bt_clock_class_priority_map_destroy); | |
8c0b8894 PP |
75 | cc_prio_map->entries = g_ptr_array_new_with_free_func( |
76 | (GDestroyNotify) bt_put); | |
77 | if (!cc_prio_map->entries) { | |
330cb9e0 | 78 | BT_LOGE_STR("Failed to allocate a GPtrArray."); |
8c0b8894 PP |
79 | goto error; |
80 | } | |
81 | ||
82 | cc_prio_map->prios = g_hash_table_new_full(g_direct_hash, | |
83 | g_direct_equal, NULL, (GDestroyNotify) g_free); | |
84 | if (!cc_prio_map->entries) { | |
330cb9e0 | 85 | BT_LOGE_STR("Failed to allocate a GHashTable."); |
8c0b8894 PP |
86 | goto error; |
87 | } | |
88 | ||
330cb9e0 PP |
89 | BT_LOGD("Created clock class priority map object: addr=%p", |
90 | cc_prio_map); | |
8c0b8894 PP |
91 | goto end; |
92 | ||
93 | error: | |
94 | BT_PUT(cc_prio_map); | |
95 | ||
96 | end: | |
97 | return cc_prio_map; | |
98 | } | |
99 | ||
544d0515 | 100 | int64_t bt_clock_class_priority_map_get_clock_class_count( |
8c0b8894 PP |
101 | struct bt_clock_class_priority_map *cc_prio_map) |
102 | { | |
8b45963b PP |
103 | BT_ASSERT_PRE_NON_NULL(cc_prio_map, "Clock class priority map"); |
104 | return (int64_t) cc_prio_map->entries->len; | |
8c0b8894 PP |
105 | } |
106 | ||
5fe68922 | 107 | struct bt_clock_class *bt_clock_class_priority_map_borrow_clock_class_by_index( |
8c0b8894 | 108 | struct bt_clock_class_priority_map *cc_prio_map, |
9ac68eb1 | 109 | uint64_t index) |
8c0b8894 | 110 | { |
8b45963b PP |
111 | BT_ASSERT_PRE_NON_NULL(cc_prio_map, "Clock class priority map"); |
112 | BT_ASSERT_PRE(index < cc_prio_map->entries->len, | |
113 | "Index is out of bounds: index=%" PRIu64 ", count=%" PRIu64, | |
114 | index, cc_prio_map->entries->len); | |
5fe68922 | 115 | return g_ptr_array_index(cc_prio_map->entries, index); |
8c0b8894 PP |
116 | } |
117 | ||
5fe68922 | 118 | struct bt_clock_class *bt_clock_class_priority_map_borrow_clock_class_by_name( |
8c0b8894 PP |
119 | struct bt_clock_class_priority_map *cc_prio_map, |
120 | const char *name) | |
121 | { | |
122 | size_t i; | |
839d52a5 | 123 | struct bt_clock_class *clock_class = NULL; |
8c0b8894 | 124 | |
8b45963b PP |
125 | BT_ASSERT_PRE_NON_NULL(cc_prio_map, "Clock class priority map"); |
126 | BT_ASSERT_PRE_NON_NULL(name, "Name"); | |
8c0b8894 PP |
127 | |
128 | for (i = 0; i < cc_prio_map->entries->len; i++) { | |
839d52a5 | 129 | struct bt_clock_class *cur_cc = |
8c0b8894 | 130 | g_ptr_array_index(cc_prio_map->entries, i); |
8c0b8894 | 131 | const char *cur_cc_name = |
839d52a5 | 132 | bt_clock_class_get_name(cur_cc); |
8c0b8894 | 133 | |
8b45963b | 134 | BT_ASSERT(cur_cc_name); |
8c0b8894 PP |
135 | |
136 | if (strcmp(cur_cc_name, name) == 0) { | |
5fe68922 | 137 | clock_class = cur_cc; |
8c0b8894 PP |
138 | goto end; |
139 | } | |
140 | } | |
141 | ||
142 | end: | |
143 | return clock_class; | |
144 | } | |
145 | ||
146 | ||
147 | struct clock_class_prio { | |
148 | uint64_t prio; | |
839d52a5 | 149 | struct bt_clock_class *clock_class; |
8c0b8894 PP |
150 | }; |
151 | ||
152 | static | |
153 | void current_highest_prio_gh_func(gpointer key, gpointer value, | |
154 | gpointer user_data) | |
155 | { | |
156 | struct clock_class_prio *func_data = user_data; | |
157 | uint64_t *prio = value; | |
158 | ||
159 | if (*prio <= func_data->prio) { | |
160 | func_data->prio = *prio; | |
161 | func_data->clock_class = key; | |
162 | } | |
163 | } | |
164 | ||
165 | static | |
839d52a5 | 166 | struct clock_class_prio bt_clock_class_priority_map_current_highest_prio( |
8c0b8894 PP |
167 | struct bt_clock_class_priority_map *cc_prio_map) |
168 | { | |
169 | struct clock_class_prio func_data = { | |
170 | .prio = -1ULL, | |
171 | .clock_class = NULL, | |
172 | }; | |
173 | ||
174 | g_hash_table_foreach(cc_prio_map->prios, current_highest_prio_gh_func, | |
175 | &func_data); | |
176 | return func_data; | |
177 | } | |
178 | ||
839d52a5 | 179 | struct bt_clock_class * |
5fe68922 | 180 | bt_clock_class_priority_map_borrow_highest_priority_clock_class( |
8c0b8894 PP |
181 | struct bt_clock_class_priority_map *cc_prio_map) |
182 | { | |
8b45963b | 183 | BT_ASSERT_PRE_NON_NULL(cc_prio_map, "Clock class priority map"); |
5fe68922 | 184 | return cc_prio_map->highest_prio_cc; |
8c0b8894 PP |
185 | } |
186 | ||
187 | int bt_clock_class_priority_map_get_clock_class_priority( | |
188 | struct bt_clock_class_priority_map *cc_prio_map, | |
839d52a5 | 189 | struct bt_clock_class *clock_class, uint64_t *priority) |
8c0b8894 PP |
190 | { |
191 | int ret = 0; | |
192 | uint64_t *prio; | |
193 | ||
8b45963b PP |
194 | BT_ASSERT_PRE_NON_NULL(cc_prio_map, "Clock class priority map"); |
195 | BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); | |
196 | BT_ASSERT_PRE_NON_NULL(priority, "Priority"); | |
8c0b8894 PP |
197 | prio = g_hash_table_lookup(cc_prio_map->prios, clock_class); |
198 | if (!prio) { | |
330cb9e0 PP |
199 | BT_LOGV("Clock class does not exist in clock class priority map: " |
200 | "cc-prio-map-addr=%p, clock-class-addr=%p, " | |
201 | "clock-class-name=\"%s\"", | |
202 | cc_prio_map, clock_class, | |
839d52a5 | 203 | bt_clock_class_get_name(clock_class)); |
8c0b8894 PP |
204 | ret = -1; |
205 | goto end; | |
206 | } | |
207 | ||
208 | *priority = *prio; | |
209 | ||
210 | end: | |
211 | return ret; | |
212 | } | |
213 | ||
214 | int bt_clock_class_priority_map_add_clock_class( | |
215 | struct bt_clock_class_priority_map *cc_prio_map, | |
839d52a5 | 216 | struct bt_clock_class *clock_class, uint64_t priority) |
8c0b8894 PP |
217 | { |
218 | int ret = 0; | |
219 | uint64_t *prio_ptr = NULL; | |
220 | struct clock_class_prio cc_prio; | |
221 | ||
222 | // FIXME when available: check | |
839d52a5 | 223 | // bt_clock_class_is_valid(clock_class) |
8b45963b PP |
224 | BT_ASSERT_PRE_NON_NULL(cc_prio_map, "Clock class priority map"); |
225 | BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); | |
226 | BT_ASSERT_PRE_HOT(cc_prio_map, "Clock class priority map", ""); | |
8c0b8894 | 227 | |
a03dd9f3 | 228 | /* Check for existing clock class */ |
8c0b8894 PP |
229 | prio_ptr = g_hash_table_lookup(cc_prio_map->prios, clock_class); |
230 | if (prio_ptr) { | |
a03dd9f3 | 231 | *prio_ptr = priority; |
8c0b8894 | 232 | prio_ptr = NULL; |
a03dd9f3 | 233 | goto set_highest_prio; |
8c0b8894 PP |
234 | } |
235 | ||
236 | prio_ptr = g_new(uint64_t, 1); | |
237 | if (!prio_ptr) { | |
330cb9e0 | 238 | BT_LOGE_STR("Failed to allocate a uint64_t."); |
8c0b8894 PP |
239 | ret = -1; |
240 | goto end; | |
241 | } | |
242 | ||
243 | *prio_ptr = priority; | |
244 | bt_get(clock_class); | |
245 | g_ptr_array_add(cc_prio_map->entries, clock_class); | |
246 | g_hash_table_insert(cc_prio_map->prios, clock_class, prio_ptr); | |
247 | prio_ptr = NULL; | |
a03dd9f3 PP |
248 | |
249 | set_highest_prio: | |
839d52a5 | 250 | cc_prio = bt_clock_class_priority_map_current_highest_prio( |
8c0b8894 | 251 | cc_prio_map); |
8b45963b | 252 | BT_ASSERT(cc_prio.clock_class); |
8c0b8894 | 253 | cc_prio_map->highest_prio_cc = cc_prio.clock_class; |
330cb9e0 PP |
254 | BT_LOGV("Added clock class to clock class priority map: " |
255 | "cc-prio-map-addr=%p, added-clock-class-addr=%p, " | |
256 | "added-clock-class-name=\"%s\", " | |
257 | "highest-prio-clock-class-addr=%p, " | |
258 | "highest-prio-clock-class-name=\"%s\"", | |
259 | cc_prio_map, clock_class, | |
839d52a5 | 260 | bt_clock_class_get_name(clock_class), |
330cb9e0 | 261 | cc_prio.clock_class, |
839d52a5 | 262 | bt_clock_class_get_name(cc_prio.clock_class)); |
8c0b8894 PP |
263 | |
264 | end: | |
be7e55c5 | 265 | g_free(prio_ptr); |
8c0b8894 PP |
266 | |
267 | return ret; | |
268 | } | |
7b5d7f76 PP |
269 | |
270 | struct bt_clock_class_priority_map *bt_clock_class_priority_map_copy( | |
271 | struct bt_clock_class_priority_map *orig_cc_prio_map) | |
272 | { | |
273 | struct bt_clock_class_priority_map *cc_prio_map; | |
274 | size_t i; | |
275 | ||
276 | cc_prio_map = bt_clock_class_priority_map_create(); | |
277 | if (!cc_prio_map) { | |
8b45963b | 278 | BT_LOGE_STR("Cannot create empty clock class priority map."); |
7b5d7f76 PP |
279 | goto error; |
280 | } | |
281 | ||
282 | for (i = 0; i < orig_cc_prio_map->entries->len; i++) { | |
839d52a5 | 283 | struct bt_clock_class *clock_class = |
7b5d7f76 PP |
284 | g_ptr_array_index(orig_cc_prio_map->entries, i); |
285 | uint64_t *prio = g_hash_table_lookup(orig_cc_prio_map->prios, | |
286 | clock_class); | |
287 | int ret = bt_clock_class_priority_map_add_clock_class( | |
288 | cc_prio_map, clock_class, *prio); | |
289 | ||
290 | if (ret) { | |
330cb9e0 PP |
291 | BT_LOGE("Cannot add clock class to clock class priority map copy: " |
292 | "cc-prio-map-copy-addr=%p, clock-class-addr=%p, " | |
293 | "clock-class-name=\"%s\"", | |
294 | cc_prio_map, clock_class, | |
839d52a5 | 295 | bt_clock_class_get_name(clock_class)); |
7b5d7f76 PP |
296 | goto error; |
297 | } | |
298 | } | |
299 | ||
300 | cc_prio_map->highest_prio_cc = orig_cc_prio_map->highest_prio_cc; | |
330cb9e0 PP |
301 | BT_LOGD("Copied clock class priority map: " |
302 | "original-addr=%p, copy-addr=%p", | |
303 | orig_cc_prio_map, cc_prio_map); | |
7b5d7f76 PP |
304 | goto end; |
305 | ||
306 | error: | |
307 | BT_PUT(cc_prio_map); | |
308 | ||
309 | end: | |
310 | return cc_prio_map; | |
311 | } |