#include <helper.h>
#include "lttng-tracer.h"
+#define OBJ_NAME_LEN 16
+
static int lttng_ust_abi_close_in_progress;
static
void *private_data;
const struct lttng_ust_objd_ops *ops;
int f_count;
+ int owner_ref; /* has ref from owner */
void *owner;
+ char name[OBJ_NAME_LEN];
} s;
int freelist_next; /* offset freelist. end is -1. */
} u;
static
int objd_alloc(void *private_data, const struct lttng_ust_objd_ops *ops,
- void *owner)
+ void *owner, const char *name)
{
struct lttng_ust_obj *obj;
obj->u.s.ops = ops;
obj->u.s.f_count = 2; /* count == 1 : object is allocated */
/* count == 2 : allocated + hold ref */
+ obj->u.s.owner_ref = 1; /* One owner reference */
obj->u.s.owner = owner;
+ strncpy(obj->u.s.name, name, OBJ_NAME_LEN);
+ obj->u.s.name[OBJ_NAME_LEN - 1] = '\0';
return obj - objd_table.array;
}
obj->u.s.f_count++;
}
-int lttng_ust_objd_unref(int id)
+int lttng_ust_objd_unref(int id, int is_owner)
{
struct lttng_ust_obj *obj = _objd_get(id);
ERR("Reference counting error\n");
return -EINVAL;
}
+ if (is_owner) {
+ if (!obj->u.s.owner_ref) {
+ ERR("Error decrementing owner reference");
+ return -EINVAL;
+ }
+ obj->u.s.owner_ref--;
+ }
if ((--obj->u.s.f_count) == 1) {
const struct lttng_ust_objd_ops *ops = objd_ops(id);
{
int i;
- for (i = 0; i < objd_table.allocated_len; i++)
- (void) lttng_ust_objd_unref(i);
+ for (i = 0; i < objd_table.allocated_len; i++) {
+ struct lttng_ust_obj *obj;
+
+ obj = _objd_get(i);
+ if (!obj)
+ continue;
+ if (!obj->u.s.owner_ref)
+ continue; /* only unref owner ref. */
+ (void) lttng_ust_objd_unref(i, 1);
+ }
free(objd_table.array);
objd_table.array = NULL;
objd_table.len = 0;
continue;
if (!obj->u.s.owner)
continue; /* skip root handles */
+ if (!obj->u.s.owner_ref)
+ continue; /* only unref owner ref. */
if (obj->u.s.owner == owner)
- (void) lttng_ust_objd_unref(i);
+ (void) lttng_ust_objd_unref(i, 1);
}
}
int root_handle;
/* root handles have NULL owners */
- root_handle = objd_alloc(NULL, <tng_ops, NULL);
+ root_handle = objd_alloc(NULL, <tng_ops, NULL, "root");
return root_handle;
}
session = lttng_session_create();
if (!session)
return -ENOMEM;
- session_objd = objd_alloc(session, <tng_session_ops, owner);
+ session_objd = objd_alloc(session, <tng_session_ops, owner, "session");
if (session_objd < 0) {
ret = session_objd;
goto objd_error;
transport_name = "<unknown>";
return -EINVAL;
}
- chan_objd = objd_alloc(NULL, ops, owner);
+ chan_objd = objd_alloc(NULL, ops, owner, "channel");
if (chan_objd < 0) {
ret = chan_objd;
goto objd_error;
{
int err;
- err = lttng_ust_objd_unref(chan_objd);
+ err = lttng_ust_objd_unref(chan_objd, 1);
assert(!err);
}
objd_error:
int list_objd, ret;
struct lttng_ust_tracepoint_list *list;
- list_objd = objd_alloc(NULL, <tng_tracepoint_list_ops, owner);
+ list_objd = objd_alloc(NULL, <tng_tracepoint_list_ops, owner, "tp_list");
if (list_objd < 0) {
ret = list_objd;
goto objd_error;
{
int err;
- err = lttng_ust_objd_unref(list_objd);
+ err = lttng_ust_objd_unref(list_objd, 1);
assert(!err);
}
objd_error:
int list_objd, ret;
struct lttng_ust_field_list *list;
- list_objd = objd_alloc(NULL, <tng_tracepoint_field_list_ops, owner);
+ list_objd = objd_alloc(NULL, <tng_tracepoint_field_list_ops, owner,
+ "tp_field_list");
if (list_objd < 0) {
ret = list_objd;
goto objd_error;
{
int err;
- err = lttng_ust_objd_unref(list_objd);
+ err = lttng_ust_objd_unref(list_objd, 1);
assert(!err);
}
objd_error:
}
priv->buf = buf;
priv->lttng_chan = channel;
- stream_objd = objd_alloc(priv, &lib_ring_buffer_objd_ops, owner);
+ stream_objd = objd_alloc(priv, &lib_ring_buffer_objd_ops, owner, "open_stream");
if (stream_objd < 0) {
ret = stream_objd;
goto objd_error;
int event_objd, ret;
event_param->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
- event_objd = objd_alloc(NULL, <tng_enabler_ops, owner);
+ event_objd = objd_alloc(NULL, <tng_enabler_ops, owner, "enabler");
if (event_objd < 0) {
ret = event_objd;
goto objd_error;
{
int err;
- err = lttng_ust_objd_unref(event_objd);
+ err = lttng_ust_objd_unref(event_objd, 1);
assert(!err);
}
objd_error:
struct lttng_channel *channel = objd_private(objd);
if (channel)
- return lttng_ust_objd_unref(channel->session->objd);
+ return lttng_ust_objd_unref(channel->session->objd, 0);
return 0;
}
if (!lttng_ust_abi_close_in_progress)
channel->ops->buffer_read_close(buf, channel->handle);
- return lttng_ust_objd_unref(channel->objd);
+ return lttng_ust_objd_unref(channel->objd, 0);
}
return 0;
}
struct lttng_enabler *enabler = objd_private(objd);
if (enabler)
- return lttng_ust_objd_unref(enabler->chan->objd);
+ return lttng_ust_objd_unref(enabler->chan->objd, 0);
return 0;
}