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