Ejemplo n.º 1
0
void *bt_get(void *ptr)
{
	struct bt_object *obj = ptr;

	if (unlikely(!obj)) {
		goto end;
	}

	if (unlikely(!obj->ref_count.release)) {
		goto end;
	}

	if (unlikely(obj->parent && bt_object_get_ref_count(obj) == 0)) {
		BT_LOGV("Incrementing object's parent's reference count: "
			"addr=%p, parent-addr=%p", ptr, obj->parent);
		bt_get(obj->parent);
	}
	BT_LOGV("Incrementing object's reference count: %lu -> %lu: "
		"addr=%p, cur-count=%lu, new-count=%lu",
		obj->ref_count.count, obj->ref_count.count + 1,
		ptr,
		obj->ref_count.count, obj->ref_count.count + 1);
	bt_ref_get(&obj->ref_count);

end:
	return obj;
}
Ejemplo n.º 2
0
void *bt_get(void *ptr)
{
	struct bt_object *obj = ptr;

	if (!obj) {
		goto end;
	}

	if (obj->parent && bt_object_get_ref_count(obj) == 0) {
		bt_get(obj->parent);
	}
	bt_ref_get(&obj->ref_count);
end:
	return obj;
}
Ejemplo n.º 3
0
static
void release_event(struct bt_ctf_event *event)
{
	if (bt_object_get_ref_count(event)) {
		/*
		 * The event is being orphaned, but it must guarantee the
		 * existence of its event class for the duration of its
		 * lifetime.
		 */
		bt_get(event->event_class);
		BT_PUT(event->base.parent);
	} else {
		bt_object_release(event);
	}
}
Ejemplo n.º 4
0
void bt_put(void *ptr)
{
	struct bt_object *obj = ptr;

	if (unlikely(!obj)) {
		return;
	}

	if (unlikely(!obj->ref_count.release)) {
		return;
	}

	if (BT_LOG_ON_WARN && unlikely(bt_object_get_ref_count(obj) == 0)) {
		BT_LOGW("Decrementing a reference count set to 0: addr=%p",
			ptr);
	}

	BT_LOGV("Decrementing object's reference count: %lu -> %lu: "
		"addr=%p, cur-count=%lu, new-count=%lu",
		obj->ref_count.count, obj->ref_count.count - 1,
		ptr,
		obj->ref_count.count, obj->ref_count.count - 1);
	bt_ref_put(&obj->ref_count);
}
Ejemplo n.º 5
0
static void test_example_scenario(void)
{
	/**
	 * Weak pointers to CTF-IR objects are to be used very carefully.
	 * This is NOT a good practice and is strongly discouraged; this
	 * is only done to facilitate the validation of expected reference
	 * counts without affecting them by taking "real" references to the
	 * objects.
	 */
	struct bt_ctf_trace *tc1 = NULL, *weak_tc1 = NULL;
	struct bt_ctf_stream_class *weak_sc1 = NULL, *weak_sc2 = NULL;
	struct bt_ctf_event_class *weak_ec1 = NULL, *weak_ec2 = NULL,
			*weak_ec3 = NULL;
	struct user user_a = { 0 }, user_b = { 0 }, user_c = { 0 };

	/* The only reference which exists at this point is on TC1. */
	tc1 = create_tc1();
	ok(tc1, "Initialize trace");
	if (!tc1) {
		return;
	}

	init_weak_refs(tc1, &weak_tc1, &weak_sc1, &weak_sc2, &weak_ec1,
			&weak_ec2, &weak_ec3);

	ok(bt_object_get_ref_count(weak_sc1) == 0,
			"Initial SC1 reference count is 0");
	ok(bt_object_get_ref_count(weak_sc2) == 0,
			"Initial SC2 reference count is 0");
	ok(bt_object_get_ref_count(weak_ec1) == 0,
			"Initial EC1 reference count is 0");
	ok(bt_object_get_ref_count(weak_ec2) == 0,
			"Initial EC2 reference count is 0");
	ok(bt_object_get_ref_count(weak_ec3) == 0,
			"Initial EC3 reference count is 0");

	/* User A has ownership of the trace. */
	BT_MOVE(user_a.tc, tc1);
	ok(bt_object_get_ref_count(user_a.tc) == 1,
			"TC1 reference count is 1");

	/* User A acquires a reference to SC2 from TC1. */
	user_a.sc = bt_ctf_trace_get_stream_class(user_a.tc, 1);
	ok(user_a.sc, "User A acquires SC2 from TC1");
	ok(bt_object_get_ref_count(weak_tc1) == 2,
			"TC1 reference count is 2");
	ok(bt_object_get_ref_count(weak_sc2) == 1,
			"SC2 reference count is 1");

	/* User A acquires a reference to EC3 from SC2. */
	user_a.ec = bt_ctf_stream_class_get_event_class(user_a.sc, 0);
	ok(user_a.ec, "User A acquires EC3 from SC2");
	ok(bt_object_get_ref_count(weak_tc1) == 2,
			"TC1 reference count is 2");
	ok(bt_object_get_ref_count(weak_sc2) == 2,
			"SC2 reference count is 2");
	ok(bt_object_get_ref_count(weak_ec3) == 1,
			"EC3 reference count is 1");

	/* User A releases its reference to SC2. */
	diag("User A releases SC2");
	BT_PUT(user_a.sc);
	/*
	 * We keep the pointer to SC2 around to validate its reference
	 * count.
	 */
	ok(bt_object_get_ref_count(weak_tc1) == 2,
			"TC1 reference count is 2");
	ok(bt_object_get_ref_count(weak_sc2) == 1,
			"SC2 reference count is 1");
	ok(bt_object_get_ref_count(weak_ec3) == 1,
			"EC3 reference count is 1");

	/* User A releases its reference to TC1. */
	diag("User A releases TC1");
	BT_PUT(user_a.tc);
	/*
	 * We keep the pointer to TC1 around to validate its reference
	 * count.
	 */
	ok(bt_object_get_ref_count(weak_tc1) == 1,
			"TC1 reference count is 1");
	ok(bt_object_get_ref_count(weak_sc2) == 1,
			"SC2 reference count is 1");
	ok(bt_object_get_ref_count(weak_ec3) == 1,
			"EC3 reference count is 1");

	/* User B acquires a reference to SC1. */
	diag("User B acquires a reference to SC1");
	user_b.sc = bt_get(weak_sc1);
	ok(bt_object_get_ref_count(weak_tc1) == 2,
			"TC1 reference count is 2");
	ok(bt_object_get_ref_count(weak_sc1) == 1,
			"SC1 reference count is 1");

	/* User C acquires a reference to EC1. */
	diag("User C acquires a reference to EC1");
	user_c.ec = bt_ctf_stream_class_get_event_class(user_b.sc, 0);
	ok(bt_object_get_ref_count(weak_ec1) == 1,
			"EC1 reference count is 1");
	ok(bt_object_get_ref_count(weak_sc1) == 2,
			"SC1 reference count is 2");

	/* User A releases its reference on EC3. */
	diag("User A releases its reference on EC3");
	BT_PUT(user_a.ec);
	ok(bt_object_get_ref_count(weak_ec3) == 0,
			"EC3 reference count is 1");
	ok(bt_object_get_ref_count(weak_sc2) == 0,
			"SC2 reference count is 0");
	ok(bt_object_get_ref_count(weak_tc1) == 1,
			"TC1 reference count is 1");

	/* User B releases its reference on SC1. */
	diag("User B releases its reference on SC1");
	BT_PUT(user_b.sc);
	ok(bt_object_get_ref_count(weak_sc1) == 1,
			"SC1 reference count is 1");

	/*
	 * User C is the sole owner of an object and is keeping the whole
	 * trace hierarchy "alive" by holding a reference to EC1.
	 */
	ok(bt_object_get_ref_count(weak_tc1) == 1,
			"TC1 reference count is 1");
	ok(bt_object_get_ref_count(weak_sc1) == 1,
			"SC1 reference count is 1");
	ok(bt_object_get_ref_count(weak_sc2) == 0,
			"SC2 reference count is 0");
	ok(bt_object_get_ref_count(weak_ec1) == 1,
			"EC1 reference count is 1");
	ok(bt_object_get_ref_count(weak_ec2) == 0,
			"EC2 reference count is 0");
	ok(bt_object_get_ref_count(weak_ec3) == 0,
			"EC3 reference count is 0");

	/* Reclaim last reference held by User C. */
	BT_PUT(user_c.ec);
}