From 3fea54f69edd1780566230255da196cb6e82df62 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Tue, 12 Jun 2018 15:47:05 -0400 Subject: [PATCH] lib: update and simplify the `bt_object` API This patch merges `ref-internal.h` into `object-internal.h` so as to simplify the `bt_object` API and ease the future addition of specialized inline functions (e.g., no specific checks). Notable changes: * There's no specific reference count structure; the reference count is directly within `struct bt_object`. * Most functions of `object-internal.h` accept and return the `struct bt_object *` type instead of `void *`. * The `struct bt_object` structure contains two release function: `release_func`: Called when the reference count falls to zero by the new bt_object_put_no_null_check() function. `spec_release_func`: Called by bt_object_try_spec_release() (formerly bt_object_release()). * You can initialize a unique object (no reference count) with bt_object_init_unique(), a shared object that will _never_ have any parent with bt_object_init_shared(), and a shared object which could have a parent in the future with bt_object_init_shared_with_parent(). bt_object_init_shared_with_parent() calls bt_object_init_shared() with the special `bt_object_with_parent_release_func` callback as the object's release function. This function used to be called generic_release(): it puts the parent if there is one, or releases the object itself (with bt_object_try_spec_release()) when there's none. The whole job of bt_object_with_parent_release_func() is unnecessary for shared objects which will never have a parent: in this case, we can call a single release function as soon as the object's reference count falls to zero. This can render the whole system faster as notification objects are shared, but without a parent, for example. Packet objects are another example, albeit less significant. * There are two new, internal versions of bt_get() and bt_put() which do not check if the parameter is null: bt_object_get_no_null_check() and bt_object_put_no_null_check(). We can use those functions internally on the fast path where it is known that a given Babeltrace object pointer is never null. This is what the public bt_get() and bt_put() function use internally now, after checking some preconditions. Signed-off-by: Philippe Proulx --- cli/babeltrace-cfg-cli-args.c | 5 +- include/Makefile.am | 1 - .../babeltrace/ctf-ir/event-class-internal.h | 2 +- include/babeltrace/ctf-ir/event-internal.h | 2 +- include/babeltrace/ctf-ir/fields-internal.h | 14 +- .../babeltrace/ctf-ir/stream-class-internal.h | 2 +- .../babeltrace/graph/notification-internal.h | 1 - .../graph/notification-iterator-internal.h | 1 - include/babeltrace/object-internal.h | 267 +++++++++++++----- include/babeltrace/object-pool-internal.h | 2 +- include/babeltrace/plugin/plugin-internal.h | 4 +- include/babeltrace/ref-internal.h | 73 ----- lib/ctf-ir/clock-class.c | 5 +- lib/ctf-ir/event-class.c | 2 +- lib/ctf-ir/event.c | 11 +- lib/ctf-ir/field-path.c | 2 +- lib/ctf-ir/field-types.c | 4 +- lib/ctf-ir/field-wrapper.c | 3 +- lib/ctf-ir/fields.c | 44 +-- lib/ctf-ir/packet.c | 3 +- lib/ctf-ir/stream-class.c | 6 +- lib/ctf-ir/stream.c | 4 +- lib/ctf-ir/trace.c | 10 +- lib/ctf-writer/clock.c | 2 +- lib/ctf-writer/event.c | 4 +- lib/ctf-writer/fields.c | 15 +- lib/ctf-writer/stream.c | 19 +- lib/ctf-writer/writer.c | 6 +- lib/graph/clock-class-priority-map.c | 3 +- lib/graph/component-class.c | 2 +- lib/graph/component.c | 12 +- lib/graph/connection.c | 11 +- lib/graph/graph.c | 17 +- lib/graph/iterator.c | 4 +- lib/graph/notification/notification.c | 2 +- lib/graph/port.c | 8 +- lib/graph/query-executor.c | 3 +- lib/lib-logging.c | 15 +- lib/plugin/plugin-so.c | 3 +- lib/ref.c | 39 +-- lib/values.c | 27 +- tests/lib/test_ctf_ir_ref.c | 62 ++-- 42 files changed, 384 insertions(+), 338 deletions(-) delete mode 100644 include/babeltrace/ref-internal.h diff --git a/cli/babeltrace-cfg-cli-args.c b/cli/babeltrace-cfg-cli-args.c index 6182f1a7..32e950a7 100644 --- a/cli/babeltrace-cfg-cli-args.c +++ b/cli/babeltrace-cfg-cli-args.c @@ -789,7 +789,8 @@ struct bt_config_component *bt_config_component_create( goto error; } - bt_object_init(cfg_component, bt_config_component_destroy); + bt_object_init_shared(&cfg_component->base, + bt_config_component_destroy); cfg_component->type = type; cfg_component->plugin_name = g_string_new(plugin_name); if (!cfg_component->plugin_name) { @@ -1499,7 +1500,7 @@ struct bt_config *bt_config_base_create(enum bt_config_command command, goto error; } - bt_object_init(cfg, bt_config_destroy); + bt_object_init_shared(&cfg->base, bt_config_destroy); cfg->command = command; cfg->command_needs_plugins = needs_plugins; diff --git a/include/Makefile.am b/include/Makefile.am index b25aabfe..d9789fcf 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -219,7 +219,6 @@ noinst_HEADERS = \ babeltrace/compiler-internal.h \ babeltrace/babeltrace-internal.h \ babeltrace/assert-pre-internal.h \ - babeltrace/ref-internal.h \ babeltrace/graph/component-internal.h \ babeltrace/graph/notification-stream-internal.h \ babeltrace/graph/connection-internal.h \ diff --git a/include/babeltrace/ctf-ir/event-class-internal.h b/include/babeltrace/ctf-ir/event-class-internal.h index 316408d8..40df300c 100644 --- a/include/babeltrace/ctf-ir/event-class-internal.h +++ b/include/babeltrace/ctf-ir/event-class-internal.h @@ -84,7 +84,7 @@ struct bt_stream_class_common *bt_event_class_common_borrow_stream_class( struct bt_event_class_common *event_class) { BT_ASSERT(event_class); - return (void *) bt_object_borrow_parent(event_class); + return (void *) bt_object_borrow_parent(&event_class->base); } typedef struct bt_field_type_common *(*bt_field_type_structure_create_func)(); diff --git a/include/babeltrace/ctf-ir/event-internal.h b/include/babeltrace/ctf-ir/event-internal.h index 43a77a23..e17ff29c 100644 --- a/include/babeltrace/ctf-ir/event-internal.h +++ b/include/babeltrace/ctf-ir/event-internal.h @@ -101,7 +101,7 @@ BT_HIDDEN int bt_event_common_initialize(struct bt_event_common *event, struct bt_event_class_common *event_class, struct bt_clock_class *init_expected_clock_class, - bt_object_release_func release_func, + bool is_shared_with_parent, bt_object_release_func release_func, bt_validation_flag_copy_field_type_func field_type_copy_func, bool must_be_in_trace, int (*map_clock_classes_func)(struct bt_stream_class_common *stream_class, diff --git a/include/babeltrace/ctf-ir/fields-internal.h b/include/babeltrace/ctf-ir/fields-internal.h index 2a4c78b0..115d4ffb 100644 --- a/include/babeltrace/ctf-ir/fields-internal.h +++ b/include/babeltrace/ctf-ir/fields-internal.h @@ -164,7 +164,7 @@ struct bt_field_common *bt_field_common_copy(struct bt_field_common *field); BT_HIDDEN int bt_field_common_structure_initialize(struct bt_field_common *field, struct bt_field_type_common *type, - bt_object_release_func release_func, + bool is_shared, bt_object_release_func release_func, struct bt_field_common_methods *methods, bt_field_common_create_func field_create_func, GDestroyNotify field_release_func); @@ -172,7 +172,7 @@ int bt_field_common_structure_initialize(struct bt_field_common *field, BT_HIDDEN int bt_field_common_array_initialize(struct bt_field_common *field, struct bt_field_type_common *type, - bt_object_release_func release_func, + bool is_shared, bt_object_release_func release_func, struct bt_field_common_methods *methods, bt_field_common_create_func field_create_func, GDestroyNotify field_destroy_func); @@ -180,14 +180,14 @@ int bt_field_common_array_initialize(struct bt_field_common *field, BT_HIDDEN int bt_field_common_sequence_initialize(struct bt_field_common *field, struct bt_field_type_common *type, - bt_object_release_func release_func, + bool is_shared, bt_object_release_func release_func, struct bt_field_common_methods *methods, GDestroyNotify field_destroy_func); BT_HIDDEN int bt_field_common_variant_initialize(struct bt_field_common *field, struct bt_field_type_common *type, - bt_object_release_func release_func, + bool is_shared, bt_object_release_func release_func, struct bt_field_common_methods *methods, bt_field_common_create_func field_create_func, GDestroyNotify field_release_func); @@ -195,7 +195,7 @@ int bt_field_common_variant_initialize(struct bt_field_common *field, BT_HIDDEN int bt_field_common_string_initialize(struct bt_field_common *field, struct bt_field_type_common *type, - bt_object_release_func release_func, + bool is_shared, bt_object_release_func release_func, struct bt_field_common_methods *methods); BT_HIDDEN @@ -355,13 +355,13 @@ end: static inline void bt_field_common_initialize(struct bt_field_common *field, - struct bt_field_type_common *ft, + struct bt_field_type_common *ft, bool is_shared, bt_object_release_func release_func, struct bt_field_common_methods *methods) { BT_ASSERT(field); BT_ASSERT(ft); - bt_object_init(field, release_func); + bt_object_init(&field->base, is_shared, release_func); field->methods = methods; field->type = bt_get(ft); } diff --git a/include/babeltrace/ctf-ir/stream-class-internal.h b/include/babeltrace/ctf-ir/stream-class-internal.h index 373e9975..8dd78567 100644 --- a/include/babeltrace/ctf-ir/stream-class-internal.h +++ b/include/babeltrace/ctf-ir/stream-class-internal.h @@ -162,7 +162,7 @@ struct bt_trace_common *bt_stream_class_common_borrow_trace( struct bt_stream_class_common *stream_class) { BT_ASSERT(stream_class); - return (void *) bt_object_borrow_parent(stream_class); + return (void *) bt_object_borrow_parent(&stream_class->base); } static inline diff --git a/include/babeltrace/graph/notification-internal.h b/include/babeltrace/graph/notification-internal.h index 3cd90509..243aac09 100644 --- a/include/babeltrace/graph/notification-internal.h +++ b/include/babeltrace/graph/notification-internal.h @@ -27,7 +27,6 @@ * SOFTWARE. */ -#include #include #include #include diff --git a/include/babeltrace/graph/notification-iterator-internal.h b/include/babeltrace/graph/notification-iterator-internal.h index 5cac60a6..dd80a519 100644 --- a/include/babeltrace/graph/notification-iterator-internal.h +++ b/include/babeltrace/graph/notification-iterator-internal.h @@ -28,7 +28,6 @@ #include #include -#include #include #include #include diff --git a/include/babeltrace/object-internal.h b/include/babeltrace/object-internal.h index afb9e6ee..70391b3b 100644 --- a/include/babeltrace/object-internal.h +++ b/include/babeltrace/object-internal.h @@ -28,147 +28,274 @@ */ #include -#include -#include #include #include -/** - * All objects publicly exposed by Babeltrace APIs must contain this structure - * as their first member. This allows the unification of all ref counting - * mechanisms and may be used to provide more base functionality to all - * objects. +struct bt_object; + +typedef void (*bt_object_release_func)(struct bt_object *); +typedef void (*bt_object_parent_is_owner_listener_func)( + struct bt_object *); + +static inline +void bt_object_get_no_null_check(struct bt_object *obj); + +static inline +void bt_object_put_no_null_check(struct bt_object *obj); + +/* + * Babeltrace object base. + * + * All objects publicly exposed by Babeltrace APIs must contain this + * object as their first member. */ struct bt_object { - struct bt_ref ref_count; - /* Class-specific, optional release function. */ - bt_object_release_func release; - /* Class-specific, optional "parent is owner" notification listener. */ - bt_object_release_func parent_is_owner_listener; - /* @see doc/ref-counting.md */ - struct bt_object *parent; - /* - * True if this object is shared, that is, it uses reference - * counting. + * True if this object is shared, that is, it has a reference + * count. */ bool is_shared; + + /* + * Current reference count. + */ + unsigned long long ref_count; + + /* + * Release function called when the object's reference count + * falls to zero. For an object with a parent, this function is + * bt_object_with_parent_release_func(), which calls + * `spec_release_func` below if there's no current parent. + */ + bt_object_release_func release_func; + + /* + * Specific release function called by + * bt_object_with_parent_release_func() or directly by a + * parent object. + */ + bt_object_release_func spec_release_func; + + /* + * Optional callback for an object with a parent, called by + * bt_object_with_parent_release_func() to indicate to the + * object that its parent is its owner. + */ + bt_object_parent_is_owner_listener_func + parent_is_owner_listener_func; + + /* + * Optional parent object. + */ + struct bt_object *parent; }; static inline -long bt_object_get_ref_count(const void *ptr) +unsigned long long bt_object_get_ref_count(struct bt_object *obj) { - const struct bt_object *obj = ptr; + BT_ASSERT(obj); + BT_ASSERT(obj->is_shared); + return obj->ref_count; +} - return obj->ref_count.count; +static inline +struct bt_object *bt_object_borrow_parent(struct bt_object *obj) +{ + BT_ASSERT(obj); + BT_ASSERT(obj->is_shared); + return obj->parent; } static inline -void bt_object_release(void *ptr) +struct bt_object *bt_object_get_parent(struct bt_object *obj) { - struct bt_object *obj = ptr; + struct bt_object *parent = bt_object_borrow_parent(obj); + + if (parent) { + bt_object_get_no_null_check(parent); + } + + return parent; +} + +static inline +void bt_object_set_parent(struct bt_object *child, struct bt_object *parent) +{ + BT_ASSERT(child); + BT_ASSERT(child->is_shared); #ifdef BT_LOGV - BT_LOGV("Releasing object: addr=%p, ref-count=%lu", ptr, - obj->ref_count.count); + BT_LOGV("Setting object's parent: addr=%p, parent-addr=%p", + child, parent); #endif - if (obj && obj->release && bt_object_get_ref_count(obj) == 0) { - obj->release(obj); + /* + * It is assumed that a "child" having a parent is publicly + * reachable. Therefore, a reference to its parent must be + * taken. The reference to the parent will be released once the + * object's reference count falls to zero. + */ + if (parent) { + BT_ASSERT(!child->parent); + child->parent = parent; + bt_object_get_no_null_check(parent); + } else { + if (child->parent) { + bt_object_put_no_null_check(child->parent); + } + + child->parent = NULL; } } static inline -void generic_release(struct bt_object *obj) +void bt_object_try_spec_release(struct bt_object *obj) +{ + BT_ASSERT(obj); + BT_ASSERT(obj->is_shared); + BT_ASSERT(obj->spec_release_func); + + if (bt_object_get_ref_count(obj) == 0) { + obj->spec_release_func(obj); + } +} + +static inline +void bt_object_with_parent_release_func(struct bt_object *obj) { if (obj->parent) { + /* + * Keep our own copy of the parent address because `obj` + * could be destroyed in + * obj->parent_is_owner_listener_func(). + */ struct bt_object *parent = obj->parent; #ifdef BT_LOGV - BT_LOGV("Releasing parented object: addr=%p, ref-count=%lu, " - "parent-addr=%p, parent-ref-count=%lu", - obj, obj->ref_count.count, - parent, parent->ref_count.count); + BT_LOGV("Releasing parented object: addr=%p, ref-count=%llu, " + "parent-addr=%p, parent-ref-count=%llu", + obj, obj->ref_count, + parent, parent->ref_count); #endif - if (obj->parent_is_owner_listener) { + if (obj->parent_is_owner_listener_func) { /* * Object has a chance to destroy itself here * under certain conditions and notify its * parent. At this point the parent is * guaranteed to exist because it's not put yet. */ - obj->parent_is_owner_listener(obj); + obj->parent_is_owner_listener_func(obj); } /* The release function will be invoked by the parent. */ - bt_put(parent); + bt_object_put_no_null_check(parent); } else { - bt_object_release(obj); + bt_object_try_spec_release(obj); } } static inline -struct bt_object *bt_object_borrow_parent(void *ptr) +void bt_object_init(struct bt_object *obj, bool is_shared, + bt_object_release_func release_func) { - struct bt_object *obj = ptr; - - return obj ? obj->parent : NULL; + BT_ASSERT(obj); + BT_ASSERT(!is_shared || release_func); + obj->is_shared = is_shared; + obj->release_func = release_func; + obj->parent_is_owner_listener_func = NULL; + obj->spec_release_func = NULL; + obj->parent = NULL; + obj->ref_count = 1; } static inline -struct bt_object *bt_object_get_parent(void *ptr) +void bt_object_init_shared(struct bt_object *obj, + bt_object_release_func release_func) { - return bt_get(bt_object_borrow_parent(ptr)); + bt_object_init(obj, true, release_func); } static inline -void bt_object_set_parent(void *child_ptr, void *parent) +void bt_object_init_unique(struct bt_object *obj) { - struct bt_object *child = child_ptr; - - if (!child) { - return; - } + bt_object_init(obj, false, NULL); +} -#ifdef BT_LOGV - BT_LOGV("Setting object's parent: addr=%p, parent-addr=%p", - child_ptr, parent); -#endif +static inline +void bt_object_init_shared_with_parent(struct bt_object *obj, + bt_object_release_func spec_release_func) +{ + BT_ASSERT(obj); + BT_ASSERT(spec_release_func); + bt_object_init_shared(obj, bt_object_with_parent_release_func); + obj->spec_release_func = spec_release_func; +} - /* - * It is assumed that a "child" being "parented" is publicly - * reachable. Therefore, a reference to its parent must be - * taken. The reference to the parent will be released once the - * object's reference count falls to zero. - */ - BT_PUT(child->parent); - child->parent = bt_get(parent); +static inline +void bt_object_set_parent_is_owner_listener_func(struct bt_object *obj, + bt_object_parent_is_owner_listener_func func) +{ + BT_ASSERT(obj); + BT_ASSERT(obj->is_shared); + BT_ASSERT(obj->spec_release_func); + ((struct bt_object *) obj)->parent_is_owner_listener_func = func; } static inline -void bt_object_set_is_shared(struct bt_object *obj, bool is_shared) +void bt_object_inc_ref_count(struct bt_object *obj) { - obj->is_shared = is_shared; + BT_ASSERT(obj); + BT_ASSERT(obj->is_shared); + obj->ref_count++; + BT_ASSERT(obj->ref_count != 0); } static inline -void bt_object_init(void *ptr, bt_object_release_func release) +void bt_object_get_no_null_check(struct bt_object *obj) { - struct bt_object *obj = ptr; + BT_ASSERT(obj); + BT_ASSERT(obj->is_shared); - obj->release = release; - obj->parent = NULL; - bt_object_set_is_shared(obj, true); - bt_ref_init(&obj->ref_count, generic_release); + if (unlikely(obj->parent && bt_object_get_ref_count(obj) == 0)) { +#ifdef BT_LOGV + BT_LOGV("Incrementing object's parent's reference count: " + "addr=%p, parent-addr=%p", obj, obj->parent); +#endif + + bt_object_get_no_null_check(obj->parent); + } + +#ifdef BT_LOGV + BT_LOGV("Incrementing object's reference count: %llu -> %llu: " + "addr=%p, cur-count=%llu, new-count=%llu", + obj->ref_count, obj->ref_count + 1, + obj, obj->ref_count, obj->ref_count + 1); +#endif + + bt_object_inc_ref_count(obj); } static inline -void bt_object_set_parent_is_owner_listener(void *obj, - bt_object_release_func cb) +void bt_object_put_no_null_check(struct bt_object *obj) { BT_ASSERT(obj); - ((struct bt_object *) obj)->parent_is_owner_listener = cb; + BT_ASSERT(obj->is_shared); + BT_ASSERT(obj->ref_count > 0); + +#ifdef BT_LOGV + BT_LOGV("Decrementing object's reference count: %llu -> %llu: " + "addr=%p, cur-count=%llu, new-count=%llu", + obj->ref_count, obj->ref_count - 1, + obj, obj->ref_count, obj->ref_count - 1); +#endif + + obj->ref_count--; + + if (obj->ref_count == 0) { + BT_ASSERT(obj->release_func); + obj->release_func(obj); + } } #endif /* BABELTRACE_OBJECT_INTERNAL_H */ diff --git a/include/babeltrace/object-pool-internal.h b/include/babeltrace/object-pool-internal.h index ef855890..54917c05 100644 --- a/include/babeltrace/object-pool-internal.h +++ b/include/babeltrace/object-pool-internal.h @@ -168,7 +168,7 @@ void bt_object_pool_recycle_object(struct bt_object_pool *pool, void *obj) } /* Reset reference count to 1 since it could be 0 now */ - bt_obj->ref_count.count = 1; + bt_obj->ref_count = 1; /* Back to the pool */ pool->objects->pdata[pool->size] = obj; diff --git a/include/babeltrace/plugin/plugin-internal.h b/include/babeltrace/plugin/plugin-internal.h index cbcf0274..4cb57513 100644 --- a/include/babeltrace/plugin/plugin-internal.h +++ b/include/babeltrace/plugin/plugin-internal.h @@ -169,7 +169,7 @@ struct bt_plugin *bt_plugin_create_empty(enum bt_plugin_type type) goto error; } - bt_object_init(plugin, bt_plugin_destroy); + bt_object_init_shared(&plugin->base, bt_plugin_destroy); plugin->type = type; /* Create empty array of component classes */ @@ -349,7 +349,7 @@ struct bt_plugin_set *bt_plugin_set_create(void) } BT_LOGD_STR("Creating empty plugin set."); - bt_object_init(plugin_set, bt_plugin_set_destroy); + bt_object_init_shared(&plugin_set->base, bt_plugin_set_destroy); plugin_set->plugins = g_ptr_array_new_with_free_func( (GDestroyNotify) bt_put); diff --git a/include/babeltrace/ref-internal.h b/include/babeltrace/ref-internal.h deleted file mode 100644 index f0d973b6..00000000 --- a/include/babeltrace/ref-internal.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef BABELTRACE_REF_INTERNAL_H -#define BABELTRACE_REF_INTERNAL_H - -/* - * Babeltrace - Reference Counting - * - * Copyright 2013, 2014 Jérémie Galarneau - * - * Author: Jérémie Galarneau - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -struct bt_object; -typedef void (*bt_object_release_func)(struct bt_object *); - -struct bt_ref { - unsigned long count; - bt_object_release_func release; -}; - -static inline -void bt_ref_init(struct bt_ref *ref, bt_object_release_func release) -{ - BT_ASSERT(ref); - ref->count = 1; - ref->release = release; -} - -static inline -void bt_ref_get(struct bt_ref *ref) -{ - BT_ASSERT(ref); - - if (unlikely(!ref->release)) { - return; - } - - ref->count++; - /* Overflow check. */ - BT_ASSERT(ref->count); -} - -static inline -void bt_ref_put(struct bt_ref *ref) -{ - BT_ASSERT(ref); - /* Only assert if the object has opted-in for reference counting. */ - if (unlikely((--ref->count) == 0 && ref->release)) { - ref->release((struct bt_object *) ref); - } -} - -#endif /* BABELTRACE_REF_INTERNAL_H */ diff --git a/lib/ctf-ir/clock-class.c b/lib/ctf-ir/clock-class.c index a4fd6ed6..5872ef83 100644 --- a/lib/ctf-ir/clock-class.c +++ b/lib/ctf-ir/clock-class.c @@ -148,7 +148,7 @@ struct bt_clock_class *bt_clock_class_create(const char *name, clock_class->precision = 1; clock_class->frequency = freq; - bt_object_init(clock_class, bt_clock_class_destroy); + bt_object_init_shared(&clock_class->base, bt_clock_class_destroy); if (name) { ret = bt_clock_class_set_name(clock_class, name); @@ -762,8 +762,7 @@ struct bt_clock_value *bt_clock_value_new(struct bt_clock_class *clock_class) goto end; } - bt_object_init(ret, NULL); - bt_object_set_is_shared((void *) ret, false); + bt_object_init_unique(&ret->base); ret->clock_class = bt_get(clock_class); bt_clock_class_freeze(clock_class); BT_LOGD("Created clock value object: clock-value-addr=%p, " diff --git a/lib/ctf-ir/event-class.c b/lib/ctf-ir/event-class.c index 57402e34..a387b38a 100644 --- a/lib/ctf-ir/event-class.c +++ b/lib/ctf-ir/event-class.c @@ -85,7 +85,7 @@ int bt_event_class_common_initialize(struct bt_event_class_common *event_class, BT_LOGD("Initializing common event class object: name=\"%s\"", name); - bt_object_init(event_class, release_func); + bt_object_init_shared_with_parent(&event_class->base, release_func); event_class->payload_field_type = ft_struct_create_func(); if (!event_class->payload_field_type) { BT_LOGE_STR("Cannot create event class's initial payload field type object."); diff --git a/lib/ctf-ir/event.c b/lib/ctf-ir/event.c index 95a17d3a..9fa9223e 100644 --- a/lib/ctf-ir/event.c +++ b/lib/ctf-ir/event.c @@ -320,7 +320,7 @@ BT_HIDDEN int bt_event_common_initialize(struct bt_event_common *event, struct bt_event_class_common *event_class, struct bt_clock_class *init_expected_clock_class, - bt_object_release_func release_func, + bool is_shared_with_parent, bt_object_release_func release_func, bt_validation_flag_copy_field_type_func field_type_copy_func, bool must_be_in_trace, int (*map_clock_classes_func)(struct bt_stream_class_common *stream_class, @@ -368,7 +368,11 @@ int bt_event_common_initialize(struct bt_event_common *event, * failure, the caller releases the reference to `event` to * destroy it. */ - bt_object_init(event, release_func); + if (is_shared_with_parent) { + bt_object_init_shared_with_parent(&event->base, release_func); + } else { + bt_object_init_unique(&event->base); + } if (!stream_class->frozen) { /* @@ -572,7 +576,7 @@ struct bt_event *bt_event_new(struct bt_event_class *event_class) } ret = bt_event_common_initialize(BT_TO_COMMON(event), - BT_TO_COMMON(event_class), NULL, NULL, + BT_TO_COMMON(event_class), NULL, false, NULL, (bt_validation_flag_copy_field_type_func) bt_field_type_copy, true, NULL, (create_field_func) bt_field_create_recursive, @@ -584,7 +588,6 @@ struct bt_event *bt_event_new(struct bt_event_class *event_class) goto error; } - bt_object_set_is_shared((void *) event, false); event->clock_values = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) bt_clock_value_recycle); diff --git a/lib/ctf-ir/field-path.c b/lib/ctf-ir/field-path.c index 61a57fe3..d9893059 100644 --- a/lib/ctf-ir/field-path.c +++ b/lib/ctf-ir/field-path.c @@ -68,7 +68,7 @@ struct bt_field_path *bt_field_path_create(void) goto error; } - bt_object_init(field_path, field_path_destroy); + bt_object_init_shared(&field_path->base, field_path_destroy); field_path->root = BT_SCOPE_UNKNOWN; field_path->indexes = g_array_new(TRUE, FALSE, sizeof(int)); if (!field_path->indexes) { diff --git a/lib/ctf-ir/field-types.c b/lib/ctf-ir/field-types.c index a8a41b57..c880d306 100644 --- a/lib/ctf-ir/field-types.c +++ b/lib/ctf-ir/field-types.c @@ -165,7 +165,7 @@ void bt_field_type_common_initialize(struct bt_field_type_common *ft, BT_ASSERT(ft && (ft->id > BT_FIELD_TYPE_ID_UNKNOWN) && (ft->id < BT_FIELD_TYPE_ID_NR)); - bt_object_init(ft, release_func); + bt_object_init_shared(&ft->base, release_func); ft->methods = methods; if (init_bo) { @@ -1430,7 +1430,7 @@ bt_field_type_common_enumeration_find_mappings_type( goto end; } - bt_object_init(&iter->base, bt_field_type_enum_iter_destroy); + bt_object_init_shared(&iter->base, bt_field_type_enum_iter_destroy); iter->enumeration_ft = bt_get(ft); iter->index = -1; iter->type = iterator_type; diff --git a/lib/ctf-ir/field-wrapper.c b/lib/ctf-ir/field-wrapper.c index 5917f70d..054d80a3 100644 --- a/lib/ctf-ir/field-wrapper.c +++ b/lib/ctf-ir/field-wrapper.c @@ -42,8 +42,7 @@ struct bt_field_wrapper *bt_field_wrapper_new(void *data) goto end; } - bt_object_init(field_wrapper, NULL); - bt_object_set_is_shared((void *) field_wrapper, false); + bt_object_init_unique(&field_wrapper->base); BT_LOGD("Created empty field wrapper object: addr=%p", field_wrapper); diff --git a/lib/ctf-ir/fields.c b/lib/ctf-ir/fields.c index db2c93b0..3a0e063b 100644 --- a/lib/ctf-ir/fields.c +++ b/lib/ctf-ir/fields.c @@ -198,7 +198,6 @@ struct bt_field *bt_field_create_recursive(struct bt_field_type *type) goto end; } - bt_object_set_is_shared((void *) field, false); bt_field_type_freeze(type); end: @@ -581,7 +580,7 @@ struct bt_field *bt_field_integer_create(struct bt_field_type *type) if (integer) { bt_field_common_initialize(BT_TO_COMMON(integer), (void *) type, - NULL, &bt_field_integer_methods); + false, NULL, &bt_field_integer_methods); BT_LOGD("Created integer field object: addr=%p, ft-addr=%p", integer, type); } else { @@ -602,7 +601,8 @@ struct bt_field *bt_field_enumeration_create(struct bt_field_type *type) if (enumeration) { bt_field_common_initialize( BT_TO_COMMON(BT_TO_COMMON(enumeration)), - (void *) type, NULL, &bt_field_enumeration_methods); + (void *) type, false, NULL, + &bt_field_enumeration_methods); BT_LOGD("Created enumeration field object: addr=%p, ft-addr=%p", enumeration, type); } else { @@ -622,7 +622,8 @@ struct bt_field *bt_field_floating_point_create(struct bt_field_type *type) if (floating_point) { bt_field_common_initialize(BT_TO_COMMON(floating_point), - (void *) type, NULL, &bt_field_floating_point_methods); + (void *) type, false, NULL, + &bt_field_floating_point_methods); BT_LOGD("Created floating point number field object: addr=%p, ft-addr=%p", floating_point, type); } else { @@ -635,7 +636,7 @@ struct bt_field *bt_field_floating_point_create(struct bt_field_type *type) BT_HIDDEN int bt_field_common_structure_initialize(struct bt_field_common *field, struct bt_field_type_common *type, - bt_object_release_func release_func, + bool is_shared, bt_object_release_func release_func, struct bt_field_common_methods *methods, bt_field_common_create_func field_create_func, GDestroyNotify field_release_func) @@ -647,7 +648,8 @@ int bt_field_common_structure_initialize(struct bt_field_common *field, size_t i; BT_LOGD("Initializing common structure field object: ft-addr=%p", type); - bt_field_common_initialize(field, type, release_func, methods); + bt_field_common_initialize(field, type, is_shared, + release_func, methods); structure->fields = g_ptr_array_new_with_free_func(field_release_func); g_ptr_array_set_size(structure->fields, structure_type->fields->len); @@ -690,7 +692,7 @@ struct bt_field *bt_field_structure_create(struct bt_field_type *type) } iret = bt_field_common_structure_initialize(BT_TO_COMMON(structure), - (void *) type, NULL, &bt_field_structure_methods, + (void *) type, false, NULL, &bt_field_structure_methods, (bt_field_common_create_func) bt_field_create_recursive, (GDestroyNotify) bt_field_destroy_recursive); if (iret) { @@ -708,7 +710,7 @@ end: BT_HIDDEN int bt_field_common_variant_initialize(struct bt_field_common *field, struct bt_field_type_common *type, - bt_object_release_func release_func, + bool is_shared, bt_object_release_func release_func, struct bt_field_common_methods *methods, bt_field_common_create_func field_create_func, GDestroyNotify field_release_func) @@ -720,7 +722,8 @@ int bt_field_common_variant_initialize(struct bt_field_common *field, size_t i; BT_LOGD("Initializing common variant field object: ft-addr=%p", type); - bt_field_common_initialize(field, type, release_func, methods); + bt_field_common_initialize(field, type, is_shared, + release_func, methods); ret = bt_field_type_common_variant_update_choices(type); if (ret) { BT_LOGE("Cannot update common variant field type choices: " @@ -759,14 +762,15 @@ end: BT_HIDDEN int bt_field_common_string_initialize(struct bt_field_common *field, struct bt_field_type_common *type, - bt_object_release_func release_func, + bool is_shared, bt_object_release_func release_func, struct bt_field_common_methods *methods) { int ret = 0; struct bt_field_common_string *string = BT_FROM_COMMON(field); BT_LOGD("Initializing common string field object: ft-addr=%p", type); - bt_field_common_initialize(field, type, release_func, methods); + bt_field_common_initialize(field, type, is_shared, + release_func, methods); string->buf = g_array_sized_new(FALSE, FALSE, sizeof(char), 1); if (!string->buf) { ret = -1; @@ -796,7 +800,7 @@ struct bt_field *bt_field_variant_create(struct bt_field_type *type) } iret = bt_field_common_variant_initialize(BT_TO_COMMON(variant), - (void *) type, NULL, &bt_field_variant_methods, + (void *) type, false, NULL, &bt_field_variant_methods, (bt_field_common_create_func) bt_field_create_recursive, (GDestroyNotify) bt_field_destroy_recursive); if (iret) { @@ -814,7 +818,7 @@ end: BT_HIDDEN int bt_field_common_array_initialize(struct bt_field_common *field, struct bt_field_type_common *type, - bt_object_release_func release_func, + bool is_shared, bt_object_release_func release_func, struct bt_field_common_methods *methods, bt_field_common_create_func field_create_func, GDestroyNotify field_destroy_func) @@ -827,7 +831,8 @@ int bt_field_common_array_initialize(struct bt_field_common *field, BT_LOGD("Initializing common array field object: ft-addr=%p", type); BT_ASSERT(type); - bt_field_common_initialize(field, type, release_func, methods); + bt_field_common_initialize(field, type, is_shared, + release_func, methods); array_length = array_type->length; array->elements = g_ptr_array_sized_new(array_length); if (!array->elements) { @@ -870,7 +875,7 @@ struct bt_field *bt_field_array_create(struct bt_field_type *type) } ret = bt_field_common_array_initialize(BT_TO_COMMON(array), - (void *) type, NULL, &bt_field_array_methods, + (void *) type, false, NULL, &bt_field_array_methods, (bt_field_common_create_func) bt_field_create_recursive, (GDestroyNotify) bt_field_destroy_recursive); if (ret) { @@ -888,7 +893,7 @@ end: BT_HIDDEN int bt_field_common_sequence_initialize(struct bt_field_common *field, struct bt_field_type_common *type, - bt_object_release_func release_func, + bool is_shared, bt_object_release_func release_func, struct bt_field_common_methods *methods, GDestroyNotify field_destroy_func) { @@ -897,7 +902,8 @@ int bt_field_common_sequence_initialize(struct bt_field_common *field, BT_LOGD("Initializing common sequence field object: ft-addr=%p", type); BT_ASSERT(type); - bt_field_common_initialize(field, type, release_func, methods); + bt_field_common_initialize(field, type, is_shared, + release_func, methods); sequence->elements = g_ptr_array_new(); if (!sequence->elements) { ret = -1; @@ -928,7 +934,7 @@ struct bt_field *bt_field_sequence_create(struct bt_field_type *type) } ret = bt_field_common_sequence_initialize(BT_TO_COMMON(sequence), - (void *) type, NULL, &bt_field_sequence_methods, + (void *) type, false, NULL, &bt_field_sequence_methods, (GDestroyNotify) bt_field_destroy_recursive); if (ret) { BT_PUT(sequence); @@ -952,7 +958,7 @@ struct bt_field *bt_field_string_create(struct bt_field_type *type) if (string) { bt_field_common_string_initialize(BT_TO_COMMON(string), - (void *) type, NULL, &bt_field_string_methods); + (void *) type, false, NULL, &bt_field_string_methods); BT_LOGD("Created string field object: addr=%p, ft-addr=%p", string, type); } else { diff --git a/lib/ctf-ir/packet.c b/lib/ctf-ir/packet.c index 232d5bd8..227a7fd9 100644 --- a/lib/ctf-ir/packet.c +++ b/lib/ctf-ir/packet.c @@ -221,7 +221,8 @@ struct bt_packet *bt_packet_new(struct bt_stream *stream) goto end; } - bt_object_init(packet, (bt_object_release_func) bt_packet_recycle); + bt_object_init_shared(&packet->base, + (bt_object_release_func) bt_packet_recycle); packet->stream = bt_get(stream); if (trace->common.packet_header_field_type) { diff --git a/lib/ctf-ir/stream-class.c b/lib/ctf-ir/stream-class.c index 45f519ad..52a5ed6d 100644 --- a/lib/ctf-ir/stream-class.c +++ b/lib/ctf-ir/stream-class.c @@ -55,10 +55,10 @@ int bt_stream_class_common_initialize(struct bt_stream_class_common *stream_clas { BT_LOGD("Initializing common stream class object: name=\"%s\"", name); - bt_object_init(stream_class, release_func); + bt_object_init_shared_with_parent(&stream_class->base, release_func); stream_class->name = g_string_new(name); stream_class->event_classes = g_ptr_array_new_with_free_func( - (GDestroyNotify) bt_object_release); + (GDestroyNotify) bt_object_try_spec_release); if (!stream_class->event_classes) { BT_LOGE_STR("Failed to allocate a GPtrArray."); goto error; @@ -516,7 +516,7 @@ int bt_stream_class_common_add_event_class( *event_id = stream_class->next_event_id; } - bt_object_set_parent(event_class, stream_class); + bt_object_set_parent(&event_class->base, &stream_class->base); if (trace) { /* diff --git a/lib/ctf-ir/stream.c b/lib/ctf-ir/stream.c index 4eb05a8b..8e5b18c5 100644 --- a/lib/ctf-ir/stream.c +++ b/lib/ctf-ir/stream.c @@ -95,7 +95,7 @@ int bt_stream_common_initialize( int ret = 0; struct bt_trace_common *trace = NULL; - bt_object_init(stream, release_func); + bt_object_init_shared_with_parent(&stream->base, release_func); if (!stream_class) { BT_LOGW_STR("Invalid parameter: stream class is NULL."); @@ -144,7 +144,7 @@ int bt_stream_common_initialize( * Acquire reference to parent since stream will become publicly * reachable; it needs its parent to remain valid. */ - bt_object_set_parent(stream, trace); + bt_object_set_parent(&stream->base, &trace->base); stream->stream_class = stream_class; stream->id = (int64_t) id; stream->destroy_listeners = g_array_new(FALSE, TRUE, diff --git a/lib/ctf-ir/trace.c b/lib/ctf-ir/trace.c index eb4211cf..c9a588fb 100644 --- a/lib/ctf-ir/trace.c +++ b/lib/ctf-ir/trace.c @@ -117,7 +117,7 @@ int bt_trace_common_initialize(struct bt_trace_common *trace, BT_LOGD_STR("Initializing common trace object."); trace->native_byte_order = BT_BYTE_ORDER_UNSPECIFIED; - bt_object_init(trace, release_func); + bt_object_init_shared_with_parent(&trace->base, release_func); trace->clock_classes = g_ptr_array_new_with_free_func( (GDestroyNotify) bt_put); if (!trace->clock_classes) { @@ -126,14 +126,14 @@ int bt_trace_common_initialize(struct bt_trace_common *trace, } trace->streams = g_ptr_array_new_with_free_func( - (GDestroyNotify) bt_object_release); + (GDestroyNotify) bt_object_try_spec_release); if (!trace->streams) { BT_LOGE_STR("Failed to allocate one GPtrArray."); goto error; } trace->stream_classes = g_ptr_array_new_with_free_func( - (GDestroyNotify) bt_object_release); + (GDestroyNotify) bt_object_try_spec_release); if (!trace->stream_classes) { BT_LOGE_STR("Failed to allocate one GPtrArray."); goto error; @@ -1412,7 +1412,7 @@ int bt_trace_common_add_stream_class(struct bt_trace_common *trace, } } - bt_object_set_parent(stream_class, trace); + bt_object_set_parent(&stream_class->base, &trace->base); g_ptr_array_add(trace->stream_classes, stream_class); /* @@ -1473,7 +1473,7 @@ int bt_trace_common_add_stream_class(struct bt_trace_common *trace, end: if (ret) { - bt_object_set_parent(stream_class, NULL); + bt_object_set_parent(&stream_class->base, NULL); if (ec_validation_outputs) { for (i = 0; i < event_class_count; i++) { diff --git a/lib/ctf-writer/clock.c b/lib/ctf-writer/clock.c index 106947e2..0437207b 100644 --- a/lib/ctf-writer/clock.c +++ b/lib/ctf-writer/clock.c @@ -57,7 +57,7 @@ struct bt_ctf_clock *bt_ctf_clock_create(const char *name) goto error; } - bt_object_init(clock, bt_ctf_clock_destroy); + bt_object_init_shared(&clock->base, bt_ctf_clock_destroy); clock->value = 0; /* Pre-2.0.0 backward compatibility: default frequency is 1 GHz */ diff --git a/lib/ctf-writer/event.c b/lib/ctf-writer/event.c index 447571c4..1e61cb98 100644 --- a/lib/ctf-writer/event.c +++ b/lib/ctf-writer/event.c @@ -128,7 +128,7 @@ struct bt_ctf_event *bt_ctf_event_create(struct bt_ctf_event_class *event_class) ret = bt_event_common_initialize(BT_TO_COMMON(event), BT_TO_COMMON(event_class), expected_clock_class, - bt_ctf_event_destroy, + true, bt_ctf_event_destroy, (bt_validation_flag_copy_field_type_func) bt_ctf_field_type_copy, false, map_clock_classes_func, @@ -161,7 +161,7 @@ struct bt_ctf_stream *bt_ctf_event_borrow_stream(struct bt_ctf_event *event) { BT_ASSERT(event); return (struct bt_ctf_stream *) - bt_object_borrow_parent(BT_TO_COMMON(event)); + bt_object_borrow_parent(&BT_TO_COMMON(event)->base); } struct bt_ctf_stream *bt_ctf_event_get_stream(struct bt_ctf_event *event) diff --git a/lib/ctf-writer/fields.c b/lib/ctf-writer/fields.c index 749494cf..1d075078 100644 --- a/lib/ctf-writer/fields.c +++ b/lib/ctf-writer/fields.c @@ -882,6 +882,7 @@ struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *type) if (integer) { bt_field_common_initialize(BT_TO_COMMON(integer), (void *) type, + true, (bt_object_release_func) bt_ctf_field_integer_destroy, &bt_ctf_field_integer_methods); integer->common.spec.writer.serialize_func = @@ -912,7 +913,7 @@ struct bt_ctf_field *bt_ctf_field_enumeration_create( bt_field_common_initialize(BT_TO_COMMON(enumeration), (void *) type, - (bt_object_release_func) + true, (bt_object_release_func) bt_ctf_field_enumeration_destroy_recursive, &bt_ctf_field_enumeration_methods); enumeration->container = (void *) bt_ctf_field_create( @@ -944,7 +945,7 @@ struct bt_ctf_field *bt_ctf_field_floating_point_create( if (floating_point) { bt_field_common_initialize(BT_TO_COMMON(floating_point), (void *) type, - (bt_object_release_func) + true, (bt_object_release_func) bt_ctf_field_floating_point_destroy, &bt_ctf_field_floating_point_methods); floating_point->common.spec.writer.serialize_func = @@ -975,7 +976,7 @@ struct bt_ctf_field *bt_ctf_field_structure_create( iret = bt_field_common_structure_initialize(BT_TO_COMMON(structure), (void *) type, - (bt_object_release_func) + true, (bt_object_release_func) bt_ctf_field_structure_destroy_recursive, &bt_ctf_field_structure_methods, (bt_field_common_create_func) bt_ctf_field_create, @@ -1010,7 +1011,7 @@ struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *type) bt_field_common_variant_initialize(BT_TO_COMMON(BT_TO_COMMON(variant)), (void *) type, - (bt_object_release_func) + true, (bt_object_release_func) bt_ctf_field_variant_destroy_recursive, &bt_ctf_field_variant_methods, (bt_field_common_create_func) bt_ctf_field_create, @@ -1043,7 +1044,7 @@ struct bt_ctf_field *bt_ctf_field_array_create(struct bt_ctf_field_type *type) ret = bt_field_common_array_initialize(BT_TO_COMMON(array), (void *) type, - (bt_object_release_func) + true, (bt_object_release_func) bt_ctf_field_array_destroy_recursive, &bt_ctf_field_array_methods, (bt_field_common_create_func) bt_ctf_field_create, @@ -1073,7 +1074,7 @@ struct bt_ctf_field *bt_ctf_field_sequence_create(struct bt_ctf_field_type *type if (sequence) { bt_field_common_sequence_initialize(BT_TO_COMMON(sequence), (void *) type, - (bt_object_release_func) + true, (bt_object_release_func) bt_ctf_field_sequence_destroy_recursive, &bt_ctf_field_sequence_methods, (GDestroyNotify) bt_put); @@ -1099,7 +1100,7 @@ struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *type) if (string) { bt_field_common_string_initialize(BT_TO_COMMON(string), (void *) type, - (bt_object_release_func) + true, (bt_object_release_func) bt_ctf_field_string_destroy, &bt_ctf_field_string_methods); string->common.spec.writer.serialize_func = diff --git a/lib/ctf-writer/stream.c b/lib/ctf-writer/stream.c index b9f9752d..5ed1ebaf 100644 --- a/lib/ctf-writer/stream.c +++ b/lib/ctf-writer/stream.c @@ -154,7 +154,9 @@ int set_packet_header_uuid(struct bt_ctf_stream *stream) goto end; } - trace = (struct bt_ctf_trace *) bt_object_get_parent(stream); + trace = (struct bt_ctf_trace *) + bt_object_get_parent(&stream->common.base); + for (i = 0; i < 16; i++) { struct bt_ctf_field *uuid_element = bt_ctf_field_array_get_field(uuid_field, i); @@ -854,7 +856,7 @@ end: static void release_event(struct bt_ctf_event *event) { - if (bt_object_get_ref_count(event)) { + if (bt_object_get_ref_count(&event->common.base)) { /* * The event is being orphaned, but it must guarantee the * existence of its event class for the duration of its @@ -863,7 +865,7 @@ void release_event(struct bt_ctf_event *event) bt_get(event->common.class); BT_PUT(event->common.base.parent); } else { - bt_object_release(event); + bt_object_try_spec_release(&event->common.base); } } @@ -1006,7 +1008,8 @@ struct bt_ctf_stream *bt_ctf_stream_create_with_id( } stream->pos.fd = -1; - writer = (struct bt_ctf_writer *) bt_object_get_parent(trace); + writer = (struct bt_ctf_writer *) + bt_object_get_parent(&trace->common.base); stream->last_ts_end = -1ULL; BT_LOGD("CTF writer stream object belongs writer's trace: " "writer-addr=%p", writer); @@ -1355,7 +1358,7 @@ int bt_ctf_stream_append_event(struct bt_ctf_stream *stream, goto end; } - bt_object_set_parent(event, stream); + bt_object_set_parent(&event->common.base, &stream->common.base); BT_LOGV_STR("Automatically populating the header of the event to append."); ret = auto_populate_event_header(stream, event); if (ret) { @@ -1398,8 +1401,7 @@ error: * Orphan the event; we were not successful in associating it to * a stream. */ - bt_object_set_parent(event, NULL); - + bt_object_set_parent(&event->common.base, NULL); return ret; } @@ -1512,7 +1514,8 @@ int bt_ctf_stream_set_packet_header(struct bt_ctf_stream *stream, goto end; } - trace = (struct bt_ctf_trace *) bt_object_get_parent(stream); + trace = (struct bt_ctf_trace *) + bt_object_get_parent(&stream->common.base); if (!field) { if (trace->common.packet_header_field_type) { diff --git a/lib/ctf-writer/writer.c b/lib/ctf-writer/writer.c index b51dd7ff..0b360c37 100644 --- a/lib/ctf-writer/writer.c +++ b/lib/ctf-writer/writer.c @@ -120,7 +120,7 @@ struct bt_ctf_writer *bt_ctf_writer_create(const char *path) metadata_path = g_build_filename(path, "metadata", NULL); - bt_object_init(writer, bt_ctf_writer_destroy); + bt_object_init_shared(&writer->base, bt_ctf_writer_destroy); writer->path = g_string_new(path); if (!writer->path) { goto error_destroy; @@ -148,7 +148,7 @@ struct bt_ctf_writer *bt_ctf_writer_create(const char *path) goto error_destroy; } - bt_object_set_parent(writer->trace, writer); + bt_object_set_parent(&writer->trace->common.base, &writer->base); bt_put(writer->trace); /* Default to little-endian */ @@ -195,7 +195,7 @@ void bt_ctf_writer_destroy(struct bt_object *obj) } } - bt_object_release(writer->trace); + bt_object_try_spec_release(&writer->trace->common.base); g_free(writer); } diff --git a/lib/graph/clock-class-priority-map.c b/lib/graph/clock-class-priority-map.c index 2d1dc520..e8f9654b 100644 --- a/lib/graph/clock-class-priority-map.c +++ b/lib/graph/clock-class-priority-map.c @@ -70,7 +70,8 @@ struct bt_clock_class_priority_map *bt_clock_class_priority_map_create() goto error; } - bt_object_init(cc_prio_map, bt_clock_class_priority_map_destroy); + bt_object_init_shared(&cc_prio_map->base, + bt_clock_class_priority_map_destroy); cc_prio_map->entries = g_ptr_array_new_with_free_func( (GDestroyNotify) bt_put); if (!cc_prio_map->entries) { diff --git a/lib/graph/component-class.c b/lib/graph/component-class.c index 1df85b48..7ce6667f 100644 --- a/lib/graph/component-class.c +++ b/lib/graph/component-class.c @@ -84,7 +84,7 @@ int bt_component_class_init(struct bt_component_class *class, { int ret = 0; - bt_object_init(class, bt_component_class_destroy); + bt_object_init_shared(&class->base, bt_component_class_destroy); class->type = type; class->name = g_string_new(name); if (!class->name) { diff --git a/lib/graph/component.c b/lib/graph/component.c index 185b8d10..8ffab8e0 100644 --- a/lib/graph/component.c +++ b/lib/graph/component.c @@ -86,7 +86,7 @@ void bt_component_destroy(struct bt_object *obj) * bt_put(): the reference count would go from 1 to 0 again and * this function would be called again. */ - obj->ref_count.count++; + obj->ref_count++; component = container_of(obj, struct bt_component, base); BT_LOGD("Destroying component: addr=%p, name=\"%s\", graph-addr=%p", component, bt_component_get_name(component), @@ -266,7 +266,8 @@ enum bt_component_status bt_component_create( goto end; } - bt_object_init(component, bt_component_destroy); + bt_object_init_shared_with_parent(&component->base, + bt_component_destroy); component->class = bt_get(component_class); component->destroy = component_destroy_funcs[type]; component->name = g_string_new(name); @@ -277,7 +278,7 @@ enum bt_component_status bt_component_create( } component->input_ports = g_ptr_array_new_with_free_func( - bt_object_release); + (GDestroyNotify) bt_object_try_spec_release); if (!component->input_ports) { BT_LOGE_STR("Failed to allocate one GPtrArray."); status = BT_COMPONENT_STATUS_NOMEM; @@ -285,7 +286,7 @@ enum bt_component_status bt_component_create( } component->output_ports = g_ptr_array_new_with_free_func( - bt_object_release); + (GDestroyNotify) bt_object_try_spec_release); if (!component->output_ports) { BT_LOGE_STR("Failed to allocate one GPtrArray."); status = BT_COMPONENT_STATUS_NOMEM; @@ -368,7 +369,8 @@ BT_HIDDEN void bt_component_set_graph(struct bt_component *component, struct bt_graph *graph) { - bt_object_set_parent(component, graph ? &graph->base : NULL); + bt_object_set_parent(&component->base, + graph ? &graph->base : NULL); } struct bt_graph *bt_component_borrow_graph(struct bt_component *component) diff --git a/lib/graph/connection.c b/lib/graph/connection.c index 91d130ed..10f80747 100644 --- a/lib/graph/connection.c +++ b/lib/graph/connection.c @@ -79,9 +79,9 @@ void bt_connection_destroy(struct bt_object *obj) static void bt_connection_try_remove_from_graph(struct bt_connection *connection) { - void *graph = bt_object_borrow_parent(&connection->base); + void *graph = (void *) bt_object_borrow_parent(&connection->base); - if (connection->base.ref_count.count > 0 || + if (connection->base.ref_count > 0 || connection->downstream_port || connection->upstream_port || connection->iterators->len > 0) { @@ -151,8 +151,9 @@ struct bt_connection *bt_connection_create( goto end; } - bt_object_init(connection, bt_connection_destroy); - bt_object_set_parent_is_owner_listener(connection, + bt_object_init_shared_with_parent(&connection->base, + bt_connection_destroy); + bt_object_set_parent_is_owner_listener_func(&connection->base, bt_connection_parent_is_owner); connection->iterators = g_ptr_array_new(); if (!connection->iterators) { @@ -168,7 +169,7 @@ struct bt_connection *bt_connection_create( bt_port_set_connection(upstream_port, connection); BT_LOGD_STR("Setting downstream port's connection."); bt_port_set_connection(downstream_port, connection); - bt_object_set_parent(connection, &graph->base); + bt_object_set_parent(&connection->base, &graph->base); BT_LOGD("Created connection: " "graph-addr=%p, upstream-port-addr=%p, uptream-port-name=\"%s\", " "downstream-port-addr=%p, downstream-port-name=\"%s\", " diff --git a/lib/graph/graph.c b/lib/graph/graph.c index 4a3c39e7..7db5b761 100644 --- a/lib/graph/graph.c +++ b/lib/graph/graph.c @@ -118,7 +118,7 @@ void bt_graph_destroy(struct bt_object *obj) * ensures that this function is not called two times. */ BT_LOGD("Destroying graph: addr=%p", graph); - obj->ref_count.count++; + obj->ref_count++; /* * Cancel the graph to disallow some operations, like creating @@ -211,14 +211,15 @@ struct bt_graph *bt_graph_create(void) goto end; } - bt_object_init(graph, bt_graph_destroy); - - graph->connections = g_ptr_array_new_with_free_func(bt_object_release); + bt_object_init_shared(&graph->base, bt_graph_destroy); + graph->connections = g_ptr_array_new_with_free_func( + (GDestroyNotify) bt_object_try_spec_release); if (!graph->connections) { BT_LOGE_STR("Failed to allocate one GPtrArray."); goto error; } - graph->components = g_ptr_array_new_with_free_func(bt_object_release); + graph->components = g_ptr_array_new_with_free_func( + (GDestroyNotify) bt_object_try_spec_release); if (!graph->components) { BT_LOGE_STR("Failed to allocate one GPtrArray."); goto error; @@ -1186,7 +1187,7 @@ int bt_graph_remove_unconnected_component(struct bt_graph *graph, BT_ASSERT(graph); BT_ASSERT(component); - BT_ASSERT(component->base.ref_count.count == 0); + BT_ASSERT(component->base.ref_count == 0); BT_ASSERT(bt_component_borrow_graph(component) == graph); init_can_consume = graph->can_consume; @@ -1244,8 +1245,8 @@ int bt_graph_remove_unconnected_component(struct bt_graph *graph, } /* - * This calls bt_object_release() on the component, and since - * its reference count is 0, its destructor is called. Its + * This calls bt_object_try_spec_release() on the component, and + * since its reference count is 0, its destructor is called. Its * destructor calls the user's finalization method (if set). */ g_ptr_array_remove(graph->components, component); diff --git a/lib/graph/iterator.c b/lib/graph/iterator.c index b5eb5649..2c83d47b 100644 --- a/lib/graph/iterator.c +++ b/lib/graph/iterator.c @@ -158,7 +158,7 @@ void bt_private_connection_notification_iterator_destroy(struct bt_object *obj) * reference count would go from 1 to 0 again and this function * would be called again. */ - obj->ref_count.count++; + obj->ref_count++; iterator = (void *) obj; BT_LOGD("Destroying private connection notification iterator object: addr=%p", iterator); @@ -292,7 +292,7 @@ void init_notification_iterator(struct bt_notification_iterator *iterator, enum bt_notification_iterator_type type, bt_object_release_func destroy) { - bt_object_init(iterator, destroy); + bt_object_init_shared(&iterator->base, destroy); iterator->type = type; } diff --git a/lib/graph/notification/notification.c b/lib/graph/notification/notification.c index 0bcfb7df..f049118c 100644 --- a/lib/graph/notification/notification.c +++ b/lib/graph/notification/notification.c @@ -53,7 +53,7 @@ void bt_notification_init(struct bt_notification *notification, BT_ASSERT(type >= 0 && type < BT_NOTIFICATION_TYPE_NR); notification->type = type; init_seq_num(notification); - bt_object_init(¬ification->base, release); + bt_object_init_shared(¬ification->base, release); notification->graph = graph; if (graph) { diff --git a/lib/graph/port.c b/lib/graph/port.c index 950a0a26..5ed5f932 100644 --- a/lib/graph/port.c +++ b/lib/graph/port.c @@ -85,7 +85,7 @@ struct bt_port *bt_port_create(struct bt_component *parent_component, parent_component, bt_component_get_name(parent_component), bt_port_type_string(type), name); - bt_object_init(port, bt_port_destroy); + bt_object_init_shared_with_parent(&port->base, bt_port_destroy); port->name = g_string_new(name); if (!port->name) { BT_LOGE_STR("Failed to allocate one GString."); @@ -95,7 +95,7 @@ struct bt_port *bt_port_create(struct bt_component *parent_component, port->type = type; port->user_data = user_data; - bt_object_set_parent(port, &parent_component->base); + bt_object_set_parent(&port->base, &parent_component->base); BT_LOGD("Created port for component: " "comp-addr=%p, comp-name=\"%s\", port-type=%s, " "port-name=\"%s\", port-addr=%p", @@ -138,7 +138,7 @@ end: struct bt_component *bt_port_get_component(struct bt_port *port) { - return (struct bt_component *) bt_object_get_parent(port); + return (struct bt_component *) bt_object_get_parent(&port->base); } struct bt_private_connection *bt_private_port_get_private_connection( @@ -184,7 +184,7 @@ enum bt_port_status bt_private_port_remove_from_component( goto end; } - comp = (void *) bt_object_get_parent(port); + comp = (void *) bt_object_get_parent(&port->base); if (!comp) { BT_LOGV("Port already removed from its component: " "port-addr=%p, port-name=\"%s\", ", diff --git a/lib/graph/query-executor.c b/lib/graph/query-executor.c index 89ae9a11..bd9b5377 100644 --- a/lib/graph/query-executor.c +++ b/lib/graph/query-executor.c @@ -52,7 +52,8 @@ struct bt_query_executor *bt_query_executor_create(void) goto end; } - bt_object_init(query_exec, bt_query_executor_destroy); + bt_object_init_shared(&query_exec->base, + bt_query_executor_destroy); BT_LOGD("Created query executor: addr=%p", query_exec); end: diff --git a/lib/lib-logging.c b/lib/lib-logging.c index 67454601..b2d09547 100644 --- a/lib/lib-logging.c +++ b/lib/lib-logging.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -131,10 +130,10 @@ static inline void format_port(char **buf_ch, bool extended, static inline void format_connection(char **buf_ch, bool extended, const char *prefix, struct bt_connection *connection); -static inline void format_ref_count(char **buf_ch, bool extended, +static inline void format_object(char **buf_ch, bool extended, const char *prefix, struct bt_object *obj) { - BUF_APPEND(", %sref-count=%lu", prefix, obj->ref_count.count); + BUF_APPEND(", %sref-count=%llu", prefix, obj->ref_count); } static inline void format_object_pool(char **buf_ch, bool extended, @@ -713,7 +712,7 @@ static inline void format_stream_common(char **buf_ch, bool extended, return; } - trace = (void *) bt_object_borrow_parent(stream); + trace = (void *) bt_object_borrow_parent(&stream->base); if (!trace) { return; } @@ -808,7 +807,7 @@ static inline void format_packet(char **buf_ch, bool extended, BUF_APPEND(", %sstream-addr=%p", PRFIELD(stream)); SET_TMP_PREFIX("stream-"); format_stream(buf_ch, false, tmp_prefix, stream); - trace = (struct bt_trace *) bt_object_borrow_parent(stream); + trace = (struct bt_trace *) bt_object_borrow_parent(&stream->common.base); if (!trace) { return; } @@ -1489,9 +1488,6 @@ static inline void handle_conversion_specifier_bt(void *priv_data, switch (cat) { case CAT_DEFAULT: switch (*fmt_ch) { - case 'r': - format_ref_count(buf_ch, extended, prefix, obj); - break; case 'F': format_field_type(buf_ch, extended, prefix, obj); break; @@ -1555,6 +1551,9 @@ static inline void handle_conversion_specifier_bt(void *priv_data, case 'o': format_object_pool(buf_ch, extended, prefix, obj); break; + case 'O': + format_object(buf_ch, extended, prefix, obj); + break; default: abort(); } diff --git a/lib/plugin/plugin-so.c b/lib/plugin/plugin-so.c index 2326ed8f..648f95d1 100644 --- a/lib/plugin/plugin-so.c +++ b/lib/plugin/plugin-so.c @@ -175,7 +175,8 @@ struct bt_plugin_so_shared_lib_handle *bt_plugin_so_shared_lib_handle_create( goto error; } - bt_object_init(shared_lib_handle, bt_plugin_so_shared_lib_handle_destroy); + bt_object_init_shared(&shared_lib_handle->base, + bt_plugin_so_shared_lib_handle_destroy); if (!path) { goto end; diff --git a/lib/ref.c b/lib/ref.c index e59187c6..ae2cef01 100644 --- a/lib/ref.c +++ b/lib/ref.c @@ -28,7 +28,6 @@ #include #include -#include #include void *bt_get(void *ptr) @@ -40,25 +39,10 @@ void *bt_get(void *ptr) } BT_ASSERT_PRE(obj->is_shared, "Object is not shared: addr=%p", obj); - - 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); + bt_object_get_no_null_check(obj); end: - return obj; + return ptr; } void bt_put(void *ptr) @@ -70,20 +54,7 @@ void bt_put(void *ptr) } BT_ASSERT_PRE(obj->is_shared, "Object is not shared: addr=%p", obj); - - 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); + BT_ASSERT_PRE(bt_object_get_ref_count(obj) > 0, + "Decrementing a reference count set to 0: addr=%p", ptr); + bt_object_put_no_null_check(obj); } diff --git a/lib/values.c b/lib/values.c index 4719e451..7514d52a 100644 --- a/lib/values.c +++ b/lib/values.c @@ -71,16 +71,21 @@ struct bt_value { bt_bool frozen; }; +static +void bt_value_null_instance_release_func(struct bt_object *obj) +{ + BT_LOGW("Releasing the null value singleton: addr=%p", obj); +} + static struct bt_value bt_value_null_instance = { .base = { - .ref_count = { - .count = 1, - .release = NULL, - }, - .release = NULL, - .parent = NULL, .is_shared = true, + .ref_count = 1, + .release_func = bt_value_null_instance_release_func, + .spec_release_func = NULL, + .parent_is_owner_listener_func = NULL, + .parent = NULL, }, .type = BT_VALUE_TYPE_NULL, .frozen = BT_TRUE, @@ -572,12 +577,12 @@ enum bt_value_type bt_value_get_type(const struct bt_value *object) static struct bt_value bt_value_create_base(enum bt_value_type type) { - struct bt_value base; + struct bt_value value; - base.type = type; - base.frozen = BT_FALSE; - bt_object_init(&base, bt_value_destroy); - return base; + value.type = type; + value.frozen = BT_FALSE; + bt_object_init_shared(&value.base, bt_value_destroy); + return value; } struct bt_value *bt_value_bool_create_init(bt_bool val) diff --git a/tests/lib/test_ctf_ir_ref.c b/tests/lib/test_ctf_ir_ref.c index c5ad8fcb..64d25e2b 100644 --- a/tests/lib/test_ctf_ir_ref.c +++ b/tests/lib/test_ctf_ir_ref.c @@ -518,38 +518,38 @@ static void test_example_scenario(void) 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, + ok(bt_object_get_ref_count((void *) weak_sc1) == 0, "Initial SC1 reference count is 0"); - ok(bt_object_get_ref_count(weak_sc2) == 0, + ok(bt_object_get_ref_count((void *) weak_sc2) == 0, "Initial SC2 reference count is 0"); - ok(bt_object_get_ref_count(weak_ec1) == 0, + ok(bt_object_get_ref_count((void *) weak_ec1) == 0, "Initial EC1 reference count is 0"); - ok(bt_object_get_ref_count(weak_ec2) == 0, + ok(bt_object_get_ref_count((void *) weak_ec2) == 0, "Initial EC2 reference count is 0"); - ok(bt_object_get_ref_count(weak_ec3) == 0, + ok(bt_object_get_ref_count((void *) 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, + ok(bt_object_get_ref_count((void *) user_a.tc) == 1, "TC1 reference count is 1"); /* User A acquires a reference to SC2 from TC1. */ user_a.sc = bt_trace_get_stream_class_by_index(user_a.tc, 1); ok(user_a.sc, "User A acquires SC2 from TC1"); - ok(bt_object_get_ref_count(weak_tc1) == 2, + ok(bt_object_get_ref_count((void *) weak_tc1) == 2, "TC1 reference count is 2"); - ok(bt_object_get_ref_count(weak_sc2) == 1, + ok(bt_object_get_ref_count((void *) weak_sc2) == 1, "SC2 reference count is 1"); /* User A acquires a reference to EC3 from SC2. */ user_a.ec = bt_stream_class_get_event_class_by_index(user_a.sc, 0); ok(user_a.ec, "User A acquires EC3 from SC2"); - ok(bt_object_get_ref_count(weak_tc1) == 2, + ok(bt_object_get_ref_count((void *) weak_tc1) == 2, "TC1 reference count is 2"); - ok(bt_object_get_ref_count(weak_sc2) == 2, + ok(bt_object_get_ref_count((void *) weak_sc2) == 2, "SC2 reference count is 2"); - ok(bt_object_get_ref_count(weak_ec3) == 1, + ok(bt_object_get_ref_count((void *) weak_ec3) == 1, "EC3 reference count is 1"); /* User A releases its reference to SC2. */ @@ -559,11 +559,11 @@ static void test_example_scenario(void) * We keep the pointer to SC2 around to validate its reference * count. */ - ok(bt_object_get_ref_count(weak_tc1) == 2, + ok(bt_object_get_ref_count((void *) weak_tc1) == 2, "TC1 reference count is 2"); - ok(bt_object_get_ref_count(weak_sc2) == 1, + ok(bt_object_get_ref_count((void *) weak_sc2) == 1, "SC2 reference count is 1"); - ok(bt_object_get_ref_count(weak_ec3) == 1, + ok(bt_object_get_ref_count((void *) weak_ec3) == 1, "EC3 reference count is 1"); /* User A releases its reference to TC1. */ @@ -573,60 +573,60 @@ static void test_example_scenario(void) * We keep the pointer to TC1 around to validate its reference * count. */ - ok(bt_object_get_ref_count(weak_tc1) == 1, + ok(bt_object_get_ref_count((void *) weak_tc1) == 1, "TC1 reference count is 1"); - ok(bt_object_get_ref_count(weak_sc2) == 1, + ok(bt_object_get_ref_count((void *) weak_sc2) == 1, "SC2 reference count is 1"); - ok(bt_object_get_ref_count(weak_ec3) == 1, + ok(bt_object_get_ref_count((void *) 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, + ok(bt_object_get_ref_count((void *) weak_tc1) == 2, "TC1 reference count is 2"); - ok(bt_object_get_ref_count(weak_sc1) == 1, + ok(bt_object_get_ref_count((void *) 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_stream_class_get_event_class_by_index(user_b.sc, 0); - ok(bt_object_get_ref_count(weak_ec1) == 1, + ok(bt_object_get_ref_count((void *) weak_ec1) == 1, "EC1 reference count is 1"); - ok(bt_object_get_ref_count(weak_sc1) == 2, + ok(bt_object_get_ref_count((void *) 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, + ok(bt_object_get_ref_count((void *) weak_ec3) == 0, "EC3 reference count is 1"); - ok(bt_object_get_ref_count(weak_sc2) == 0, + ok(bt_object_get_ref_count((void *) weak_sc2) == 0, "SC2 reference count is 0"); - ok(bt_object_get_ref_count(weak_tc1) == 1, + ok(bt_object_get_ref_count((void *) 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, + ok(bt_object_get_ref_count((void *) 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, + ok(bt_object_get_ref_count((void *) weak_tc1) == 1, "TC1 reference count is 1"); - ok(bt_object_get_ref_count(weak_sc1) == 1, + ok(bt_object_get_ref_count((void *) weak_sc1) == 1, "SC1 reference count is 1"); - ok(bt_object_get_ref_count(weak_sc2) == 0, + ok(bt_object_get_ref_count((void *) weak_sc2) == 0, "SC2 reference count is 0"); - ok(bt_object_get_ref_count(weak_ec1) == 1, + ok(bt_object_get_ref_count((void *) weak_ec1) == 1, "EC1 reference count is 1"); - ok(bt_object_get_ref_count(weak_ec2) == 0, + ok(bt_object_get_ref_count((void *) weak_ec2) == 0, "EC2 reference count is 0"); - ok(bt_object_get_ref_count(weak_ec3) == 0, + ok(bt_object_get_ref_count((void *) weak_ec3) == 0, "EC3 reference count is 0"); /* Reclaim last reference held by User C. */ -- 2.34.1