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 | ||
25 | #include <babeltrace/graph/clock-class-priority-map.h> | |
26 | #include <babeltrace/graph/clock-class-priority-map-internal.h> | |
27 | #include <babeltrace/ctf-ir/clock-class.h> | |
28 | #include <babeltrace/ctf-ir/clock-class-internal.h> | |
29 | #include <babeltrace/babeltrace-internal.h> | |
3d9990ac | 30 | #include <babeltrace/compiler-internal.h> |
8c0b8894 | 31 | #include <babeltrace/ref.h> |
9ac68eb1 | 32 | #include <stdint.h> |
8c0b8894 PP |
33 | #include <glib.h> |
34 | ||
35 | static | |
36 | void bt_clock_class_priority_map_destroy(struct bt_object *obj) | |
37 | { | |
38 | struct bt_clock_class_priority_map *cc_prio_map = (void *) obj; | |
39 | ||
40 | if (!cc_prio_map) { | |
41 | return; | |
42 | } | |
43 | ||
44 | if (cc_prio_map->entries) { | |
45 | g_ptr_array_free(cc_prio_map->entries, TRUE); | |
46 | } | |
47 | ||
48 | if (cc_prio_map->prios) { | |
49 | g_hash_table_destroy(cc_prio_map->prios); | |
50 | } | |
51 | ||
52 | g_free(cc_prio_map); | |
53 | } | |
54 | ||
55 | struct bt_clock_class_priority_map *bt_clock_class_priority_map_create() | |
56 | { | |
57 | struct bt_clock_class_priority_map *cc_prio_map = NULL; | |
58 | ||
59 | cc_prio_map = g_new0(struct bt_clock_class_priority_map, 1); | |
60 | if (!cc_prio_map) { | |
61 | goto error; | |
62 | } | |
63 | ||
64 | bt_object_init(cc_prio_map, bt_clock_class_priority_map_destroy); | |
65 | cc_prio_map->entries = g_ptr_array_new_with_free_func( | |
66 | (GDestroyNotify) bt_put); | |
67 | if (!cc_prio_map->entries) { | |
68 | goto error; | |
69 | } | |
70 | ||
71 | cc_prio_map->prios = g_hash_table_new_full(g_direct_hash, | |
72 | g_direct_equal, NULL, (GDestroyNotify) g_free); | |
73 | if (!cc_prio_map->entries) { | |
74 | goto error; | |
75 | } | |
76 | ||
77 | goto end; | |
78 | ||
79 | error: | |
80 | BT_PUT(cc_prio_map); | |
81 | ||
82 | end: | |
83 | return cc_prio_map; | |
84 | } | |
85 | ||
544d0515 | 86 | int64_t bt_clock_class_priority_map_get_clock_class_count( |
8c0b8894 PP |
87 | struct bt_clock_class_priority_map *cc_prio_map) |
88 | { | |
9ac68eb1 | 89 | int64_t ret = (int64_t) -1; |
8c0b8894 PP |
90 | |
91 | if (!cc_prio_map) { | |
92 | goto end; | |
93 | } | |
94 | ||
544d0515 | 95 | ret = (int64_t) cc_prio_map->entries->len; |
8c0b8894 PP |
96 | |
97 | end: | |
98 | return ret; | |
99 | } | |
100 | ||
9ac68eb1 | 101 | struct bt_ctf_clock_class *bt_clock_class_priority_map_get_clock_class_by_index( |
8c0b8894 | 102 | struct bt_clock_class_priority_map *cc_prio_map, |
9ac68eb1 | 103 | uint64_t index) |
8c0b8894 PP |
104 | { |
105 | struct bt_ctf_clock_class *clock_class = NULL; | |
106 | ||
107 | if (!cc_prio_map || index >= cc_prio_map->entries->len) { | |
108 | goto end; | |
109 | } | |
110 | ||
111 | clock_class = g_ptr_array_index(cc_prio_map->entries, index); | |
112 | bt_get(clock_class); | |
113 | ||
114 | end: | |
115 | return clock_class; | |
116 | } | |
117 | ||
118 | struct bt_ctf_clock_class *bt_clock_class_priority_map_get_clock_class_by_name( | |
119 | struct bt_clock_class_priority_map *cc_prio_map, | |
120 | const char *name) | |
121 | { | |
122 | size_t i; | |
123 | struct bt_ctf_clock_class *clock_class = NULL; | |
124 | ||
125 | if (!cc_prio_map || !name) { | |
126 | goto end; | |
127 | } | |
128 | ||
129 | for (i = 0; i < cc_prio_map->entries->len; i++) { | |
130 | struct bt_ctf_clock_class *cur_cc = | |
131 | g_ptr_array_index(cc_prio_map->entries, i); | |
132 | // FIXME when available: use bt_ctf_clock_class_get_name() | |
133 | const char *cur_cc_name = | |
134 | cur_cc->name ? cur_cc->name->str : NULL; | |
135 | ||
136 | if (!cur_cc_name) { | |
137 | goto end; | |
138 | } | |
139 | ||
140 | if (strcmp(cur_cc_name, name) == 0) { | |
141 | clock_class = bt_get(cur_cc); | |
142 | goto end; | |
143 | } | |
144 | } | |
145 | ||
146 | end: | |
147 | return clock_class; | |
148 | } | |
149 | ||
150 | ||
151 | struct clock_class_prio { | |
152 | uint64_t prio; | |
153 | struct bt_ctf_clock_class *clock_class; | |
154 | }; | |
155 | ||
156 | static | |
157 | void current_highest_prio_gh_func(gpointer key, gpointer value, | |
158 | gpointer user_data) | |
159 | { | |
160 | struct clock_class_prio *func_data = user_data; | |
161 | uint64_t *prio = value; | |
162 | ||
163 | if (*prio <= func_data->prio) { | |
164 | func_data->prio = *prio; | |
165 | func_data->clock_class = key; | |
166 | } | |
167 | } | |
168 | ||
169 | static | |
170 | struct clock_class_prio bt_ctf_clock_class_priority_map_current_highest_prio( | |
171 | struct bt_clock_class_priority_map *cc_prio_map) | |
172 | { | |
173 | struct clock_class_prio func_data = { | |
174 | .prio = -1ULL, | |
175 | .clock_class = NULL, | |
176 | }; | |
177 | ||
178 | g_hash_table_foreach(cc_prio_map->prios, current_highest_prio_gh_func, | |
179 | &func_data); | |
180 | return func_data; | |
181 | } | |
182 | ||
183 | struct bt_ctf_clock_class * | |
184 | bt_clock_class_priority_map_get_highest_priority_clock_class( | |
185 | struct bt_clock_class_priority_map *cc_prio_map) | |
186 | { | |
187 | struct bt_ctf_clock_class *clock_class = NULL; | |
188 | ||
189 | if (!cc_prio_map) { | |
190 | goto end; | |
191 | } | |
192 | ||
193 | clock_class = bt_get(cc_prio_map->highest_prio_cc); | |
194 | ||
195 | end: | |
196 | return clock_class; | |
197 | } | |
198 | ||
199 | int bt_clock_class_priority_map_get_clock_class_priority( | |
200 | struct bt_clock_class_priority_map *cc_prio_map, | |
201 | struct bt_ctf_clock_class *clock_class, uint64_t *priority) | |
202 | { | |
203 | int ret = 0; | |
204 | uint64_t *prio; | |
205 | ||
206 | if (!cc_prio_map || !clock_class || !priority) { | |
207 | ret = -1; | |
208 | goto end; | |
209 | } | |
210 | ||
211 | prio = g_hash_table_lookup(cc_prio_map->prios, clock_class); | |
212 | if (!prio) { | |
213 | ret = -1; | |
214 | goto end; | |
215 | } | |
216 | ||
217 | *priority = *prio; | |
218 | ||
219 | end: | |
220 | return ret; | |
221 | } | |
222 | ||
223 | int bt_clock_class_priority_map_add_clock_class( | |
224 | struct bt_clock_class_priority_map *cc_prio_map, | |
225 | struct bt_ctf_clock_class *clock_class, uint64_t priority) | |
226 | { | |
227 | int ret = 0; | |
228 | uint64_t *prio_ptr = NULL; | |
229 | struct clock_class_prio cc_prio; | |
230 | ||
231 | // FIXME when available: check | |
232 | // bt_ctf_clock_class_is_valid(clock_class) | |
fe650ea4 | 233 | if (!cc_prio_map || !clock_class || cc_prio_map->frozen) { |
8c0b8894 PP |
234 | ret = -1; |
235 | goto end; | |
236 | } | |
237 | ||
a03dd9f3 | 238 | /* Check for existing clock class */ |
8c0b8894 PP |
239 | prio_ptr = g_hash_table_lookup(cc_prio_map->prios, clock_class); |
240 | if (prio_ptr) { | |
a03dd9f3 | 241 | *prio_ptr = priority; |
8c0b8894 | 242 | prio_ptr = NULL; |
a03dd9f3 | 243 | goto set_highest_prio; |
8c0b8894 PP |
244 | } |
245 | ||
246 | prio_ptr = g_new(uint64_t, 1); | |
247 | if (!prio_ptr) { | |
248 | ret = -1; | |
249 | goto end; | |
250 | } | |
251 | ||
252 | *prio_ptr = priority; | |
253 | bt_get(clock_class); | |
254 | g_ptr_array_add(cc_prio_map->entries, clock_class); | |
255 | g_hash_table_insert(cc_prio_map->prios, clock_class, prio_ptr); | |
256 | prio_ptr = NULL; | |
a03dd9f3 PP |
257 | |
258 | set_highest_prio: | |
8c0b8894 PP |
259 | cc_prio = bt_ctf_clock_class_priority_map_current_highest_prio( |
260 | cc_prio_map); | |
261 | assert(cc_prio.clock_class); | |
262 | cc_prio_map->highest_prio_cc = cc_prio.clock_class; | |
263 | ||
264 | end: | |
265 | if (prio_ptr) { | |
266 | g_free(prio_ptr); | |
267 | } | |
268 | ||
269 | return ret; | |
270 | } | |
7b5d7f76 PP |
271 | |
272 | struct bt_clock_class_priority_map *bt_clock_class_priority_map_copy( | |
273 | struct bt_clock_class_priority_map *orig_cc_prio_map) | |
274 | { | |
275 | struct bt_clock_class_priority_map *cc_prio_map; | |
276 | size_t i; | |
277 | ||
278 | cc_prio_map = bt_clock_class_priority_map_create(); | |
279 | if (!cc_prio_map) { | |
280 | goto error; | |
281 | } | |
282 | ||
283 | for (i = 0; i < orig_cc_prio_map->entries->len; i++) { | |
284 | struct bt_ctf_clock_class *clock_class = | |
285 | g_ptr_array_index(orig_cc_prio_map->entries, i); | |
286 | uint64_t *prio = g_hash_table_lookup(orig_cc_prio_map->prios, | |
287 | clock_class); | |
288 | int ret = bt_clock_class_priority_map_add_clock_class( | |
289 | cc_prio_map, clock_class, *prio); | |
290 | ||
291 | if (ret) { | |
292 | goto error; | |
293 | } | |
294 | } | |
295 | ||
296 | cc_prio_map->highest_prio_cc = orig_cc_prio_map->highest_prio_cc; | |
297 | goto end; | |
298 | ||
299 | error: | |
300 | BT_PUT(cc_prio_map); | |
301 | ||
302 | end: | |
303 | return cc_prio_map; | |
304 | } |