clock: clear callback on unparent
authorPaolo Bonzini <pbonzini@redhat.com>
Thu, 28 Nov 2024 12:21:13 +0000 (13:21 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 10 Dec 2024 17:49:24 +0000 (18:49 +0100)
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
hw/core/clock.c
hw/core/qdev-clock.c
include/hw/clock.h

index cbe7b1bc469106e48bec499cfd6b0e17ed66bb8a..391095eb4e5ec08c290d4c0bb92f8b2835402c80 100644 (file)
@@ -44,16 +44,12 @@ Clock *clock_new(Object *parent, const char *name)
 void clock_set_callback(Clock *clk, ClockCallback *cb, void *opaque,
                         unsigned int events)
 {
+    assert(OBJECT(clk)->parent);
     clk->callback = cb;
     clk->callback_opaque = opaque;
     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)
 {
     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);
 }
 
+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)
 {
@@ -200,11 +206,17 @@ static void clock_finalizefn(Object *obj)
     g_free(clk->canonical_path);
 }
 
+static void clock_class_init(ObjectClass *klass, void *data)
+{
+    klass->unparent = clock_unparent;
+}
+
 static const TypeInfo clock_info = {
     .name              = TYPE_CLOCK,
     .parent            = TYPE_OBJECT,
     .instance_size     = sizeof(Clock),
     .instance_init     = clock_initfn,
+    .class_init        = clock_class_init,
     .instance_finalize = clock_finalizefn,
 };
 
index 82799577f3e959c655ccca861ee394b3280b5262..ca65685c04ebc40ca554b1a1d36dd39bedb924bc 100644 (file)
@@ -87,11 +87,8 @@ void qdev_finalize_clocklist(DeviceState *dev)
         if (!ncl->output && !ncl->alias) {
             /*
              * We kept a reference on the input clock to ensure it lives up to
-             * this point so we can safely remove the callback.
-             * It avoids having a callback to a deleted object if ncl->clock
-             * is still referenced somewhere else (eg: by a clock output).
+             * this point; it is used by the monitor to show the frequency.
              */
-            clock_clear_callback(ncl->clock);
             object_unref(OBJECT(ncl->clock));
         }
         g_free(ncl->name);
index eb58599131c7d50477808cf02127bb039b8904a5..a279bd4ba5e318e647dde64ae24fb119040966e9 100644 (file)
@@ -141,14 +141,6 @@ Clock *clock_new(Object *parent, const char *name);
 void clock_set_callback(Clock *clk, ClockCallback *cb,
                         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:
  * @clk: the clock.