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> |
9ac68eb1 | 35 | #include <stdint.h> |
330cb9e0 | 36 | #include <inttypes.h> |
8c0b8894 PP |
37 | #include <glib.h> |
38 | ||
39 | static | |
40 | void bt_clock_class_priority_map_destroy(struct bt_object *obj) | |
41 | { | |
42 | struct bt_clock_class_priority_map *cc_prio_map = (void *) obj; | |
43 | ||
44 | if (!cc_prio_map) { | |
45 | return; | |
46 | } | |
47 | ||
330cb9e0 PP |
48 | BT_LOGD("Destroying component class priority map object: addr=%p", |
49 | cc_prio_map); | |
50 | ||
8c0b8894 | 51 | if (cc_prio_map->entries) { |
330cb9e0 | 52 | BT_LOGD("Putting clock classes."); |
8c0b8894 PP |
53 | g_ptr_array_free(cc_prio_map->entries, TRUE); |
54 | } | |
55 | ||
56 | if (cc_prio_map->prios) { | |
57 | g_hash_table_destroy(cc_prio_map->prios); | |
58 | } | |
59 | ||
60 | g_free(cc_prio_map); | |
61 | } | |
62 | ||
63 | struct bt_clock_class_priority_map *bt_clock_class_priority_map_create() | |
64 | { | |
65 | struct bt_clock_class_priority_map *cc_prio_map = NULL; | |
66 | ||
330cb9e0 PP |
67 | BT_LOGD_STR("Creating clock class priority map object."); |
68 | ||
8c0b8894 PP |
69 | cc_prio_map = g_new0(struct bt_clock_class_priority_map, 1); |
70 | if (!cc_prio_map) { | |
330cb9e0 | 71 | BT_LOGE_STR("Failed to allocate one clock class priority map."); |
8c0b8894 PP |
72 | goto error; |
73 | } | |
74 | ||
75 | bt_object_init(cc_prio_map, bt_clock_class_priority_map_destroy); | |
76 | cc_prio_map->entries = g_ptr_array_new_with_free_func( | |
77 | (GDestroyNotify) bt_put); | |
78 | if (!cc_prio_map->entries) { | |
330cb9e0 | 79 | BT_LOGE_STR("Failed to allocate a GPtrArray."); |
8c0b8894 PP |
80 | goto error; |
81 | } | |
82 | ||
83 | cc_prio_map->prios = g_hash_table_new_full(g_direct_hash, | |
84 | g_direct_equal, NULL, (GDestroyNotify) g_free); | |
85 | if (!cc_prio_map->entries) { | |
330cb9e0 | 86 | BT_LOGE_STR("Failed to allocate a GHashTable."); |
8c0b8894 PP |
87 | goto error; |
88 | } | |
89 | ||
330cb9e0 PP |
90 | BT_LOGD("Created clock class priority map object: addr=%p", |
91 | cc_prio_map); | |
8c0b8894 PP |
92 | goto end; |
93 | ||
94 | error: | |
95 | BT_PUT(cc_prio_map); | |
96 | ||
97 | end: | |
98 | return cc_prio_map; | |
99 | } | |
100 | ||
544d0515 | 101 | int64_t bt_clock_class_priority_map_get_clock_class_count( |
8c0b8894 PP |
102 | struct bt_clock_class_priority_map *cc_prio_map) |
103 | { | |
9ac68eb1 | 104 | int64_t ret = (int64_t) -1; |
8c0b8894 PP |
105 | |
106 | if (!cc_prio_map) { | |
330cb9e0 | 107 | BT_LOGW_STR("Invalid parameter: clock class priority map is NULL."); |
8c0b8894 PP |
108 | goto end; |
109 | } | |
110 | ||
544d0515 | 111 | ret = (int64_t) cc_prio_map->entries->len; |
8c0b8894 PP |
112 | |
113 | end: | |
114 | return ret; | |
115 | } | |
116 | ||
9ac68eb1 | 117 | struct bt_ctf_clock_class *bt_clock_class_priority_map_get_clock_class_by_index( |
8c0b8894 | 118 | struct bt_clock_class_priority_map *cc_prio_map, |
9ac68eb1 | 119 | uint64_t index) |
8c0b8894 PP |
120 | { |
121 | struct bt_ctf_clock_class *clock_class = NULL; | |
122 | ||
330cb9e0 PP |
123 | if (!cc_prio_map) { |
124 | BT_LOGW_STR("Invalid parameter: clock class priority map is NULL."); | |
125 | goto end; | |
126 | } | |
127 | ||
128 | if (index >= cc_prio_map->entries->len) { | |
129 | BT_LOGW("Invalid parameter: index is out of bounds: " | |
130 | "addr=%p, index=%" PRIu64 ", count=%u", | |
131 | cc_prio_map, index, cc_prio_map->entries->len); | |
8c0b8894 PP |
132 | goto end; |
133 | } | |
134 | ||
135 | clock_class = g_ptr_array_index(cc_prio_map->entries, index); | |
136 | bt_get(clock_class); | |
137 | ||
138 | end: | |
139 | return clock_class; | |
140 | } | |
141 | ||
142 | struct bt_ctf_clock_class *bt_clock_class_priority_map_get_clock_class_by_name( | |
143 | struct bt_clock_class_priority_map *cc_prio_map, | |
144 | const char *name) | |
145 | { | |
146 | size_t i; | |
147 | struct bt_ctf_clock_class *clock_class = NULL; | |
148 | ||
330cb9e0 PP |
149 | if (!cc_prio_map) { |
150 | BT_LOGW_STR("Invalid parameter: clock class priority map is NULL."); | |
151 | goto end; | |
152 | } | |
153 | ||
154 | if (!name) { | |
155 | BT_LOGW_STR("Invalid parameter: name is NULL."); | |
8c0b8894 PP |
156 | goto end; |
157 | } | |
158 | ||
159 | for (i = 0; i < cc_prio_map->entries->len; i++) { | |
160 | struct bt_ctf_clock_class *cur_cc = | |
161 | g_ptr_array_index(cc_prio_map->entries, i); | |
8c0b8894 | 162 | const char *cur_cc_name = |
330cb9e0 | 163 | bt_ctf_clock_class_get_name(cur_cc); |
8c0b8894 | 164 | |
330cb9e0 | 165 | assert(cur_cc_name); |
8c0b8894 PP |
166 | |
167 | if (strcmp(cur_cc_name, name) == 0) { | |
168 | clock_class = bt_get(cur_cc); | |
169 | goto end; | |
170 | } | |
171 | } | |
172 | ||
173 | end: | |
174 | return clock_class; | |
175 | } | |
176 | ||
177 | ||
178 | struct clock_class_prio { | |
179 | uint64_t prio; | |
180 | struct bt_ctf_clock_class *clock_class; | |
181 | }; | |
182 | ||
183 | static | |
184 | void current_highest_prio_gh_func(gpointer key, gpointer value, | |
185 | gpointer user_data) | |
186 | { | |
187 | struct clock_class_prio *func_data = user_data; | |
188 | uint64_t *prio = value; | |
189 | ||
190 | if (*prio <= func_data->prio) { | |
191 | func_data->prio = *prio; | |
192 | func_data->clock_class = key; | |
193 | } | |
194 | } | |
195 | ||
196 | static | |
197 | struct clock_class_prio bt_ctf_clock_class_priority_map_current_highest_prio( | |
198 | struct bt_clock_class_priority_map *cc_prio_map) | |
199 | { | |
200 | struct clock_class_prio func_data = { | |
201 | .prio = -1ULL, | |
202 | .clock_class = NULL, | |
203 | }; | |
204 | ||
205 | g_hash_table_foreach(cc_prio_map->prios, current_highest_prio_gh_func, | |
206 | &func_data); | |
207 | return func_data; | |
208 | } | |
209 | ||
210 | struct bt_ctf_clock_class * | |
211 | bt_clock_class_priority_map_get_highest_priority_clock_class( | |
212 | struct bt_clock_class_priority_map *cc_prio_map) | |
213 | { | |
214 | struct bt_ctf_clock_class *clock_class = NULL; | |
215 | ||
216 | if (!cc_prio_map) { | |
330cb9e0 | 217 | BT_LOGW_STR("Invalid parameter: clock class priority map is NULL."); |
8c0b8894 PP |
218 | goto end; |
219 | } | |
220 | ||
221 | clock_class = bt_get(cc_prio_map->highest_prio_cc); | |
222 | ||
223 | end: | |
224 | return clock_class; | |
225 | } | |
226 | ||
227 | int bt_clock_class_priority_map_get_clock_class_priority( | |
228 | struct bt_clock_class_priority_map *cc_prio_map, | |
229 | struct bt_ctf_clock_class *clock_class, uint64_t *priority) | |
230 | { | |
231 | int ret = 0; | |
232 | uint64_t *prio; | |
233 | ||
330cb9e0 PP |
234 | if (!cc_prio_map) { |
235 | BT_LOGW_STR("Invalid parameter: clock class priority map is NULL."); | |
236 | ret = -1; | |
237 | goto end; | |
238 | } | |
239 | ||
240 | if (!clock_class) { | |
241 | BT_LOGW_STR("Invalid parameter: clock class is NULL."); | |
242 | ret = -1; | |
243 | goto end; | |
244 | } | |
245 | ||
246 | if (!priority) { | |
247 | BT_LOGW_STR("Invalid parameter: priority is NULL."); | |
8c0b8894 PP |
248 | ret = -1; |
249 | goto end; | |
250 | } | |
251 | ||
252 | prio = g_hash_table_lookup(cc_prio_map->prios, clock_class); | |
253 | if (!prio) { | |
330cb9e0 PP |
254 | BT_LOGV("Clock class does not exist in clock class priority map: " |
255 | "cc-prio-map-addr=%p, clock-class-addr=%p, " | |
256 | "clock-class-name=\"%s\"", | |
257 | cc_prio_map, clock_class, | |
258 | bt_ctf_clock_class_get_name(clock_class)); | |
8c0b8894 PP |
259 | ret = -1; |
260 | goto end; | |
261 | } | |
262 | ||
263 | *priority = *prio; | |
264 | ||
265 | end: | |
266 | return ret; | |
267 | } | |
268 | ||
269 | int bt_clock_class_priority_map_add_clock_class( | |
270 | struct bt_clock_class_priority_map *cc_prio_map, | |
271 | struct bt_ctf_clock_class *clock_class, uint64_t priority) | |
272 | { | |
273 | int ret = 0; | |
274 | uint64_t *prio_ptr = NULL; | |
275 | struct clock_class_prio cc_prio; | |
276 | ||
277 | // FIXME when available: check | |
278 | // bt_ctf_clock_class_is_valid(clock_class) | |
330cb9e0 PP |
279 | if (!cc_prio_map) { |
280 | BT_LOGW_STR("Invalid parameter: clock class priority map is NULL."); | |
281 | ret = -1; | |
282 | goto end; | |
283 | } | |
284 | ||
285 | if (!clock_class) { | |
286 | BT_LOGW_STR("Invalid parameter: clock class is NULL."); | |
287 | ret = -1; | |
288 | goto end; | |
289 | } | |
290 | ||
291 | if (cc_prio_map->frozen) { | |
292 | BT_LOGW("Invalid parameter: clock class priority map is frozen: " | |
293 | "addr=%p", cc_prio_map); | |
8c0b8894 PP |
294 | ret = -1; |
295 | goto end; | |
296 | } | |
297 | ||
a03dd9f3 | 298 | /* Check for existing clock class */ |
8c0b8894 PP |
299 | prio_ptr = g_hash_table_lookup(cc_prio_map->prios, clock_class); |
300 | if (prio_ptr) { | |
a03dd9f3 | 301 | *prio_ptr = priority; |
8c0b8894 | 302 | prio_ptr = NULL; |
a03dd9f3 | 303 | goto set_highest_prio; |
8c0b8894 PP |
304 | } |
305 | ||
306 | prio_ptr = g_new(uint64_t, 1); | |
307 | if (!prio_ptr) { | |
330cb9e0 | 308 | BT_LOGE_STR("Failed to allocate a uint64_t."); |
8c0b8894 PP |
309 | ret = -1; |
310 | goto end; | |
311 | } | |
312 | ||
313 | *prio_ptr = priority; | |
314 | bt_get(clock_class); | |
315 | g_ptr_array_add(cc_prio_map->entries, clock_class); | |
316 | g_hash_table_insert(cc_prio_map->prios, clock_class, prio_ptr); | |
317 | prio_ptr = NULL; | |
a03dd9f3 PP |
318 | |
319 | set_highest_prio: | |
8c0b8894 PP |
320 | cc_prio = bt_ctf_clock_class_priority_map_current_highest_prio( |
321 | cc_prio_map); | |
322 | assert(cc_prio.clock_class); | |
323 | cc_prio_map->highest_prio_cc = cc_prio.clock_class; | |
330cb9e0 PP |
324 | BT_LOGV("Added clock class to clock class priority map: " |
325 | "cc-prio-map-addr=%p, added-clock-class-addr=%p, " | |
326 | "added-clock-class-name=\"%s\", " | |
327 | "highest-prio-clock-class-addr=%p, " | |
328 | "highest-prio-clock-class-name=\"%s\"", | |
329 | cc_prio_map, clock_class, | |
330 | bt_ctf_clock_class_get_name(clock_class), | |
331 | cc_prio.clock_class, | |
332 | bt_ctf_clock_class_get_name(cc_prio.clock_class)); | |
8c0b8894 PP |
333 | |
334 | end: | |
335 | if (prio_ptr) { | |
336 | g_free(prio_ptr); | |
337 | } | |
338 | ||
339 | return ret; | |
340 | } | |
7b5d7f76 PP |
341 | |
342 | struct bt_clock_class_priority_map *bt_clock_class_priority_map_copy( | |
343 | struct bt_clock_class_priority_map *orig_cc_prio_map) | |
344 | { | |
345 | struct bt_clock_class_priority_map *cc_prio_map; | |
346 | size_t i; | |
347 | ||
348 | cc_prio_map = bt_clock_class_priority_map_create(); | |
349 | if (!cc_prio_map) { | |
330cb9e0 | 350 | BT_LOGW_STR("Invalid parameter: clock class priority map is NULL."); |
7b5d7f76 PP |
351 | goto error; |
352 | } | |
353 | ||
354 | for (i = 0; i < orig_cc_prio_map->entries->len; i++) { | |
355 | struct bt_ctf_clock_class *clock_class = | |
356 | g_ptr_array_index(orig_cc_prio_map->entries, i); | |
357 | uint64_t *prio = g_hash_table_lookup(orig_cc_prio_map->prios, | |
358 | clock_class); | |
359 | int ret = bt_clock_class_priority_map_add_clock_class( | |
360 | cc_prio_map, clock_class, *prio); | |
361 | ||
362 | if (ret) { | |
330cb9e0 PP |
363 | BT_LOGE("Cannot add clock class to clock class priority map copy: " |
364 | "cc-prio-map-copy-addr=%p, clock-class-addr=%p, " | |
365 | "clock-class-name=\"%s\"", | |
366 | cc_prio_map, clock_class, | |
367 | bt_ctf_clock_class_get_name(clock_class)); | |
7b5d7f76 PP |
368 | goto error; |
369 | } | |
370 | } | |
371 | ||
372 | cc_prio_map->highest_prio_cc = orig_cc_prio_map->highest_prio_cc; | |
330cb9e0 PP |
373 | BT_LOGD("Copied clock class priority map: " |
374 | "original-addr=%p, copy-addr=%p", | |
375 | orig_cc_prio_map, cc_prio_map); | |
7b5d7f76 PP |
376 | goto end; |
377 | ||
378 | error: | |
379 | BT_PUT(cc_prio_map); | |
380 | ||
381 | end: | |
382 | return cc_prio_map; | |
383 | } |