X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=libust%2Flttng-ust-abi.c;h=01512128f24b478e9bea2bef795ba89eb04e97b7;hb=a4be89629a02fb95790eecf786c7f3b720c03a8e;hp=fee3d0750022becad801f34979a62e11224bcf0c;hpb=b35d179d7be2ab0cb4a9c698b86d78928089fc39;p=lttng-ust.git diff --git a/libust/lttng-ust-abi.c b/libust/lttng-ust-abi.c index fee3d075..01512128 100644 --- a/libust/lttng-ust-abi.c +++ b/libust/lttng-ust-abi.c @@ -100,7 +100,8 @@ int objd_alloc(void *private_data, const struct objd_ops *ops) end: obj->u.s.private_data = private_data; obj->u.s.ops = ops; - obj->u.s.f_count = 1; + obj->u.s.f_count = 2; /* count == 1 : object is allocated */ + /* count == 2 : allocated + hold ref */ return obj - objd_table.array; } @@ -109,6 +110,8 @@ struct obj *_objd_get(int id) { if (id >= objd_table.len) return NULL; + if (!objd_table.array[id].u.s.f_count) + return NULL; return &objd_table.array[id]; } @@ -132,7 +135,8 @@ static const struct objd_ops *objd_ops(int id) { struct obj *obj = _objd_get(id); - assert(obj); + if (!obj) + return NULL; return obj->u.s.ops; } @@ -144,6 +148,8 @@ void objd_free(int id) assert(obj); obj->u.freelist_next = objd_table.freelist_head; objd_table.freelist_head = obj - objd_table.array; + assert(obj->u.s.f_count == 1); + obj->u.s.f_count = 0; /* deallocated */ } static @@ -153,23 +159,41 @@ void objd_ref(int id) obj->u.s.f_count++; } -static -void objd_unref(int id) +int objd_unref(int id) { struct obj *obj = _objd_get(id); - if (!(--obj->u.s.f_count)) { + if (!obj) + return -EINVAL; + if (obj->u.s.f_count == 1) { + ERR("Reference counting error\n"); + return -EINVAL; + } + if ((--obj->u.s.f_count) == 1) { const struct objd_ops *ops = objd_ops(id); - + if (ops->release) ops->release(id); objd_free(id); } + return 0; } static void objd_table_destroy(void) { + int i; + + for (i = 0; i < objd_table.allocated_len; i++) { + struct obj *obj = _objd_get(i); + const struct objd_ops *ops; + + if (!obj) + continue; + ops = obj->u.s.ops; + if (ops->release) + ops->release(i); + } free(objd_table.array); } @@ -189,7 +213,6 @@ enum channel_type { METADATA_CHANNEL, }; -static int lttng_abi_create_session(void) { struct ltt_session *session; @@ -396,7 +419,12 @@ int lttng_abi_create_channel(int session_objd, return chan_objd; chan_error: - objd_unref(chan_objd); + { + int err; + + err = objd_unref(chan_objd); + assert(!err); + } objd_error: return ret; } @@ -454,17 +482,20 @@ long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg) * individual file is released). */ static -int lttng_session_release(int objd) +int lttng_release_session(int objd) { struct ltt_session *session = objd_private(objd); - if (session) + if (session) { ltt_session_destroy(session); - return 0; + return 0; + } else { + return -EINVAL; + } } static const struct objd_ops lttng_session_ops = { - .release = lttng_session_release, + .release = lttng_release_session, .cmd = lttng_session_cmd, }; @@ -527,7 +558,12 @@ int lttng_abi_create_event(int channel_objd, return event_objd; event_error: - objd_unref(event_objd); + { + int err; + + err = objd_unref(event_objd); + assert(!err); + } objd_error: return ret; } @@ -639,7 +675,7 @@ int lttng_channel_release(int objd) struct ltt_channel *channel = objd_private(objd); if (channel) - objd_unref(channel->session->objd); + return objd_unref(channel->session->objd); return 0; } @@ -694,7 +730,7 @@ int lttng_event_release(int objd) struct ltt_event *event = objd_private(objd); if (event) - objd_unref(event->chan->objd); + return objd_unref(event->chan->objd); return 0; } @@ -706,6 +742,5 @@ static const struct objd_ops lttng_event_ops = { void lttng_ust_abi_exit(void) { - /* TODO: teardown socket */ objd_table_destroy(); }