X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=ltt%2Fbranches%2Fpoly%2Flttv%2Flttv%2Fhook.c;h=926e5fd0b8d670929132170f758dfbaccb7dd144;hb=1d1df11d0582bef07ef2b33e8e82a75b08f32be4;hp=183f499a46fd7065ce32c62330e6259470deb88e;hpb=bb545b3cec36359286807096eef91175d1dd5da4;p=lttv.git diff --git a/ltt/branches/poly/lttv/lttv/hook.c b/ltt/branches/poly/lttv/lttv/hook.c index 183f499a..926e5fd0 100644 --- a/ltt/branches/poly/lttv/lttv/hook.c +++ b/ltt/branches/poly/lttv/lttv/hook.c @@ -18,19 +18,21 @@ #include - +#include typedef struct _LttvHookClosure { LttvHook hook; void *hook_data; LttvHookPrio prio; + guint ref_count; } LttvHookClosure; gint lttv_hooks_prio_compare(LttvHookClosure *a, LttvHookClosure *b) { - if(a->prio < b->prio) return -1; - if(a->prio > b->prio) return 1; - return 0; + gint ret=0; + if(a->prio < b->prio) ret = -1; + else if(a->prio > b->prio) ret = 1; + return ret; } @@ -52,13 +54,26 @@ void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data, LttvHookPrio p) LttvHookClosure *c, new_c; guint i; - if(h == NULL)g_error("Null hook added"); + if(unlikely(h == NULL))g_error("Null hook added"); new_c.hook = f; new_c.hook_data = hook_data; new_c.prio = p; + new_c.ref_count = 1; + + /* Preliminary check for duplication */ + /* only hook and hook data is checked */ + for(i = 0; i < h->len; i++) { + c = &g_array_index(h, LttvHookClosure, i); + if(new_c.hook == c->hook && new_c.hook_data == c->hook_data) { + g_assert(new_c.prio == c->prio); + c->ref_count++; + return; + } + } + + for(i = 0; i < h->len; i++) { - c = &g_array_index(h, LttvHookClosure, i); if(new_c.prio < c->prio) { g_array_insert_val(h,i,new_c); @@ -81,25 +96,45 @@ void lttv_hooks_add(LttvHooks *h, LttvHook f, void *hook_data, LttvHookPrio p) */ void lttv_hooks_add_list(LttvHooks *h, const LttvHooks *list) { - guint i,j; + guint i,j,k; LttvHookClosure *c; const LttvHookClosure *new_c; - if(list == NULL) return; + if(unlikely(list == NULL)) return; + for(i = 0, j = 0 ; i < list->len; i++) { new_c = &g_array_index(list, LttvHookClosure, i); - while(j < h->len) { - c = &g_array_index(h, LttvHookClosure, j); - if(new_c->prio < c->prio) { - g_array_insert_val(h,j,*new_c); - j++; + gboolean found=FALSE; + + /* Preliminary check for duplication */ + /* only hook and hook data is checked, not priority */ + for(k = 0; k < h->len; k++) { + c = &g_array_index(h, LttvHookClosure, k); + if(new_c->hook == c->hook && new_c->hook_data == c->hook_data) { + /* Found another identical entry : increment its ref_count and + * jump over the source index */ + g_assert(new_c->prio == c->prio); + found=TRUE; + c->ref_count++; break; } - else j++; } - if(j == h->len) { - g_array_append_val(h,*new_c); - j++; + + if(!found) { + /* If not found, add it to the destination array */ + while(j < h->len) { + c = &g_array_index(h, LttvHookClosure, j); + if(new_c->prio < c->prio) { + g_array_insert_val(h,j,*new_c); + j++; + break; + } + else j++; + } + if(j == h->len) { + g_array_append_val(h,*new_c); + j++; + } } } } @@ -116,9 +151,16 @@ void *lttv_hooks_remove(LttvHooks *h, LttvHook f) for(i = 0 ; i < h->len ; i++) { c = &g_array_index(h, LttvHookClosure, i); if(c->hook == f) { - hook_data = c->hook_data; - lttv_hooks_remove_by_position(h, i); - return hook_data; + if(c->ref_count == 1) { + hook_data = c->hook_data; + lttv_hooks_remove_by_position(h, i); + return hook_data; + } else { + g_assert(c->ref_count != 0); + c->ref_count--; + return NULL; /* We do not want anyone to free a hook_data + still referenced */ + } } } return NULL; @@ -134,8 +176,14 @@ void lttv_hooks_remove_data(LttvHooks *h, LttvHook f, void *hook_data) for(i = 0 ; i < h->len ; i++) { c = &g_array_index(h, LttvHookClosure, i); if(c->hook == f && c->hook_data == hook_data) { - lttv_hooks_remove_by_position(h, i); - return; + if(c->ref_count == 1) { + lttv_hooks_remove_by_position(h, i); + return; + } else { + g_assert(c->ref_count != 0); + c->ref_count--; + return; + } } } } @@ -152,7 +200,12 @@ void lttv_hooks_remove_list(LttvHooks *h, LttvHooks *list) c = &g_array_index(h, LttvHookClosure, i); c_list = &g_array_index(list, LttvHookClosure, j); if(c->hook == c_list->hook && c->hook_data == c_list->hook_data) { - lttv_hooks_remove_by_position(h, i); + if(c->ref_count == 1) { + lttv_hooks_remove_by_position(h, i); + } else { + g_assert(c->ref_count != 0); + c->ref_count--; + } j++; } else i++; @@ -161,7 +214,7 @@ void lttv_hooks_remove_list(LttvHooks *h, LttvHooks *list) /* Normally the hooks in h are ordered as in list. If this is not the case, try harder here. */ - if(j < list->len) { + if(unlikely(j < list->len)) { for(; j < list->len ; j++) { c_list = &g_array_index(list, LttvHookClosure, j); lttv_hooks_remove_data(h, c_list->hook, c_list->hook_data); @@ -181,7 +234,7 @@ void lttv_hooks_get(LttvHooks *h, unsigned i, LttvHook *f, void **hook_data, { LttvHookClosure *c; - if(i >= h->len) + if(unlikely(i >= h->len)) { *f = NULL; *hook_data = NULL; @@ -209,7 +262,7 @@ gboolean lttv_hooks_call(LttvHooks *h, void *call_data) guint i; - if(h != NULL) { + if(likely(h != NULL)) { for(i = 0 ; i < h->len ; i++) { c = &g_array_index(h, LttvHookClosure, i); ret = c->hook(c->hook_data,call_data); @@ -228,11 +281,18 @@ gboolean lttv_hooks_call_check(LttvHooks *h, void *call_data) for(i = 0 ; i < h->len ; i++) { c = &g_array_index(h, LttvHookClosure, i); - if(c->hook(c->hook_data,call_data)) return TRUE; + if(unlikely(c->hook(c->hook_data,call_data))) return TRUE; } return FALSE; } +/* Optimised for h1 == NULL, h2 != NULL. This is the case + * for optimised computation (with specific by id hooks, but + * no main hooks). + * + * The second case that should occur the most often is + * h1 != NULL , h2 == NULL. + */ gboolean lttv_hooks_call_merge(LttvHooks *h1, void *call_data1, LttvHooks *h2, void *call_data2) { @@ -242,42 +302,42 @@ gboolean lttv_hooks_call_merge(LttvHooks *h1, void *call_data1, guint i, j; - if(h1 != NULL && h2 != NULL) { - for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) { - c1 = &g_array_index(h1, LttvHookClosure, i); - c2 = &g_array_index(h2, LttvHookClosure, j); - if(c1->prio <= c2->prio) { + if(unlikely(h1 != NULL)) { + if(unlikely(h2 != NULL)) { + for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) { + c1 = &g_array_index(h1, LttvHookClosure, i); + c2 = &g_array_index(h2, LttvHookClosure, j); + if(c1->prio <= c2->prio) { + ret = c1->hook(c1->hook_data,call_data1); + sum_ret = sum_ret || ret; + i++; + } + else { + ret = c2->hook(c2->hook_data,call_data2); + sum_ret = sum_ret || ret; + j++; + } + } + /* Finish the last list with hooks left */ + for(;i < h1->len; i++) { + c1 = &g_array_index(h1, LttvHookClosure, i); ret = c1->hook(c1->hook_data,call_data1); sum_ret = sum_ret || ret; - i++; } - else { + for(;j < h2->len; j++) { + c2 = &g_array_index(h2, LttvHookClosure, j); ret = c2->hook(c2->hook_data,call_data2); sum_ret = sum_ret || ret; - j++; + } + } else { /* h1 != NULL && h2 == NULL */ + for(i = 0 ; i < h1->len ; i++) { + c1 = &g_array_index(h1, LttvHookClosure, i); + ret = c1->hook(c1->hook_data,call_data1); + sum_ret = sum_ret || ret; } } - /* Finish the last list with hooks left */ - for(;i < h1->len; i++) { - c1 = &g_array_index(h1, LttvHookClosure, i); - ret = c1->hook(c1->hook_data,call_data1); - sum_ret = sum_ret || ret; - } - for(;j < h2->len; j++) { - c2 = &g_array_index(h2, LttvHookClosure, j); - ret = c2->hook(c2->hook_data,call_data2); - sum_ret = sum_ret || ret; - } - } - else if(h1 != NULL && h2 == NULL) { - for(i = 0 ; i < h1->len ; i++) { - c1 = &g_array_index(h1, LttvHookClosure, i); - ret = c1->hook(c1->hook_data,call_data1); - sum_ret = sum_ret || ret; - } - } - else if(h1 == NULL && h2 != NULL) { - for(j = 0 ; j < h2->len ; j++) { + } else if(likely(h2 != NULL)) { /* h1 == NULL && h2 != NULL */ + for(j = 0 ; j < h2->len ; j++) { c2 = &g_array_index(h2, LttvHookClosure, j); ret = c2->hook(c2->hook_data,call_data2); sum_ret = sum_ret || ret; @@ -294,42 +354,42 @@ gboolean lttv_hooks_call_check_merge(LttvHooks *h1, void *call_data1, guint i, j; - if(h1 != NULL && h2 != NULL) { - for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) { - c1 = &g_array_index(h1, LttvHookClosure, i); - c2 = &g_array_index(h2, LttvHookClosure, j); - if(c1->prio <= c2->prio) { + if(unlikely(h1 != NULL)) { + if(unlikely(h2 != NULL)) { + for(i = 0, j = 0 ; i < h1->len && j < h2->len ;) { + c1 = &g_array_index(h1, LttvHookClosure, i); + c2 = &g_array_index(h2, LttvHookClosure, j); + if(c1->prio <= c2->prio) { + if(c1->hook(c1->hook_data,call_data1)) return TRUE; + i++; + } + else { + if(c2->hook(c2->hook_data,call_data2)) return TRUE; + j++; + } + } + /* Finish the last list with hooks left */ + for(;i < h1->len; i++) { + c1 = &g_array_index(h1, LttvHookClosure, i); if(c1->hook(c1->hook_data,call_data1)) return TRUE; - i++; } - else { + for(;j < h2->len; j++) { + c2 = &g_array_index(h2, LttvHookClosure, j); if(c2->hook(c2->hook_data,call_data2)) return TRUE; - j++; + } + } else { /* h2 == NULL && h1 != NULL */ + for(i = 0 ; i < h1->len ; i++) { + c1 = &g_array_index(h1, LttvHookClosure, i); + if(c1->hook(c1->hook_data,call_data1)) return TRUE; } } - /* Finish the last list with hooks left */ - for(;i < h1->len; i++) { - c1 = &g_array_index(h1, LttvHookClosure, i); - if(c1->hook(c1->hook_data,call_data1)) return TRUE; - } - for(;j < h2->len; j++) { - c2 = &g_array_index(h2, LttvHookClosure, j); - if(c2->hook(c2->hook_data,call_data2)) return TRUE; - } - } - else if(h1 != NULL && h2 == NULL) { - for(i = 0 ; i < h1->len ; i++) { - c1 = &g_array_index(h1, LttvHookClosure, i); - if(c1->hook(c1->hook_data,call_data1)) return TRUE; - } - } - else if(h1 == NULL && h2 != NULL) { + } else if(likely(h2 != NULL)) { /* h1 == NULL && h2 != NULL */ for(j = 0 ; j < h2->len ; j++) { c2 = &g_array_index(h2, LttvHookClosure, j); if(c2->hook(c2->hook_data,call_data2)) return TRUE; } } - + return FALSE; } @@ -351,11 +411,11 @@ void lttv_hooks_by_id_destroy(LttvHooksById *h) g_ptr_array_free(h, TRUE); } - +/* Optimised for searching an existing hook */ LttvHooks *lttv_hooks_by_id_find(LttvHooksById *h, unsigned id) { - if(h->len <= id) g_ptr_array_set_size(h, id + 1); - if(h->pdata[id] == NULL) h->pdata[id] = lttv_hooks_new(); + if(unlikely(h->len <= id)) g_ptr_array_set_size(h, id + 1); + if(unlikely(h->pdata[id] == NULL)) h->pdata[id] = lttv_hooks_new(); return h->pdata[id]; } @@ -365,17 +425,9 @@ unsigned lttv_hooks_by_id_max_id(LttvHooksById *h) return h->len; } - -LttvHooks *lttv_hooks_by_id_get(LttvHooksById *h, unsigned id) -{ - if(id < h->len) return h->pdata[id]; - return NULL; -} - - void lttv_hooks_by_id_remove(LttvHooksById *h, unsigned id) { - if(id < h->len && h->pdata[id] != NULL) { + if(likely(id < h->len && h->pdata[id] != NULL)) { lttv_hooks_destroy((LttvHooks *)h->pdata[id]); h->pdata[id] = NULL; }