clock: clear callback on unparent

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Paolo Bonzini 2024-11-28 13:21:13 +01:00
parent a3057c52f4
commit 4cc055039f
3 changed files with 18 additions and 17 deletions

View file

@ -44,16 +44,12 @@ Clock *clock_new(Object *parent, const char *name)
void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque, void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque,
unsigned int events) unsigned int events)
{ {
assert(OBJECT(clk)->parent);
clk->callback = cb; clk->callback = cb;
clk->callback_opaque = opaque; clk->callback_opaque = opaque;
clk->callback_events = events; clk->callback_events = events;
} }
void clock_clear_callback(Clock *clk)
{
clock_set_callback(clk, NULL, NULL, 0);
}
bool clock_set(Clock *clk, uint64_t period) bool clock_set(Clock *clk, uint64_t period)
{ {
if (clk->period == period) { if (clk->period == period) {
@ -168,6 +164,16 @@ static void clock_period_prop_get(Object *obj, Visitor *v, const char *name,
visit_type_uint64(v, name, &period, errp); visit_type_uint64(v, name, &period, errp);
} }
static void clock_unparent(Object *obj)
{
/*
* Callback are registered by the parent, which might die anytime after
* it's unparented the children. Avoid having a callback to a deleted
* object in case the clock is still referenced somewhere else (eg: by
* a clock output).
*/
clock_set_callback(CLOCK(obj), NULL, NULL, 0);
}
static void clock_initfn(Object *obj) static void clock_initfn(Object *obj)
{ {
@ -200,11 +206,17 @@ static void clock_finalizefn(Object *obj)
g_free(clk->canonical_path); g_free(clk->canonical_path);
} }
static void clock_class_init(ObjectClass *klass, void *data)
{
klass->unparent = clock_unparent;
}
static const TypeInfo clock_info = { static const TypeInfo clock_info = {
.name = TYPE_CLOCK, .name = TYPE_CLOCK,
.parent = TYPE_OBJECT, .parent = TYPE_OBJECT,
.instance_size = sizeof(Clock), .instance_size = sizeof(Clock),
.instance_init = clock_initfn, .instance_init = clock_initfn,
.class_init = clock_class_init,
.instance_finalize = clock_finalizefn, .instance_finalize = clock_finalizefn,
}; };

View file

@ -87,11 +87,8 @@ void qdev_finalize_clocklist(DeviceState *dev)
if (!ncl->output && !ncl->alias) { if (!ncl->output && !ncl->alias) {
/* /*
* We kept a reference on the input clock to ensure it lives up to * We kept a reference on the input clock to ensure it lives up to
* this point so we can safely remove the callback. * this point; it is used by the monitor to show the frequency.
* It avoids having a callback to a deleted object if ncl->clock
* is still referenced somewhere else (eg: by a clock output).
*/ */
clock_clear_callback(ncl->clock);
object_unref(OBJECT(ncl->clock)); object_unref(OBJECT(ncl->clock));
} }
g_free(ncl->name); g_free(ncl->name);

View file

@ -141,14 +141,6 @@ Clock *clock_new(Object *parent, const char *name);
void clock_set_callback(Clock *clk, ClockCallback *cb, void clock_set_callback(Clock *clk, ClockCallback *cb,
void *opaque, unsigned int events); void *opaque, unsigned int events);
/**
* clock_clear_callback:
* @clk: the clock to delete the callback from
*
* Unregister the callback registered with clock_set_callback.
*/
void clock_clear_callback(Clock *clk);
/** /**
* clock_set_source: * clock_set_source:
* @clk: the clock. * @clk: the clock.