batchtest can now output the textdump
[lttv.git] / ltt / branches / poly / lttv / lttv / hook.c
CommitLineData
9c312311 1/* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Michel Dagenais
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
16 * MA 02111-1307, USA.
17 */
18
4e4d11b3 19#ifdef HAVE_CONFIG_H
20#include <config.h>
21#endif
ffd54a90 22
3d218f2a 23#include <lttv/hook.h>
1d1df11d 24#include <ltt/compiler.h>
eccb5352 25
dc877563 26typedef struct _LttvHookClosure {
47e76340 27 LttvHook hook;
28 void *hook_data;
29 LttvHookPrio prio;
8436038a 30 guint ref_count;
dc877563 31} LttvHookClosure;
eccb5352 32
47e76340 33gint lttv_hooks_prio_compare(LttvHookClosure *a, LttvHookClosure *b)
34{
1d1df11d 35 gint ret=0;
36 if(a->prio < b->prio) ret = -1;
37 else if(a->prio > b->prio) ret = 1;
38 return ret;
47e76340 39}
40
eccb5352 41
dc877563 42LttvHooks *lttv_hooks_new()
43{
44 return g_array_new(FALSE, FALSE, sizeof(LttvHookClosure));
eccb5352 45}
46
dc877563 47
48void lttv_hooks_destroy(LttvHooks *h)
49{
2a2fa4f0 50 g_log(G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "lttv_hooks_destroy()");
eccb5352 51 g_array_free(h, TRUE);
52}
53
eccb5352 54
47e76340 55void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data, LttvHookPrio p)
dc877563 56{
bb545b3c 57 LttvHookClosure *c, new_c;
58 guint i;
59
1d1df11d 60 if(unlikely(h == NULL))g_error("Null hook added");
eccb5352 61
bb545b3c 62 new_c.hook = f;
63 new_c.hook_data = hook_data;
64 new_c.prio = p;
5a6db8b4 65 new_c.ref_count = 1;
8436038a 66
67 /* Preliminary check for duplication */
68 /* only hook and hook data is checked */
69 for(i = 0; i < h->len; i++) {
70 c = &g_array_index(h, LttvHookClosure, i);
71 if(new_c.hook == c->hook && new_c.hook_data == c->hook_data) {
72 g_assert(new_c.prio == c->prio);
73 c->ref_count++;
74 return;
75 }
76 }
77
78
bb545b3c 79 for(i = 0; i < h->len; i++) {
bb545b3c 80 c = &g_array_index(h, LttvHookClosure, i);
81 if(new_c.prio < c->prio) {
82 g_array_insert_val(h,i,new_c);
83 return;
84 }
85 }
86 if(i == h->len)
87 g_array_append_val(h,new_c);
eccb5352 88}
89
bb545b3c 90/* lttv_hooks_add_list
91 *
92 * Adds a sorted list into another sorted list.
93 *
94 * Note : h->len is modified, but only incremented. This assures
95 * its coherence through the function.
96 *
97 * j is an index to the element following the last one added in the
98 * destination array.
99 */
100void lttv_hooks_add_list(LttvHooks *h, const LttvHooks *list)
dc877563 101{
8436038a 102 guint i,j,k;
bb545b3c 103 LttvHookClosure *c;
104 const LttvHookClosure *new_c;
dc877563 105
1d1df11d 106 if(unlikely(list == NULL)) return;
107
bb545b3c 108 for(i = 0, j = 0 ; i < list->len; i++) {
109 new_c = &g_array_index(list, LttvHookClosure, i);
8436038a 110 gboolean found=FALSE;
111
112 /* Preliminary check for duplication */
113 /* only hook and hook data is checked, not priority */
114 for(k = 0; k < h->len; k++) {
115 c = &g_array_index(h, LttvHookClosure, k);
116 if(new_c->hook == c->hook && new_c->hook_data == c->hook_data) {
117 /* Found another identical entry : increment its ref_count and
118 * jump over the source index */
119 g_assert(new_c->prio == c->prio);
120 found=TRUE;
121 c->ref_count++;
bb545b3c 122 break;
123 }
bb545b3c 124 }
8436038a 125
126 if(!found) {
127 /* If not found, add it to the destination array */
128 while(j < h->len) {
129 c = &g_array_index(h, LttvHookClosure, j);
130 if(new_c->prio < c->prio) {
131 g_array_insert_val(h,j,*new_c);
132 j++;
133 break;
134 }
135 else j++;
136 }
137 if(j == h->len) {
138 g_array_append_val(h,*new_c);
139 j++;
140 }
bb545b3c 141 }
dc877563 142 }
143}
144
145
146void *lttv_hooks_remove(LttvHooks *h, LttvHook f)
147{
148 unsigned i;
149
150 void *hook_data;
151
152 LttvHookClosure *c;
153
154 for(i = 0 ; i < h->len ; i++) {
155 c = &g_array_index(h, LttvHookClosure, i);
156 if(c->hook == f) {
8436038a 157 if(c->ref_count == 1) {
158 hook_data = c->hook_data;
159 lttv_hooks_remove_by_position(h, i);
160 return hook_data;
161 } else {
162 g_assert(c->ref_count != 0);
163 c->ref_count--;
164 return NULL; /* We do not want anyone to free a hook_data
165 still referenced */
166 }
dc877563 167 }
168 }
169 return NULL;
170}
171
172
173void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data)
eccb5352 174{
dc877563 175 unsigned i;
176
177 LttvHookClosure *c;
eccb5352 178
179 for(i = 0 ; i < h->len ; i++) {
dc877563 180 c = &g_array_index(h, LttvHookClosure, i);
181 if(c->hook == f && c->hook_data == hook_data) {
8436038a 182 if(c->ref_count == 1) {
183 lttv_hooks_remove_by_position(h, i);
184 return;
185 } else {
186 g_assert(c->ref_count != 0);
187 c->ref_count--;
188 return;
189 }
dc877563 190 }
191 }
192}
193
194
195void lttv_hooks_remove_list(LttvHooks *h, LttvHooks *list)
196{
197 guint i, j;
198
199 LttvHookClosure *c, *c_list;
200
ffd54a90 201 if(list == NULL) return;
dc877563 202 for(i = 0, j = 0 ; i < h->len && j < list->len ;) {
203 c = &g_array_index(h, LttvHookClosure, i);
204 c_list = &g_array_index(list, LttvHookClosure, j);
205 if(c->hook == c_list->hook && c->hook_data == c_list->hook_data) {
8436038a 206 if(c->ref_count == 1) {
207 lttv_hooks_remove_by_position(h, i);
208 } else {
209 g_assert(c->ref_count != 0);
210 c->ref_count--;
211 }
dc877563 212 j++;
213 }
214 else i++;
215 }
216
217 /* Normally the hooks in h are ordered as in list. If this is not the case,
218 try harder here. */
219
1d1df11d 220 if(unlikely(j < list->len)) {
dc877563 221 for(; j < list->len ; j++) {
222 c_list = &g_array_index(list, LttvHookClosure, j);
223 lttv_hooks_remove_data(h, c_list->hook, c_list->hook_data);
224 }
eccb5352 225 }
226}
227
228
dc877563 229unsigned lttv_hooks_number(LttvHooks *h)
230{
231 return h->len;
232}
eccb5352 233
dc877563 234
47e76340 235void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data,
236 LttvHookPrio *p)
dc877563 237{
238 LttvHookClosure *c;
239
1d1df11d 240 if(unlikely(i >= h->len))
47e76340 241 {
242 *f = NULL;
243 *hook_data = NULL;
244 *p = 0;
245 return;
246 }
247
dc877563 248 c = &g_array_index(h, LttvHookClosure, i);
249 *f = c->hook;
250 *hook_data = c->hook_data;
47e76340 251 *p = c->prio;
dc877563 252}
253
254
ffd54a90 255void lttv_hooks_remove_by_position(LttvHooks *h, unsigned i)
dc877563 256{
ffd54a90 257 g_array_remove_index(h, i);
dc877563 258}
259
dc877563 260gboolean lttv_hooks_call(LttvHooks *h, void *call_data)
261{
b445142a 262 gboolean ret, sum_ret = FALSE;
dc877563 263
264 LttvHookClosure *c;
265
ffd54a90 266 guint i;
267
1d1df11d 268 if(likely(h != NULL)) {
dc877563 269 for(i = 0 ; i < h->len ; i++) {
270 c = &g_array_index(h, LttvHookClosure, i);
b445142a 271 ret = c->hook(c->hook_data,call_data);
272 sum_ret = sum_ret || ret;
dc877563 273 }
274 }
b445142a 275 return sum_ret;
dc877563 276}
277
278
279gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data)
280{
281 LttvHookClosure *c;
282
ffd54a90 283 guint i;
284
dc877563 285 for(i = 0 ; i < h->len ; i++) {
286 c = &g_array_index(h, LttvHookClosure, i);
1d1df11d 287 if(unlikely(c->hook(c->hook_data,call_data))) return TRUE;
dc877563 288 }
289 return FALSE;
290}
291
1d1df11d 292/* Optimised for h1 == NULL, h2 != NULL. This is the case
293 * for optimised computation (with specific by id hooks, but
294 * no main hooks).
295 *
296 * The second case that should occur the most often is
297 * h1 != NULL , h2 == NULL.
298 */
47e76340 299gboolean lttv_hooks_call_merge(LttvHooks *h1, void *call_data1,
300 LttvHooks *h2, void *call_data2)
301{
302 gboolean ret, sum_ret = FALSE;
303
304 LttvHookClosure *c1, *c2;
305
306 guint i, j;
307
1d1df11d 308 if(unlikely(h1 != NULL)) {
309 if(unlikely(h2 != NULL)) {
f210b68b 310 for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) {
311 c1 = &g_array_index(h1, LttvHookClosure, i);
312 c2 = &g_array_index(h2, LttvHookClosure, j);
313 if(c1->prio <= c2->prio) {
314 ret = c1->hook(c1->hook_data,call_data1);
315 sum_ret = sum_ret || ret;
316 i++;
317 }
318 else {
319 ret = c2->hook(c2->hook_data,call_data2);
320 sum_ret = sum_ret || ret;
321 j++;
322 }
323 }
324 /* Finish the last list with hooks left */
325 for(;i < h1->len; i++) {
326 c1 = &g_array_index(h1, LttvHookClosure, i);
47e76340 327 ret = c1->hook(c1->hook_data,call_data1);
328 sum_ret = sum_ret || ret;
47e76340 329 }
f210b68b 330 for(;j < h2->len; j++) {
331 c2 = &g_array_index(h2, LttvHookClosure, j);
47e76340 332 ret = c2->hook(c2->hook_data,call_data2);
333 sum_ret = sum_ret || ret;
f210b68b 334 }
335 } else { /* h1 != NULL && h2 == NULL */
336 for(i = 0 ; i < h1->len ; i++) {
337 c1 = &g_array_index(h1, LttvHookClosure, i);
338 ret = c1->hook(c1->hook_data,call_data1);
339 sum_ret = sum_ret || ret;
47e76340 340 }
341 }
1d1df11d 342 } else if(likely(h2 != NULL)) { /* h1 == NULL && h2 != NULL */
f210b68b 343 for(j = 0 ; j < h2->len ; j++) {
47e76340 344 c2 = &g_array_index(h2, LttvHookClosure, j);
345 ret = c2->hook(c2->hook_data,call_data2);
346 sum_ret = sum_ret || ret;
347 }
348 }
349
350 return sum_ret;
351}
352
353gboolean lttv_hooks_call_check_merge(LttvHooks *h1, void *call_data1,
354 LttvHooks *h2, void *call_data2)
355{
356 LttvHookClosure *c1, *c2;
357
358 guint i, j;
359
1d1df11d 360 if(unlikely(h1 != NULL)) {
361 if(unlikely(h2 != NULL)) {
f210b68b 362 for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) {
363 c1 = &g_array_index(h1, LttvHookClosure, i);
364 c2 = &g_array_index(h2, LttvHookClosure, j);
365 if(c1->prio <= c2->prio) {
366 if(c1->hook(c1->hook_data,call_data1)) return TRUE;
367 i++;
368 }
369 else {
370 if(c2->hook(c2->hook_data,call_data2)) return TRUE;
371 j++;
372 }
373 }
374 /* Finish the last list with hooks left */
375 for(;i < h1->len; i++) {
376 c1 = &g_array_index(h1, LttvHookClosure, i);
47e76340 377 if(c1->hook(c1->hook_data,call_data1)) return TRUE;
47e76340 378 }
f210b68b 379 for(;j < h2->len; j++) {
380 c2 = &g_array_index(h2, LttvHookClosure, j);
47e76340 381 if(c2->hook(c2->hook_data,call_data2)) return TRUE;
f210b68b 382 }
383 } else { /* h2 == NULL && h1 != NULL */
384 for(i = 0 ; i < h1->len ; i++) {
385 c1 = &g_array_index(h1, LttvHookClosure, i);
386 if(c1->hook(c1->hook_data,call_data1)) return TRUE;
47e76340 387 }
388 }
1d1df11d 389 } else if(likely(h2 != NULL)) { /* h1 == NULL && h2 != NULL */
47e76340 390 for(j = 0 ; j < h2->len ; j++) {
391 c2 = &g_array_index(h2, LttvHookClosure, j);
392 if(c2->hook(c2->hook_data,call_data2)) return TRUE;
393 }
394 }
f210b68b 395
47e76340 396 return FALSE;
397
398}
399
dc877563 400
401LttvHooksById *lttv_hooks_by_id_new()
402{
eccb5352 403 return g_ptr_array_new();
404}
405
406
dc877563 407void lttv_hooks_by_id_destroy(LttvHooksById *h)
408{
409 guint i;
410
411 for(i = 0 ; i < h->len ; i++) {
412 if(h->pdata[i] != NULL) lttv_hooks_destroy((LttvHooks *)(h->pdata[i]));
413 }
eccb5352 414 g_ptr_array_free(h, TRUE);
415}
416
1d1df11d 417/* Optimised for searching an existing hook */
ffd54a90 418LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id)
eccb5352 419{
1d1df11d 420 if(unlikely(h->len <= id)) g_ptr_array_set_size(h, id + 1);
421 if(unlikely(h->pdata[id] == NULL)) h->pdata[id] = lttv_hooks_new();
dc877563 422 return h->pdata[id];
eccb5352 423}
424
dc877563 425
426unsigned lttv_hooks_by_id_max_id(LttvHooksById *h)
eccb5352 427{
dc877563 428 return h->len;
429}
430
dc877563 431void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id)
432{
1d1df11d 433 if(likely(id < h->len && h->pdata[id] != NULL)) {
dc877563 434 lttv_hooks_destroy((LttvHooks *)h->pdata[id]);
435 h->pdata[id] = NULL;
436 }
eccb5352 437}
438
This page took 0.070008 seconds and 4 git commands to generate.