qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: a quetion about sysbus_realize_and_unref function


From: Markus Armbruster
Subject: Re: a quetion about sysbus_realize_and_unref function
Date: Mon, 18 Oct 2021 19:07:33 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux)

Philippe Mathieu-Daudé <philmd@redhat.com> writes:

> Hi,
>
> On 10/18/21 14:01, Chan Kim wrote:
>> Hi, list members,
>> 
>> I see for example in hw/arm/virt.c, when it creates a device to attach
>> to a system bus, it calls “sysbus_realize_and_unref(SYS_BUS_DEVICE(dev),
>> &error_fatal);” function
>> 
>> .
>> 
>> static void create_its(VirtMachineState *vms)
>> 
>> {
>> 
>>     const char *itsclass = its_class_name();
>> 
>>     DeviceState *dev;
>> 
>>  
>> 
>>     if (!itsclass) {
>> 
>>         /* Do nothing if not supported */
>> 
>>         return;
>> 
>>     }
>> 
>>  
>> 
>>     dev = qdev_new(itsclass);
>> 
>>  
>> 
>>     object_property_set_link(OBJECT(dev), "parent-gicv3", OBJECT(vms->gic),
>> 
>>                              &error_abort);
>> 
>>     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
>> 
>>     sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_GIC_ITS].base);
>> 
>>  
>> 
>>     fdt_add_its_gic_node(vms);
>> 
>>     vms->msi_controller = VIRT_MSI_CTRL_ITS;
>> 
>> }
>> 
>> 
>> 
>> The document says it decrements the reference counter and when the ref
>> count is non zero, the object can’t be removed.
>> 
>> Then why does it call sysbus_realize_and_unref function to reduce the
>> ref count of the system bus(=parent object) of the device being create?
>
> The qemu-devel@nongnu.org is better for developer questions.

Yup.

When working with reference-counted objects, each increase ("ref") must
be paired with a decrease ("unref").  When the last "ref" is "unref'ed",
the object is destroyed.

In the code you quoted, qdev_new() is a "ref", and the matching "unref"
is sysbus_realize_and_unref(), which is a trivial wrapper around
qdev_realize_and_unref().  Its documentation in include/hw/qdev-core.h
explains how it manipulates reference counts.  Please study it, then
come back if you still have questions.

> Cc'ing Markus for:
>
> commit 496a8525622d4ac5d276f76840dd30eddb73672d
> Author: Markus Armbruster <armbru@redhat.com>
> Date:   Wed Jun 10 07:32:33 2020 +0200
>
>     sysbus: New sysbus_realize(), sysbus_realize_and_unref()
>
>     Sysbus devices almost always plug into the main system bus.
>     qdev_create() even has a convenience feature to make that easy:
>     a null bus argument gets replaced by the main system bus.
>     qdev_realize() and qdev_realize_and_unref() do the same.
>
>     We can do better.  Provide convenience wrappers around
>     qdev_realize() and qdev_realize_and_unref() that don't take a
>     @bus argument.  They always pass the main system bus.

This commit merely adds convenience wrappers and puts them to use.  The
argument for "and unref" is in the commit that adds the function being
wrapped:

commit 9940b2cfbc05cdffdf6b42227a80cb1e6d2a85c2
Author: Markus Armbruster <armbru@redhat.com>
Date:   Wed Jun 10 07:31:53 2020 +0200

    qdev: New qdev_new(), qdev_realize(), etc.
    
    We commonly plug devices into their bus right when we create them,
    like this:
    
        dev = qdev_create(bus, type_name);
    
    Note that @dev is a weak reference.  The reference from @bus to @dev
    is the only strong one.
    
    We realize at some later time, either with
    
        object_property_set_bool(OBJECT(dev), true, "realized", errp);
    
    or its convenience wrapper
    
        qdev_init_nofail(dev);
    
    If @dev still has no QOM parent then, realizing makes the
    /machine/unattached/ orphanage its QOM parent.
    
    Note that the device returned by qdev_create() is plugged into a bus,
    but doesn't have a QOM parent, yet.  Until it acquires one,
    unrealizing the bus will hang in bus_unparent():
    
        while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
            DeviceState *dev = kid->child;
            object_unparent(OBJECT(dev));
        }
    
    object_unparent() does nothing when its argument has no QOM parent,
    and the loop spins forever.
    
    Device state "no QOM parent, but plugged into bus" is dangerous.
    
    Paolo suggested to delay plugging into the bus until realize.  We need
    to plug into the parent bus before we call the device's realize
    method, in case it uses the parent bus.  So the dangerous state still
    exists, but only within realization, where we can manage it safely.
    
    This commit creates infrastructure to do this:
    
        dev = qdev_new(type_name);
        ...
        qdev_realize_and_unref(dev, bus, errp)
    
    Note that @dev becomes a strong reference here.
    qdev_realize_and_unref() drops it.  There is also plain
    qdev_realize(), which doesn't drop it.
    
    The remainder of this series will convert all users to this new
    interface.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]