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> |
f6ccaed9 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 | ||
73 | bt_object_init(cc_prio_map, bt_clock_class_priority_map_destroy); | |
74 | cc_prio_map->entries = g_ptr_array_new_with_free_func( | |
75 | (GDestroyNotify) bt_put); | |
76 | if (!cc_prio_map->entries) { | |
330cb9e0 | 77 | BT_LOGE_STR("Failed to allocate a GPtrArray."); |
8c0b8894 PP |
78 | goto error; |
79 | } | |
80 | ||
81 | cc_prio_map->prios = g_hash_table_new_full(g_direct_hash, | |
82 | g_direct_equal, NULL, (GDestroyNotify) g_free); | |
83 | if (!cc_prio_map->entries) { | |
330cb9e0 | 84 | BT_LOGE_STR("Failed to allocate a GHashTable."); |
8c0b8894 PP |
85 | goto error; |
86 | } | |
87 | ||
330cb9e0 PP |
88 | BT_LOGD("Created clock class priority map object: addr=%p", |
89 | cc_prio_map); | |
8c0b8894 PP |
90 | goto end; |
91 | ||
92 | error: | |
93 | BT_PUT(cc_prio_map); | |
94 | ||
95 | end: | |
96 | return cc_prio_map; | |
97 | } | |
98 | ||
544d0515 | 99 | int64_t bt_clock_class_priority_map_get_clock_class_count( |
8c0b8894 PP |
100 | struct bt_clock_class_priority_map *cc_prio_map) |
101 | { | |
f6ccaed9 PP |
102 | BT_ASSERT_PRE_NON_NULL(cc_prio_map, "Clock class priority map"); |
103 | return (int64_t) cc_prio_map->entries->len; | |
8c0b8894 PP |
104 | } |
105 | ||
094ff7c0 | 106 | struct bt_clock_class *bt_clock_class_priority_map_borrow_clock_class_by_index( |
8c0b8894 | 107 | struct bt_clock_class_priority_map *cc_prio_map, |
9ac68eb1 | 108 | uint64_t index) |
8c0b8894 | 109 | { |
f6ccaed9 PP |
110 | BT_ASSERT_PRE_NON_NULL(cc_prio_map, "Clock class priority map"); |
111 | BT_ASSERT_PRE(index < cc_prio_map->entries->len, | |
112 | "Index is out of bounds: index=%" PRIu64 ", count=%" PRIu64, | |
113 | index, cc_prio_map->entries->len); | |
094ff7c0 | 114 | return g_ptr_array_index(cc_prio_map->entries, index); |
8c0b8894 PP |
115 | } |
116 | ||
094ff7c0 | 117 | struct bt_clock_class *bt_clock_class_priority_map_borrow_clock_class_by_name( |
8c0b8894 PP |
118 | struct bt_clock_class_priority_map *cc_prio_map, |
119 | const char *name) | |
120 | { | |
121 | size_t i; | |
50842bdc | 122 | struct bt_clock_class *clock_class = NULL; |
8c0b8894 | 123 | |
f6ccaed9 PP |
124 | BT_ASSERT_PRE_NON_NULL(cc_prio_map, "Clock class priority map"); |
125 | BT_ASSERT_PRE_NON_NULL(name, "Name"); | |
8c0b8894 PP |
126 | |
127 | for (i = 0; i < cc_prio_map->entries->len; i++) { | |
50842bdc | 128 | struct bt_clock_class *cur_cc = |
8c0b8894 | 129 | g_ptr_array_index(cc_prio_map->entries, i); |
8c0b8894 | 130 | const char *cur_cc_name = |
50842bdc | 131 | bt_clock_class_get_name(cur_cc); |
8c0b8894 | 132 | |
f6ccaed9 | 133 | BT_ASSERT(cur_cc_name); |
8c0b8894 PP |
134 | |
135 | if (strcmp(cur_cc_name, name) == 0) { | |
094ff7c0 | 136 | clock_class = cur_cc; |
8c0b8894 PP |
137 | goto end; |
138 | } | |
139 | } | |
140 | ||
141 | end: | |
142 | return clock_class; | |
143 | } | |
144 | ||
145 | ||
146 | struct clock_class_prio { | |
147 | uint64_t prio; | |
50842bdc | 148 | struct bt_clock_class *clock_class; |
8c0b8894 PP |
149 | }; |
150 | ||
151 | static | |
152 | void current_highest_prio_gh_func(gpointer key, gpointer value, | |
153 | gpointer user_data) | |
154 | { | |
155 | struct clock_class_prio *func_data = user_data; | |
156 | uint64_t *prio = value; | |
157 | ||
158 | if (*prio <= func_data->prio) { | |
159 | func_data->prio = *prio; | |
160 | func_data->clock_class = key; | |
161 | } | |
162 | } | |
163 | ||
164 | static | |
50842bdc | 165 | struct clock_class_prio bt_clock_class_priority_map_current_highest_prio( |
8c0b8894 PP |
166 | struct bt_clock_class_priority_map *cc_prio_map) |
167 | { | |
168 | struct clock_class_prio func_data = { | |
169 | .prio = -1ULL, | |
170 | .clock_class = NULL, | |
171 | }; | |
172 | ||
173 | g_hash_table_foreach(cc_prio_map->prios, current_highest_prio_gh_func, | |
174 | &func_data); | |
175 | return func_data; | |
176 | } | |
177 | ||
50842bdc | 178 | struct bt_clock_class * |
094ff7c0 | 179 | bt_clock_class_priority_map_borrow_highest_priority_clock_class( |
8c0b8894 PP |
180 | struct bt_clock_class_priority_map *cc_prio_map) |
181 | { | |
f6ccaed9 | 182 | BT_ASSERT_PRE_NON_NULL(cc_prio_map, "Clock class priority map"); |
094ff7c0 | 183 | return cc_prio_map->highest_prio_cc; |
8c0b8894 PP |
184 | } |
185 | ||
186 | int bt_clock_class_priority_map_get_clock_class_priority( | |
187 | struct bt_clock_class_priority_map *cc_prio_map, | |
50842bdc | 188 | struct bt_clock_class *clock_class, uint64_t *priority) |
8c0b8894 PP |
189 | { |
190 | int ret = 0; | |
191 | uint64_t *prio; | |
192 | ||
f6ccaed9 PP |
193 | BT_ASSERT_PRE_NON_NULL(cc_prio_map, "Clock class priority map"); |
194 | BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); | |
195 | BT_ASSERT_PRE_NON_NULL(priority, "Priority"); | |
8c0b8894 PP |
196 | prio = g_hash_table_lookup(cc_prio_map->prios, clock_class); |
197 | if (!prio) { | |
330cb9e0 PP |
198 | BT_LOGV("Clock class does not exist in clock class priority map: " |
199 | "cc-prio-map-addr=%p, clock-class-addr=%p, " | |
200 | "clock-class-name=\"%s\"", | |
201 | cc_prio_map, clock_class, | |
50842bdc | 202 | bt_clock_class_get_name(clock_class)); |
8c0b8894 PP |
203 | ret = -1; |
204 | goto end; | |
205 | } | |
206 | ||
207 | *priority = *prio; | |
208 | ||
209 | end: | |
210 | return ret; | |
211 | } | |
212 | ||
213 | int bt_clock_class_priority_map_add_clock_class( | |
214 | struct bt_clock_class_priority_map *cc_prio_map, | |
50842bdc | 215 | struct bt_clock_class *clock_class, uint64_t priority) |
8c0b8894 PP |
216 | { |
217 | int ret = 0; | |
218 | uint64_t *prio_ptr = NULL; | |
219 | struct clock_class_prio cc_prio; | |
220 | ||
221 | // FIXME when available: check | |
50842bdc | 222 | // bt_clock_class_is_valid(clock_class) |
f6ccaed9 PP |
223 | BT_ASSERT_PRE_NON_NULL(cc_prio_map, "Clock class priority map"); |
224 | BT_ASSERT_PRE_NON_NULL(clock_class, "Clock class"); | |
225 | BT_ASSERT_PRE_HOT(cc_prio_map, "Clock class priority map", ""); | |
8c0b8894 | 226 | |
a03dd9f3 | 227 | /* Check for existing clock class */ |
8c0b8894 PP |
228 | prio_ptr = g_hash_table_lookup(cc_prio_map->prios, clock_class); |
229 | if (prio_ptr) { | |
a03dd9f3 | 230 | *prio_ptr = priority; |
8c0b8894 | 231 | prio_ptr = NULL; |
a03dd9f3 | 232 | goto set_highest_prio; |
8c0b8894 PP |
233 | } |
234 | ||
235 | prio_ptr = g_new(uint64_t, 1); | |
236 | if (!prio_ptr) { | |
330cb9e0 | 237 | BT_LOGE_STR("Failed to allocate a uint64_t."); |
8c0b8894 PP |
238 | ret = -1; |
239 | goto end; | |
240 | } | |
241 | ||
242 | *prio_ptr = priority; | |
243 | bt_get(clock_class); | |
244 | g_ptr_array_add(cc_prio_map->entries, clock_class); | |
245 | g_hash_table_insert(cc_prio_map->prios, clock_class, prio_ptr); | |
246 | prio_ptr = NULL; | |
a03dd9f3 PP |
247 | |
248 | set_highest_prio: | |
50842bdc | 249 | cc_prio = bt_clock_class_priority_map_current_highest_prio( |
8c0b8894 | 250 | cc_prio_map); |
f6ccaed9 | 251 | BT_ASSERT(cc_prio.clock_class); |
8c0b8894 | 252 | cc_prio_map->highest_prio_cc = cc_prio.clock_class; |
330cb9e0 PP |
253 | BT_LOGV("Added clock class to clock class priority map: " |
254 | "cc-prio-map-addr=%p, added-clock-class-addr=%p, " | |
255 | "added-clock-class-name=\"%s\", " | |
256 | "highest-prio-clock-class-addr=%p, " | |
257 | "highest-prio-clock-class-name=\"%s\"", | |
258 | cc_prio_map, clock_class, | |
50842bdc | 259 | bt_clock_class_get_name(clock_class), |
330cb9e0 | 260 | cc_prio.clock_class, |
50842bdc | 261 | bt_clock_class_get_name(cc_prio.clock_class)); |
8c0b8894 PP |
262 | |
263 | end: | |
36ede12a | 264 | g_free(prio_ptr); |
8c0b8894 PP |
265 | |
266 | return ret; | |
267 | } | |
7b5d7f76 PP |
268 | |
269 | struct bt_clock_class_priority_map *bt_clock_class_priority_map_copy( | |
270 | struct bt_clock_class_priority_map *orig_cc_prio_map) | |
271 | { | |
272 | struct bt_clock_class_priority_map *cc_prio_map; | |
273 | size_t i; | |
274 | ||
275 | cc_prio_map = bt_clock_class_priority_map_create(); | |
276 | if (!cc_prio_map) { | |
f6ccaed9 | 277 | BT_LOGE_STR("Cannot create empty clock class priority map."); |
7b5d7f76 PP |
278 | goto error; |
279 | } | |
280 | ||
281 | for (i = 0; i < orig_cc_prio_map->entries->len; i++) { | |
50842bdc | 282 | struct bt_clock_class *clock_class = |
7b5d7f76 PP |
283 | g_ptr_array_index(orig_cc_prio_map->entries, i); |
284 | uint64_t *prio = g_hash_table_lookup(orig_cc_prio_map->prios, | |
285 | clock_class); | |
286 | int ret = bt_clock_class_priority_map_add_clock_class( | |
287 | cc_prio_map, clock_class, *prio); | |
288 | ||
289 | if (ret) { | |
330cb9e0 PP |
290 | BT_LOGE("Cannot add clock class to clock class priority map copy: " |
291 | "cc-prio-map-copy-addr=%p, clock-class-addr=%p, " | |
292 | "clock-class-name=\"%s\"", | |
293 | cc_prio_map, clock_class, | |
50842bdc | 294 | bt_clock_class_get_name(clock_class)); |
7b5d7f76 PP |
295 | goto error; |
296 | } | |
297 | } | |
298 | ||
299 | cc_prio_map->highest_prio_cc = orig_cc_prio_map->highest_prio_cc; | |
330cb9e0 PP |
300 | BT_LOGD("Copied clock class priority map: " |
301 | "original-addr=%p, copy-addr=%p", | |
302 | orig_cc_prio_map, cc_prio_map); | |
7b5d7f76 PP |
303 | goto end; |
304 | ||
305 | error: | |
306 | BT_PUT(cc_prio_map); | |
307 | ||
308 | end: | |
309 | return cc_prio_map; | |
310 | } |