qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] Issues around TYPE_INTERFACE


From: Markus Armbruster
Subject: Re: [Qemu-devel] Issues around TYPE_INTERFACE
Date: Wed, 03 Apr 2019 10:53:39 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.1 (gnu/linux)

I figure what I wrote was too long to read, so let me try again,
focusing on just the main issue, leaving the bonus messes for later.

Here's the main issue in a nutshell: (1) our interfaces can't have state
(but that's okay), (2) our conversions to interface types actually
convert to "an Object that has this interface" (and that's anything but
obvious).


Why (1) our interfaces can't have state:

Since interfaces are abstract, there's no such thing as an interface
instance.

Okay, but WTF does a conversion to an interface type *mean* then?
Recall, interface TYPE_MY_IFACE commonly defines struct type MyIface and
macro MY_IFACE(), which is a checked conversion from any instance of
Object to MyIface.  What *is* MyIface?


What (2) our conversions to interface types do:

MY_IFACE(obj) either fails its assertion or returns (MyIface *)obj.

When @obj points to an instance of MyFrob, then we can safely cast it to
any supertype of MyFrob.

MyIface is not a supertype of MyFrob, it's an interface.  WTF?

Turns out we only ever define MyIface in one of two ways:

    typedef struct MyIface MyIface;     // incomplete

    typedef struct MyIface {            // fake subtype of Object
        Object parent;
    } MyIface;

If we somehow know that only subtypes of SuperFrob have interface
MyIface, then we can exploit that and safely cast to SuperFrob * or any
of its supertypes.

If we don't (want to) know, then we can only cast to Object *.

The "fake subtype of Object" kind could save casts to Object *, but we
don't seem to use that.  Cargo cult?  Fear of not completing your types?

Regardless of how we cast or convert, we still know the object has
interface TYPE_MY_IFACE.


Example of how we actually use this: TYPE_MEMORY_DEVICE and unplug

pc_memory_unplug() converts DeviceState * to subtype PCDIMMDevice *,
checked.  Okay.

pc_dimm_unplug() converts PCDIMMDevice * to interface MemoryDeviceState
*.  Ooookay.  Note that MemoryDeviceState is incomplete.

memory_device_unplug() passes it on to its get_memory_region() method.
Since it's actually a PCDIMMDevice, this is
pc_dimm_md_get_memory_region().

pc_dimm_md_get_memory_region() converts the MemoryDeviceState * right
back to PCDIMMDevice *, checked.  This works even though
MemoryDeviceState is incomplete, because the checked conversion
PC_DIMM() accepts *any* pointer type.  It casts to Object * below the
hood, and if it isn't one, we get undefined behavior.



reply via email to

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