[Qemu-devel] [RFC v2 0/9] qom: Make object_get_class()/*_GET_CLASS return const pointers

Eduardo Habkost posted 9 patches 7 years ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20170329194148.19015-1-ehabkost@redhat.com
Test checkpatch failed
Test docker passed
Test s390x passed
configure                       | 20 +++++++++
include/qom/cpu.h               | 12 +++---
include/qom/object.h            | 94 ++++++++++++++++++++++++++++++++++-------
target/ppc/mmu-book3s-v3.h      |  2 +-
target/ppc/mmu-hash64.h         |  2 +-
target/s390x/cpu.h              |  2 +-
backends/cryptodev.c            | 10 ++---
backends/hostmem.c              |  2 +-
backends/rng.c                  |  4 +-
backends/tpm.c                  | 28 ++++++------
chardev/char-mux.c              |  2 +-
chardev/char.c                  | 10 ++---
cpu-exec.c                      | 14 +++---
device-hotplug.c                |  2 +-
disas.c                         |  4 +-
exec.c                          |  6 +--
gdbstub.c                       | 12 +++---
hmp.c                           |  4 +-
hw/acpi/acpi_interface.c        |  2 +-
hw/acpi/cpu.c                   |  8 ++--
hw/acpi/cpu_hotplug.c           |  4 +-
hw/acpi/ipmi.c                  |  2 +-
hw/acpi/memory_hotplug.c        |  2 +-
hw/acpi/nvdimm.c                |  4 +-
hw/acpi/pcihp.c                 |  4 +-
hw/arm/aspeed.c                 |  2 +-
hw/arm/aspeed_soc.c             |  4 +-
hw/arm/boot.c                   |  2 +-
hw/arm/exynos4_boards.c         |  2 +-
hw/arm/vexpress.c               |  2 +-
hw/arm/virt-acpi-build.c        |  6 +--
hw/arm/virt.c                   |  6 +--
hw/audio/cs4231a.c              | 10 ++---
hw/audio/gus.c                  |  6 +--
hw/audio/intel-hda.c            |  8 ++--
hw/audio/sb16.c                 |  6 +--
hw/block/dataplane/virtio-blk.c |  6 +--
hw/block/fdc.c                  |  8 ++--
hw/block/m25p80.c               |  2 +-
hw/char/serial-pci.c            |  2 +-
hw/char/virtio-console.c        |  6 +--
hw/char/virtio-serial-bus.c     | 18 ++++----
hw/core/bus.c                   |  4 +-
hw/core/fw-path-provider.c      |  2 +-
hw/core/generic-loader.c        |  2 +-
hw/core/hotplug.c               |  8 ++--
hw/core/loader.c                |  4 +-
hw/core/machine.c               |  5 +--
hw/core/nmi.c                   |  2 +-
hw/core/qdev-properties.c       |  4 +-
hw/core/qdev.c                  | 32 +++++++-------
hw/core/stream.c                |  4 +-
hw/core/sysbus.c                |  6 +--
hw/display/cirrus_vga.c         |  2 +-
hw/i2c/core.c                   | 10 ++---
hw/i2c/smbus.c                  |  8 ++--
hw/i386/acpi-build.c            | 16 +++----
hw/i386/kvm/i8254.c             |  2 +-
hw/i386/kvm/i8259.c             |  2 +-
hw/i386/pc.c                    | 32 +++++++-------
hw/i386/pc_piix.c               |  4 +-
hw/i386/pc_q35.c                |  4 +-
hw/i386/x86-iommu.c             |  2 +-
hw/ide/microdrive.c             |  4 +-
hw/ide/qdev.c                   |  2 +-
hw/input/adb.c                  |  6 +--
hw/input/virtio-input.c         | 12 +++---
hw/intc/apic_common.c           | 26 ++++++------
hw/intc/arm_gic.c               |  2 +-
hw/intc/arm_gic_common.c        |  4 +-
hw/intc/arm_gic_kvm.c           |  4 +-
hw/intc/arm_gicv3.c             |  2 +-
hw/intc/arm_gicv3_common.c      |  4 +-
hw/intc/arm_gicv3_its_common.c  |  6 +--
hw/intc/arm_gicv3_kvm.c         |  4 +-
hw/intc/i8259.c                 |  2 +-
hw/intc/i8259_common.c          |  4 +-
hw/intc/ioapic_common.c         |  6 +--
hw/intc/xics.c                  | 26 ++++++------
hw/ipack/ipack.c                |  4 +-
hw/ipack/tpci200.c              | 12 +++---
hw/ipmi/ipmi_bmc_extern.c       | 12 +++---
hw/ipmi/ipmi_bmc_sim.c          | 24 +++++------
hw/ipmi/isa_ipmi_bt.c           | 22 +++++-----
hw/ipmi/isa_ipmi_kcs.c          | 20 ++++-----
hw/mem/pc-dimm.c                | 10 ++---
hw/mips/mips_jazz.c             |  2 +-
hw/misc/imx_ccm.c               |  2 +-
hw/net/e1000.c                  |  2 +-
hw/net/vhost_net.c              |  4 +-
hw/net/vmxnet3.c                |  2 +-
hw/nvram/fw_cfg.c               |  2 +-
hw/pci-bridge/pcie_root_port.c  |  8 ++--
hw/pci/pci.c                    | 17 ++++----
hw/pcmcia/pxa2xx.c              | 16 +++----
hw/ppc/pnv.c                    | 14 +++---
hw/ppc/pnv_core.c               |  2 +-
hw/ppc/pnv_xscom.c              |  6 +--
hw/ppc/prep.c                   |  8 ++--
hw/ppc/spapr.c                  | 50 +++++++++++-----------
hw/ppc/spapr_cpu_core.c         |  4 +-
hw/ppc/spapr_drc.c              | 20 ++++-----
hw/ppc/spapr_events.c           |  6 +--
hw/ppc/spapr_hcall.c            |  2 +-
hw/ppc/spapr_pci.c              | 14 +++---
hw/ppc/spapr_rtas.c             |  8 ++--
hw/ppc/spapr_vio.c              | 12 +++---
hw/s390x/css-bridge.c           |  2 +-
hw/s390x/css.c                  |  6 +--
hw/s390x/event-facility.c       | 14 +++---
hw/s390x/s390-skeys-kvm.c       |  2 +-
hw/s390x/s390-skeys.c           |  8 ++--
hw/s390x/s390-virtio-ccw.c      |  8 ++--
hw/s390x/sclp.c                 | 10 ++---
hw/s390x/virtio-ccw.c           | 12 +++---
hw/scsi/megasas.c               |  8 ++--
hw/scsi/mptconfig.c             |  6 +--
hw/scsi/scsi-bus.c              |  8 ++--
hw/scsi/vhost-scsi.c            |  4 +-
hw/scsi/virtio-scsi-dataplane.c |  6 +--
hw/scsi/vmw_pvscsi.c            |  2 +-
hw/sd/core.c                    | 18 ++++----
hw/sh4/sh7750.c                 |  2 +-
hw/smbios/smbios_type_38.c      |  2 +-
hw/sparc/sun4m.c                |  2 +-
hw/sparc64/sun4u.c              |  2 +-
hw/ssi/aspeed_smc.c             |  2 +-
hw/ssi/ssi.c                    |  8 ++--
hw/ssi/xilinx_spips.c           |  2 +-
hw/timer/i8254.c                |  2 +-
hw/timer/i8254_common.c         | 10 ++---
hw/timer/m48t59-isa.c           |  2 +-
hw/timer/m48t59.c               |  2 +-
hw/usb/bus.c                    | 32 +++++++-------
hw/usb/dev-smartcard-reader.c   |  8 ++--
hw/usb/hcd-ehci-pci.c           |  2 +-
hw/usb/hcd-ehci-sysbus.c        |  2 +-
hw/usb/hcd-uhci.c               |  2 +-
hw/vfio/amd-xgbe.c              |  2 +-
hw/vfio/calxeda-xgmac.c         |  2 +-
hw/virtio/vhost-vsock.c         |  4 +-
hw/virtio/vhost.c               |  2 +-
hw/virtio/virtio-bus.c          | 24 +++++------
hw/virtio/virtio-mmio.c         |  2 +-
hw/virtio/virtio-pci.c          | 20 ++++-----
hw/virtio/virtio.c              | 62 +++++++++++++--------------
hw/xen/xen_backend.c            |  3 +-
io/channel.c                    | 20 ++++-----
kvm-all.c                       |  2 +-
migration/migration.c           |  2 +-
migration/savevm.c              |  2 +-
monitor.c                       |  2 +-
net/filter.c                    |  6 +--
qdev-monitor.c                  | 12 +++---
qmp.c                           |  4 +-
qom/cpu.c                       | 26 ++++++------
qom/object.c                    | 31 +++++++-------
qom/object_interfaces.c         |  4 +-
target/alpha/cpu.c              |  2 +-
target/arm/cpu.c                |  8 ++--
target/arm/kvm.c                |  2 +-
target/cris/cpu.c               | 10 ++---
target/cris/helper.c            |  2 +-
target/hppa/cpu.c               |  2 +-
target/i386/cpu.c               | 10 ++---
target/i386/kvm.c               |  2 +-
target/i386/machine.c           |  3 +-
target/lm32/cpu.c               |  4 +-
target/lm32/gdbstub.c           |  2 +-
target/m68k/cpu.c               |  4 +-
target/microblaze/cpu.c         |  4 +-
target/microblaze/gdbstub.c     |  2 +-
target/mips/cpu.c               |  4 +-
target/moxie/cpu.c              |  4 +-
target/nios2/cpu.c              |  8 ++--
target/openrisc/cpu.c           |  4 +-
target/openrisc/gdbstub.c       |  2 +-
target/ppc/arch_dump.c          |  2 +-
target/ppc/compat.c             |  4 +-
target/ppc/excp_helper.c        |  2 +-
target/ppc/mmu-hash64.c         |  6 +--
target/ppc/mmu_helper.c         |  2 +-
target/ppc/translate_init.c     | 14 +++---
target/s390x/cpu.c              |  6 +--
target/s390x/cpu_models.c       |  4 +-
target/s390x/kvm.c              |  4 +-
target/s390x/mem_helper.c       |  6 +--
target/s390x/misc_helper.c      |  6 +--
target/s390x/mmu_helper.c       |  2 +-
target/sh4/cpu.c                |  4 +-
target/sparc/cpu.c              |  4 +-
target/tilegx/cpu.c             |  4 +-
target/tricore/cpu.c            |  4 +-
target/unicore32/cpu.c          |  2 +-
target/xtensa/cpu.c             |  6 +--
tests/check-qom-interface.c     |  2 +-
user-exec.c                     |  2 +-
vl.c                            |  2 +-
198 files changed, 800 insertions(+), 721 deletions(-)
[Qemu-devel] [RFC v2 0/9] qom: Make object_get_class()/*_GET_CLASS return const pointers
Posted by Eduardo Habkost 7 years ago
The problem
-----------

QOM has a data model where class struct data is static: class
structs are initialized at class_init, and never changed again.

...except for a few rare cases where class data is changed
outside class_init. Those cases are:

  qbus_realize(), code added by:
  commit 61de36761b565a4138d8ad7ec75489ab28fe84b6
  Date:   Thu Feb 6 16:08:15 2014 +0100
      qdev: Keep global allocation counter per bus

  mips_jazz_init(), code added by:
  commit 54e755588cf1e90f0b1460c4e8e6b6a54b6d3a32
  Date:   Mon Nov 4 23:26:17 2013 +0100
      mips jazz: do not raise data bus exception when accessing invalid addresses

  xen_set_dynamic_sysbus(), code added by:
  commit 3a6c9172ac5951e6dac2b3f6cbce3cfccdec5894
  Date:   Tue Nov 22 07:10:58 2016 +0100
      xen: create qdev for each backend device

  s390_cpu_realizefn(), code added by:
  commit c6644fc88bed1176f67b4b7a9df691bcf25c0c5b
  Date:   Fri Mar 4 12:34:31 2016 -0500
      s390x/cpu: Get rid of side effects when creating a vcpu

I want to prevent that from happening again.

Proposal
--------

I propose we make object_get_class() and *_GET_CLASS macros
return const pointers. This way, anybody willing to change class
structs outside class_init will (hopefully) be aware that they
are doing something unexpected.

This would be very simple and trivial, except that:
* OBJECT_CLASS_CHECK cast its return value to a different
  (non-const) pointer type.
* OBJECT_CLASS_CHECK-based macros are used everywhere to
  cast class pointers to different class types.

I have addressed this problem using C11's _Generic keyword.
_Generic allows us to make OBJECT_CLASS_CHECK and other macros
return a const pointer if its argument is a const pointer, and a
non-const pointer otherwise.

This series changes OBJECT_CLASS, OBJECT_CLASS_CHECK,
object_class_dynamic_cast_assert(), object_class_dynamic_cast(),
and object_class_get_parent() to exhibit this const-aware
behavior.

If the compiler doesn't support _Generic, we keep the old
behavior, and the cast macros will keep returning non-const
pointers.

---
Cc: Alexander Graf <agraf@suse.de>
Cc: Hervé Poussineau <hpoussin@reactos.org>
Cc: Juergen Gross <jgross@suse.com>
Cc: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Andreas Färber <afaerber@suse.de>

Eduardo Habkost (9):
  configure: test if _Generic works as expected
  Simplify code using *MACHINE_GET_CLASS
  qom: QUALIFIED_CAST helper macro
  qom: Make object_class_get_parent() const-aware
  Make class parameter const at some functions
  Explicitly cast the *_GET_CLASS() value when we break the rules
  Use const variables for *_GET_CLASS values
  qom: Make class cast macros/functions const-aware
  qom: Make object_get_class() return const pointer

 configure                       | 20 +++++++++
 include/qom/cpu.h               | 12 +++---
 include/qom/object.h            | 94 ++++++++++++++++++++++++++++++++++-------
 target/ppc/mmu-book3s-v3.h      |  2 +-
 target/ppc/mmu-hash64.h         |  2 +-
 target/s390x/cpu.h              |  2 +-
 backends/cryptodev.c            | 10 ++---
 backends/hostmem.c              |  2 +-
 backends/rng.c                  |  4 +-
 backends/tpm.c                  | 28 ++++++------
 chardev/char-mux.c              |  2 +-
 chardev/char.c                  | 10 ++---
 cpu-exec.c                      | 14 +++---
 device-hotplug.c                |  2 +-
 disas.c                         |  4 +-
 exec.c                          |  6 +--
 gdbstub.c                       | 12 +++---
 hmp.c                           |  4 +-
 hw/acpi/acpi_interface.c        |  2 +-
 hw/acpi/cpu.c                   |  8 ++--
 hw/acpi/cpu_hotplug.c           |  4 +-
 hw/acpi/ipmi.c                  |  2 +-
 hw/acpi/memory_hotplug.c        |  2 +-
 hw/acpi/nvdimm.c                |  4 +-
 hw/acpi/pcihp.c                 |  4 +-
 hw/arm/aspeed.c                 |  2 +-
 hw/arm/aspeed_soc.c             |  4 +-
 hw/arm/boot.c                   |  2 +-
 hw/arm/exynos4_boards.c         |  2 +-
 hw/arm/vexpress.c               |  2 +-
 hw/arm/virt-acpi-build.c        |  6 +--
 hw/arm/virt.c                   |  6 +--
 hw/audio/cs4231a.c              | 10 ++---
 hw/audio/gus.c                  |  6 +--
 hw/audio/intel-hda.c            |  8 ++--
 hw/audio/sb16.c                 |  6 +--
 hw/block/dataplane/virtio-blk.c |  6 +--
 hw/block/fdc.c                  |  8 ++--
 hw/block/m25p80.c               |  2 +-
 hw/char/serial-pci.c            |  2 +-
 hw/char/virtio-console.c        |  6 +--
 hw/char/virtio-serial-bus.c     | 18 ++++----
 hw/core/bus.c                   |  4 +-
 hw/core/fw-path-provider.c      |  2 +-
 hw/core/generic-loader.c        |  2 +-
 hw/core/hotplug.c               |  8 ++--
 hw/core/loader.c                |  4 +-
 hw/core/machine.c               |  5 +--
 hw/core/nmi.c                   |  2 +-
 hw/core/qdev-properties.c       |  4 +-
 hw/core/qdev.c                  | 32 +++++++-------
 hw/core/stream.c                |  4 +-
 hw/core/sysbus.c                |  6 +--
 hw/display/cirrus_vga.c         |  2 +-
 hw/i2c/core.c                   | 10 ++---
 hw/i2c/smbus.c                  |  8 ++--
 hw/i386/acpi-build.c            | 16 +++----
 hw/i386/kvm/i8254.c             |  2 +-
 hw/i386/kvm/i8259.c             |  2 +-
 hw/i386/pc.c                    | 32 +++++++-------
 hw/i386/pc_piix.c               |  4 +-
 hw/i386/pc_q35.c                |  4 +-
 hw/i386/x86-iommu.c             |  2 +-
 hw/ide/microdrive.c             |  4 +-
 hw/ide/qdev.c                   |  2 +-
 hw/input/adb.c                  |  6 +--
 hw/input/virtio-input.c         | 12 +++---
 hw/intc/apic_common.c           | 26 ++++++------
 hw/intc/arm_gic.c               |  2 +-
 hw/intc/arm_gic_common.c        |  4 +-
 hw/intc/arm_gic_kvm.c           |  4 +-
 hw/intc/arm_gicv3.c             |  2 +-
 hw/intc/arm_gicv3_common.c      |  4 +-
 hw/intc/arm_gicv3_its_common.c  |  6 +--
 hw/intc/arm_gicv3_kvm.c         |  4 +-
 hw/intc/i8259.c                 |  2 +-
 hw/intc/i8259_common.c          |  4 +-
 hw/intc/ioapic_common.c         |  6 +--
 hw/intc/xics.c                  | 26 ++++++------
 hw/ipack/ipack.c                |  4 +-
 hw/ipack/tpci200.c              | 12 +++---
 hw/ipmi/ipmi_bmc_extern.c       | 12 +++---
 hw/ipmi/ipmi_bmc_sim.c          | 24 +++++------
 hw/ipmi/isa_ipmi_bt.c           | 22 +++++-----
 hw/ipmi/isa_ipmi_kcs.c          | 20 ++++-----
 hw/mem/pc-dimm.c                | 10 ++---
 hw/mips/mips_jazz.c             |  2 +-
 hw/misc/imx_ccm.c               |  2 +-
 hw/net/e1000.c                  |  2 +-
 hw/net/vhost_net.c              |  4 +-
 hw/net/vmxnet3.c                |  2 +-
 hw/nvram/fw_cfg.c               |  2 +-
 hw/pci-bridge/pcie_root_port.c  |  8 ++--
 hw/pci/pci.c                    | 17 ++++----
 hw/pcmcia/pxa2xx.c              | 16 +++----
 hw/ppc/pnv.c                    | 14 +++---
 hw/ppc/pnv_core.c               |  2 +-
 hw/ppc/pnv_xscom.c              |  6 +--
 hw/ppc/prep.c                   |  8 ++--
 hw/ppc/spapr.c                  | 50 +++++++++++-----------
 hw/ppc/spapr_cpu_core.c         |  4 +-
 hw/ppc/spapr_drc.c              | 20 ++++-----
 hw/ppc/spapr_events.c           |  6 +--
 hw/ppc/spapr_hcall.c            |  2 +-
 hw/ppc/spapr_pci.c              | 14 +++---
 hw/ppc/spapr_rtas.c             |  8 ++--
 hw/ppc/spapr_vio.c              | 12 +++---
 hw/s390x/css-bridge.c           |  2 +-
 hw/s390x/css.c                  |  6 +--
 hw/s390x/event-facility.c       | 14 +++---
 hw/s390x/s390-skeys-kvm.c       |  2 +-
 hw/s390x/s390-skeys.c           |  8 ++--
 hw/s390x/s390-virtio-ccw.c      |  8 ++--
 hw/s390x/sclp.c                 | 10 ++---
 hw/s390x/virtio-ccw.c           | 12 +++---
 hw/scsi/megasas.c               |  8 ++--
 hw/scsi/mptconfig.c             |  6 +--
 hw/scsi/scsi-bus.c              |  8 ++--
 hw/scsi/vhost-scsi.c            |  4 +-
 hw/scsi/virtio-scsi-dataplane.c |  6 +--
 hw/scsi/vmw_pvscsi.c            |  2 +-
 hw/sd/core.c                    | 18 ++++----
 hw/sh4/sh7750.c                 |  2 +-
 hw/smbios/smbios_type_38.c      |  2 +-
 hw/sparc/sun4m.c                |  2 +-
 hw/sparc64/sun4u.c              |  2 +-
 hw/ssi/aspeed_smc.c             |  2 +-
 hw/ssi/ssi.c                    |  8 ++--
 hw/ssi/xilinx_spips.c           |  2 +-
 hw/timer/i8254.c                |  2 +-
 hw/timer/i8254_common.c         | 10 ++---
 hw/timer/m48t59-isa.c           |  2 +-
 hw/timer/m48t59.c               |  2 +-
 hw/usb/bus.c                    | 32 +++++++-------
 hw/usb/dev-smartcard-reader.c   |  8 ++--
 hw/usb/hcd-ehci-pci.c           |  2 +-
 hw/usb/hcd-ehci-sysbus.c        |  2 +-
 hw/usb/hcd-uhci.c               |  2 +-
 hw/vfio/amd-xgbe.c              |  2 +-
 hw/vfio/calxeda-xgmac.c         |  2 +-
 hw/virtio/vhost-vsock.c         |  4 +-
 hw/virtio/vhost.c               |  2 +-
 hw/virtio/virtio-bus.c          | 24 +++++------
 hw/virtio/virtio-mmio.c         |  2 +-
 hw/virtio/virtio-pci.c          | 20 ++++-----
 hw/virtio/virtio.c              | 62 +++++++++++++--------------
 hw/xen/xen_backend.c            |  3 +-
 io/channel.c                    | 20 ++++-----
 kvm-all.c                       |  2 +-
 migration/migration.c           |  2 +-
 migration/savevm.c              |  2 +-
 monitor.c                       |  2 +-
 net/filter.c                    |  6 +--
 qdev-monitor.c                  | 12 +++---
 qmp.c                           |  4 +-
 qom/cpu.c                       | 26 ++++++------
 qom/object.c                    | 31 +++++++-------
 qom/object_interfaces.c         |  4 +-
 target/alpha/cpu.c              |  2 +-
 target/arm/cpu.c                |  8 ++--
 target/arm/kvm.c                |  2 +-
 target/cris/cpu.c               | 10 ++---
 target/cris/helper.c            |  2 +-
 target/hppa/cpu.c               |  2 +-
 target/i386/cpu.c               | 10 ++---
 target/i386/kvm.c               |  2 +-
 target/i386/machine.c           |  3 +-
 target/lm32/cpu.c               |  4 +-
 target/lm32/gdbstub.c           |  2 +-
 target/m68k/cpu.c               |  4 +-
 target/microblaze/cpu.c         |  4 +-
 target/microblaze/gdbstub.c     |  2 +-
 target/mips/cpu.c               |  4 +-
 target/moxie/cpu.c              |  4 +-
 target/nios2/cpu.c              |  8 ++--
 target/openrisc/cpu.c           |  4 +-
 target/openrisc/gdbstub.c       |  2 +-
 target/ppc/arch_dump.c          |  2 +-
 target/ppc/compat.c             |  4 +-
 target/ppc/excp_helper.c        |  2 +-
 target/ppc/mmu-hash64.c         |  6 +--
 target/ppc/mmu_helper.c         |  2 +-
 target/ppc/translate_init.c     | 14 +++---
 target/s390x/cpu.c              |  6 +--
 target/s390x/cpu_models.c       |  4 +-
 target/s390x/kvm.c              |  4 +-
 target/s390x/mem_helper.c       |  6 +--
 target/s390x/misc_helper.c      |  6 +--
 target/s390x/mmu_helper.c       |  2 +-
 target/sh4/cpu.c                |  4 +-
 target/sparc/cpu.c              |  4 +-
 target/tilegx/cpu.c             |  4 +-
 target/tricore/cpu.c            |  4 +-
 target/unicore32/cpu.c          |  2 +-
 target/xtensa/cpu.c             |  6 +--
 tests/check-qom-interface.c     |  2 +-
 user-exec.c                     |  2 +-
 vl.c                            |  2 +-
 198 files changed, 800 insertions(+), 721 deletions(-)

-- 
2.11.0.259.g40922b1


Re: [Qemu-devel] [RFC v2 0/9] qom: Make object_get_class()/*_GET_CLASS return const pointers
Posted by Laszlo Ersek 7 years ago
On 03/29/17 21:41, Eduardo Habkost wrote:
> The problem
> -----------
> 
> QOM has a data model where class struct data is static: class
> structs are initialized at class_init, and never changed again.
> 
> ...except for a few rare cases where class data is changed
> outside class_init. Those cases are:
> 
>   qbus_realize(), code added by:
>   commit 61de36761b565a4138d8ad7ec75489ab28fe84b6
>   Date:   Thu Feb 6 16:08:15 2014 +0100
>       qdev: Keep global allocation counter per bus
> 
>   mips_jazz_init(), code added by:
>   commit 54e755588cf1e90f0b1460c4e8e6b6a54b6d3a32
>   Date:   Mon Nov 4 23:26:17 2013 +0100
>       mips jazz: do not raise data bus exception when accessing invalid addresses
> 
>   xen_set_dynamic_sysbus(), code added by:
>   commit 3a6c9172ac5951e6dac2b3f6cbce3cfccdec5894
>   Date:   Tue Nov 22 07:10:58 2016 +0100
>       xen: create qdev for each backend device
> 
>   s390_cpu_realizefn(), code added by:
>   commit c6644fc88bed1176f67b4b7a9df691bcf25c0c5b
>   Date:   Fri Mar 4 12:34:31 2016 -0500
>       s390x/cpu: Get rid of side effects when creating a vcpu
> 
> I want to prevent that from happening again.
> 
> Proposal
> --------
> 
> I propose we make object_get_class() and *_GET_CLASS macros
> return const pointers. This way, anybody willing to change class
> structs outside class_init will (hopefully) be aware that they
> are doing something unexpected.
> 
> This would be very simple and trivial, except that:
> * OBJECT_CLASS_CHECK cast its return value to a different
>   (non-const) pointer type.
> * OBJECT_CLASS_CHECK-based macros are used everywhere to
>   cast class pointers to different class types.
> 
> I have addressed this problem using C11's _Generic keyword.
> _Generic allows us to make OBJECT_CLASS_CHECK and other macros
> return a const pointer if its argument is a const pointer, and a
> non-const pointer otherwise.
> 
> This series changes OBJECT_CLASS, OBJECT_CLASS_CHECK,
> object_class_dynamic_cast_assert(), object_class_dynamic_cast(),
> and object_class_get_parent() to exhibit this const-aware
> behavior.
> 
> If the compiler doesn't support _Generic, we keep the old
> behavior, and the cast macros will keep returning non-const
> pointers.
> 
> ---
> Cc: Alexander Graf <agraf@suse.de>
> Cc: Hervé Poussineau <hpoussin@reactos.org>
> Cc: Juergen Gross <jgross@suse.com>
> Cc: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
> Cc: Igor Mammedov <imammedo@redhat.com>
> Cc: Andreas Färber <afaerber@suse.de>
> 
> Eduardo Habkost (9):
>   configure: test if _Generic works as expected
>   Simplify code using *MACHINE_GET_CLASS
>   qom: QUALIFIED_CAST helper macro
>   qom: Make object_class_get_parent() const-aware
>   Make class parameter const at some functions
>   Explicitly cast the *_GET_CLASS() value when we break the rules
>   Use const variables for *_GET_CLASS values
>   qom: Make class cast macros/functions const-aware
>   qom: Make object_get_class() return const pointer

Only superficial comments:

(1) HACKING has some notes on C99 and C11 usage; I think you should
update them as well.

(2) Can you CC the maintainers of the code being modified on each patch?

(3) (Corollary of the former -- I'm not seeing patch 7 yet, which I
assume is the big one, from the cumulative diffstat) -- is it possible
to split up patch 7 more fine-grained? To help reviewers. (I don't
maintain anything in QEMU, so this is just a generic suggestion;
everyone feel free to disagree.)

Thanks
Laszlo


Re: [Qemu-devel] [RFC v2 0/9] qom: Make object_get_class()/*_GET_CLASS return const pointers
Posted by Eduardo Habkost 7 years ago
On Wed, Mar 29, 2017 at 09:56:54PM +0200, Laszlo Ersek wrote:
> On 03/29/17 21:41, Eduardo Habkost wrote:
> > The problem
> > -----------
> > 
> > QOM has a data model where class struct data is static: class
> > structs are initialized at class_init, and never changed again.
> > 
> > ...except for a few rare cases where class data is changed
> > outside class_init. Those cases are:
> > 
> >   qbus_realize(), code added by:
> >   commit 61de36761b565a4138d8ad7ec75489ab28fe84b6
> >   Date:   Thu Feb 6 16:08:15 2014 +0100
> >       qdev: Keep global allocation counter per bus
> > 
> >   mips_jazz_init(), code added by:
> >   commit 54e755588cf1e90f0b1460c4e8e6b6a54b6d3a32
> >   Date:   Mon Nov 4 23:26:17 2013 +0100
> >       mips jazz: do not raise data bus exception when accessing invalid addresses
> > 
> >   xen_set_dynamic_sysbus(), code added by:
> >   commit 3a6c9172ac5951e6dac2b3f6cbce3cfccdec5894
> >   Date:   Tue Nov 22 07:10:58 2016 +0100
> >       xen: create qdev for each backend device
> > 
> >   s390_cpu_realizefn(), code added by:
> >   commit c6644fc88bed1176f67b4b7a9df691bcf25c0c5b
> >   Date:   Fri Mar 4 12:34:31 2016 -0500
> >       s390x/cpu: Get rid of side effects when creating a vcpu
> > 
> > I want to prevent that from happening again.
> > 
> > Proposal
> > --------
> > 
> > I propose we make object_get_class() and *_GET_CLASS macros
> > return const pointers. This way, anybody willing to change class
> > structs outside class_init will (hopefully) be aware that they
> > are doing something unexpected.
> > 
> > This would be very simple and trivial, except that:
> > * OBJECT_CLASS_CHECK cast its return value to a different
> >   (non-const) pointer type.
> > * OBJECT_CLASS_CHECK-based macros are used everywhere to
> >   cast class pointers to different class types.
> > 
> > I have addressed this problem using C11's _Generic keyword.
> > _Generic allows us to make OBJECT_CLASS_CHECK and other macros
> > return a const pointer if its argument is a const pointer, and a
> > non-const pointer otherwise.
> > 
> > This series changes OBJECT_CLASS, OBJECT_CLASS_CHECK,
> > object_class_dynamic_cast_assert(), object_class_dynamic_cast(),
> > and object_class_get_parent() to exhibit this const-aware
> > behavior.
> > 
> > If the compiler doesn't support _Generic, we keep the old
> > behavior, and the cast macros will keep returning non-const
> > pointers.
> > 
> > ---
> > Cc: Alexander Graf <agraf@suse.de>
> > Cc: Hervé Poussineau <hpoussin@reactos.org>
> > Cc: Juergen Gross <jgross@suse.com>
> > Cc: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Paolo Bonzini <pbonzini@redhat.com>
> > Cc: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
> > Cc: Igor Mammedov <imammedo@redhat.com>
> > Cc: Andreas Färber <afaerber@suse.de>
> > 
> > Eduardo Habkost (9):
> >   configure: test if _Generic works as expected
> >   Simplify code using *MACHINE_GET_CLASS
> >   qom: QUALIFIED_CAST helper macro
> >   qom: Make object_class_get_parent() const-aware
> >   Make class parameter const at some functions
> >   Explicitly cast the *_GET_CLASS() value when we break the rules
> >   Use const variables for *_GET_CLASS values
> >   qom: Make class cast macros/functions const-aware
> >   qom: Make object_get_class() return const pointer
> 
> Only superficial comments:
> 
> (1) HACKING has some notes on C99 and C11 usage; I think you should
> update them as well.

I will take a look, thanks!

> 
> (2) Can you CC the maintainers of the code being modified on each patch?

I can, on the shorter ones, but this will be difficult on patch
7, which is composed mostly of mechanical changes generated using
Coccinelle. I didn't want to generate a huge CC list just because
of those mechanical changes.

> 
> (3) (Corollary of the former -- I'm not seeing patch 7 yet, which I
> assume is the big one, from the cumulative diffstat) -- is it possible
> to split up patch 7 more fine-grained? To help reviewers. (I don't
> maintain anything in QEMU, so this is just a generic suggestion;
> everyone feel free to disagree.)

The coccinelle-generated parts of patch 7 will be hard to split,
but I can try to split the rest of the changes later.

I tried to keep the patch count smaller on purpose on the RFC,
because first I want to hear what people think of this proposal.
If people like it, I will split a few patches, especially:

* [RFC v2 2/9] Simplify code using *MACHINE_GET_CLASS
  (split the pc, machine core, and pci changes into separate patches)
* [RFC v2 5/9] Make class parameter const at some functions
  (split into one patch for each subsystem being changed)
* [RFC v2 6/9] Explicitly cast the *_GET_CLASS() value when we break the rules
  (not sure if I I will split it, but I will surely CC the
  maintainers for each subsystem)
* [RFC v2 7/9] Use const variables for *_GET_CLASS values
  (probably I will separate the coccinelle-generated changes from the others,
  and split the manual changes per subsystem)

-- 
Eduardo

Re: [Qemu-devel] [RFC v2 0/9] qom: Make object_get_class()/*_GET_CLASS return const pointers
Posted by Eduardo Habkost 7 years ago
On Wed, Mar 29, 2017 at 04:41:39PM -0300, Eduardo Habkost wrote:
[...]
> Eduardo Habkost (9):
>   configure: test if _Generic works as expected
>   Simplify code using *MACHINE_GET_CLASS
>   qom: QUALIFIED_CAST helper macro
>   qom: Make object_class_get_parent() const-aware
>   Make class parameter const at some functions
>   Explicitly cast the *_GET_CLASS() value when we break the rules
>   Use const variables for *_GET_CLASS values

In case patch 7/9 never gets delivered to the list because of its
size, below is the commit message, containing a Coccinelle
script.

Git tree is available at:
  git://github.com/ehabkost/qemu-hacks.git work/const-classes


"""
Use const variables for the return value of *_GET_CLASS and
object_get_class(). This will allow us to make *_GET_CLASS and
object_get_class() return const pointers later.

Most of the changes were generated using the following Coccinelle
script, but some additional cases had to be udpated by hand after
running the script.

  @@
  type XClass;
  identifier oc;
  identifier X_GET_CLASS =~ ".*_GET_CLASS|object_get_class";
  @@
  -XClass *oc;
  +const XClass *oc;
   <+...
   oc = X_GET_CLASS(...);
   ...+>

  @@
  type XClass;
  identifier oc;
  identifier X_GET_CLASS =~ ".*_GET_CLASS|object_get_class";
  @@
  +const
   XClass *oc = X_GET_CLASS(...);
"""

>   qom: Make class cast macros/functions const-aware
>   qom: Make object_get_class() return const pointer
> 
>  configure                       | 20 +++++++++
>  include/qom/cpu.h               | 12 +++---
>  include/qom/object.h            | 94 ++++++++++++++++++++++++++++++++++-------
>  target/ppc/mmu-book3s-v3.h      |  2 +-
>  target/ppc/mmu-hash64.h         |  2 +-
>  target/s390x/cpu.h              |  2 +-
>  backends/cryptodev.c            | 10 ++---
>  backends/hostmem.c              |  2 +-
>  backends/rng.c                  |  4 +-
>  backends/tpm.c                  | 28 ++++++------
>  chardev/char-mux.c              |  2 +-
>  chardev/char.c                  | 10 ++---
>  cpu-exec.c                      | 14 +++---
>  device-hotplug.c                |  2 +-
>  disas.c                         |  4 +-
>  exec.c                          |  6 +--
>  gdbstub.c                       | 12 +++---
>  hmp.c                           |  4 +-
>  hw/acpi/acpi_interface.c        |  2 +-
>  hw/acpi/cpu.c                   |  8 ++--
>  hw/acpi/cpu_hotplug.c           |  4 +-
>  hw/acpi/ipmi.c                  |  2 +-
>  hw/acpi/memory_hotplug.c        |  2 +-
>  hw/acpi/nvdimm.c                |  4 +-
>  hw/acpi/pcihp.c                 |  4 +-
>  hw/arm/aspeed.c                 |  2 +-
>  hw/arm/aspeed_soc.c             |  4 +-
>  hw/arm/boot.c                   |  2 +-
>  hw/arm/exynos4_boards.c         |  2 +-
>  hw/arm/vexpress.c               |  2 +-
>  hw/arm/virt-acpi-build.c        |  6 +--
>  hw/arm/virt.c                   |  6 +--
>  hw/audio/cs4231a.c              | 10 ++---
>  hw/audio/gus.c                  |  6 +--
>  hw/audio/intel-hda.c            |  8 ++--
>  hw/audio/sb16.c                 |  6 +--
>  hw/block/dataplane/virtio-blk.c |  6 +--
>  hw/block/fdc.c                  |  8 ++--
>  hw/block/m25p80.c               |  2 +-
>  hw/char/serial-pci.c            |  2 +-
>  hw/char/virtio-console.c        |  6 +--
>  hw/char/virtio-serial-bus.c     | 18 ++++----
>  hw/core/bus.c                   |  4 +-
>  hw/core/fw-path-provider.c      |  2 +-
>  hw/core/generic-loader.c        |  2 +-
>  hw/core/hotplug.c               |  8 ++--
>  hw/core/loader.c                |  4 +-
>  hw/core/machine.c               |  5 +--
>  hw/core/nmi.c                   |  2 +-
>  hw/core/qdev-properties.c       |  4 +-
>  hw/core/qdev.c                  | 32 +++++++-------
>  hw/core/stream.c                |  4 +-
>  hw/core/sysbus.c                |  6 +--
>  hw/display/cirrus_vga.c         |  2 +-
>  hw/i2c/core.c                   | 10 ++---
>  hw/i2c/smbus.c                  |  8 ++--
>  hw/i386/acpi-build.c            | 16 +++----
>  hw/i386/kvm/i8254.c             |  2 +-
>  hw/i386/kvm/i8259.c             |  2 +-
>  hw/i386/pc.c                    | 32 +++++++-------
>  hw/i386/pc_piix.c               |  4 +-
>  hw/i386/pc_q35.c                |  4 +-
>  hw/i386/x86-iommu.c             |  2 +-
>  hw/ide/microdrive.c             |  4 +-
>  hw/ide/qdev.c                   |  2 +-
>  hw/input/adb.c                  |  6 +--
>  hw/input/virtio-input.c         | 12 +++---
>  hw/intc/apic_common.c           | 26 ++++++------
>  hw/intc/arm_gic.c               |  2 +-
>  hw/intc/arm_gic_common.c        |  4 +-
>  hw/intc/arm_gic_kvm.c           |  4 +-
>  hw/intc/arm_gicv3.c             |  2 +-
>  hw/intc/arm_gicv3_common.c      |  4 +-
>  hw/intc/arm_gicv3_its_common.c  |  6 +--
>  hw/intc/arm_gicv3_kvm.c         |  4 +-
>  hw/intc/i8259.c                 |  2 +-
>  hw/intc/i8259_common.c          |  4 +-
>  hw/intc/ioapic_common.c         |  6 +--
>  hw/intc/xics.c                  | 26 ++++++------
>  hw/ipack/ipack.c                |  4 +-
>  hw/ipack/tpci200.c              | 12 +++---
>  hw/ipmi/ipmi_bmc_extern.c       | 12 +++---
>  hw/ipmi/ipmi_bmc_sim.c          | 24 +++++------
>  hw/ipmi/isa_ipmi_bt.c           | 22 +++++-----
>  hw/ipmi/isa_ipmi_kcs.c          | 20 ++++-----
>  hw/mem/pc-dimm.c                | 10 ++---
>  hw/mips/mips_jazz.c             |  2 +-
>  hw/misc/imx_ccm.c               |  2 +-
>  hw/net/e1000.c                  |  2 +-
>  hw/net/vhost_net.c              |  4 +-
>  hw/net/vmxnet3.c                |  2 +-
>  hw/nvram/fw_cfg.c               |  2 +-
>  hw/pci-bridge/pcie_root_port.c  |  8 ++--
>  hw/pci/pci.c                    | 17 ++++----
>  hw/pcmcia/pxa2xx.c              | 16 +++----
>  hw/ppc/pnv.c                    | 14 +++---
>  hw/ppc/pnv_core.c               |  2 +-
>  hw/ppc/pnv_xscom.c              |  6 +--
>  hw/ppc/prep.c                   |  8 ++--
>  hw/ppc/spapr.c                  | 50 +++++++++++-----------
>  hw/ppc/spapr_cpu_core.c         |  4 +-
>  hw/ppc/spapr_drc.c              | 20 ++++-----
>  hw/ppc/spapr_events.c           |  6 +--
>  hw/ppc/spapr_hcall.c            |  2 +-
>  hw/ppc/spapr_pci.c              | 14 +++---
>  hw/ppc/spapr_rtas.c             |  8 ++--
>  hw/ppc/spapr_vio.c              | 12 +++---
>  hw/s390x/css-bridge.c           |  2 +-
>  hw/s390x/css.c                  |  6 +--
>  hw/s390x/event-facility.c       | 14 +++---
>  hw/s390x/s390-skeys-kvm.c       |  2 +-
>  hw/s390x/s390-skeys.c           |  8 ++--
>  hw/s390x/s390-virtio-ccw.c      |  8 ++--
>  hw/s390x/sclp.c                 | 10 ++---
>  hw/s390x/virtio-ccw.c           | 12 +++---
>  hw/scsi/megasas.c               |  8 ++--
>  hw/scsi/mptconfig.c             |  6 +--
>  hw/scsi/scsi-bus.c              |  8 ++--
>  hw/scsi/vhost-scsi.c            |  4 +-
>  hw/scsi/virtio-scsi-dataplane.c |  6 +--
>  hw/scsi/vmw_pvscsi.c            |  2 +-
>  hw/sd/core.c                    | 18 ++++----
>  hw/sh4/sh7750.c                 |  2 +-
>  hw/smbios/smbios_type_38.c      |  2 +-
>  hw/sparc/sun4m.c                |  2 +-
>  hw/sparc64/sun4u.c              |  2 +-
>  hw/ssi/aspeed_smc.c             |  2 +-
>  hw/ssi/ssi.c                    |  8 ++--
>  hw/ssi/xilinx_spips.c           |  2 +-
>  hw/timer/i8254.c                |  2 +-
>  hw/timer/i8254_common.c         | 10 ++---
>  hw/timer/m48t59-isa.c           |  2 +-
>  hw/timer/m48t59.c               |  2 +-
>  hw/usb/bus.c                    | 32 +++++++-------
>  hw/usb/dev-smartcard-reader.c   |  8 ++--
>  hw/usb/hcd-ehci-pci.c           |  2 +-
>  hw/usb/hcd-ehci-sysbus.c        |  2 +-
>  hw/usb/hcd-uhci.c               |  2 +-
>  hw/vfio/amd-xgbe.c              |  2 +-
>  hw/vfio/calxeda-xgmac.c         |  2 +-
>  hw/virtio/vhost-vsock.c         |  4 +-
>  hw/virtio/vhost.c               |  2 +-
>  hw/virtio/virtio-bus.c          | 24 +++++------
>  hw/virtio/virtio-mmio.c         |  2 +-
>  hw/virtio/virtio-pci.c          | 20 ++++-----
>  hw/virtio/virtio.c              | 62 +++++++++++++--------------
>  hw/xen/xen_backend.c            |  3 +-
>  io/channel.c                    | 20 ++++-----
>  kvm-all.c                       |  2 +-
>  migration/migration.c           |  2 +-
>  migration/savevm.c              |  2 +-
>  monitor.c                       |  2 +-
>  net/filter.c                    |  6 +--
>  qdev-monitor.c                  | 12 +++---
>  qmp.c                           |  4 +-
>  qom/cpu.c                       | 26 ++++++------
>  qom/object.c                    | 31 +++++++-------
>  qom/object_interfaces.c         |  4 +-
>  target/alpha/cpu.c              |  2 +-
>  target/arm/cpu.c                |  8 ++--
>  target/arm/kvm.c                |  2 +-
>  target/cris/cpu.c               | 10 ++---
>  target/cris/helper.c            |  2 +-
>  target/hppa/cpu.c               |  2 +-
>  target/i386/cpu.c               | 10 ++---
>  target/i386/kvm.c               |  2 +-
>  target/i386/machine.c           |  3 +-
>  target/lm32/cpu.c               |  4 +-
>  target/lm32/gdbstub.c           |  2 +-
>  target/m68k/cpu.c               |  4 +-
>  target/microblaze/cpu.c         |  4 +-
>  target/microblaze/gdbstub.c     |  2 +-
>  target/mips/cpu.c               |  4 +-
>  target/moxie/cpu.c              |  4 +-
>  target/nios2/cpu.c              |  8 ++--
>  target/openrisc/cpu.c           |  4 +-
>  target/openrisc/gdbstub.c       |  2 +-
>  target/ppc/arch_dump.c          |  2 +-
>  target/ppc/compat.c             |  4 +-
>  target/ppc/excp_helper.c        |  2 +-
>  target/ppc/mmu-hash64.c         |  6 +--
>  target/ppc/mmu_helper.c         |  2 +-
>  target/ppc/translate_init.c     | 14 +++---
>  target/s390x/cpu.c              |  6 +--
>  target/s390x/cpu_models.c       |  4 +-
>  target/s390x/kvm.c              |  4 +-
>  target/s390x/mem_helper.c       |  6 +--
>  target/s390x/misc_helper.c      |  6 +--
>  target/s390x/mmu_helper.c       |  2 +-
>  target/sh4/cpu.c                |  4 +-
>  target/sparc/cpu.c              |  4 +-
>  target/tilegx/cpu.c             |  4 +-
>  target/tricore/cpu.c            |  4 +-
>  target/unicore32/cpu.c          |  2 +-
>  target/xtensa/cpu.c             |  6 +--
>  tests/check-qom-interface.c     |  2 +-
>  user-exec.c                     |  2 +-
>  vl.c                            |  2 +-
>  198 files changed, 800 insertions(+), 721 deletions(-)
> 
> -- 
> 2.11.0.259.g40922b1
> 

-- 
Eduardo

Re: [Qemu-devel] [RFC v2 0/9] qom: Make object_get_class()/*_GET_CLASS return const pointers
Posted by Paolo Bonzini 7 years ago

On 29/03/2017 21:41, Eduardo Habkost wrote:
> QOM has a data model where class struct data is static: class
> structs are initialized at class_init, and never changed again.

Isn't that just the way class data is being used?  There's no reason for
class data to be static.  It happens to be that way because our
hierarchies are pretty shallow and global static variables are used
instead of class data.  But it doesn't _have_ to be like that.

That said, the QUALIFIED_CAST concept is very interesting and I'd even
extend it to OBJECT_CHECK, object_dynamic_cast and
object_dynamic_cast_assert.  I'm just not sure about returning const
from object_get_class()/*_GET_CLASS, which ironically is the thing that
prompted you to write the series. :)

Paolo

> ...except for a few rare cases where class data is changed
> outside class_init. Those cases are:
> 
>   qbus_realize(), code added by:
>   commit 61de36761b565a4138d8ad7ec75489ab28fe84b6
>   Date:   Thu Feb 6 16:08:15 2014 +0100
>       qdev: Keep global allocation counter per bus
> 
>   mips_jazz_init(), code added by:
>   commit 54e755588cf1e90f0b1460c4e8e6b6a54b6d3a32
>   Date:   Mon Nov 4 23:26:17 2013 +0100
>       mips jazz: do not raise data bus exception when accessing invalid addresses
> 
>   xen_set_dynamic_sysbus(), code added by:
>   commit 3a6c9172ac5951e6dac2b3f6cbce3cfccdec5894
>   Date:   Tue Nov 22 07:10:58 2016 +0100
>       xen: create qdev for each backend device
> 
>   s390_cpu_realizefn(), code added by:
>   commit c6644fc88bed1176f67b4b7a9df691bcf25c0c5b
>   Date:   Fri Mar 4 12:34:31 2016 -0500
>       s390x/cpu: Get rid of side effects when creating a vcpu

Re: [Qemu-devel] [RFC v2 0/9] qom: Make object_get_class()/*_GET_CLASS return const pointers
Posted by Eduardo Habkost 7 years ago
On Thu, Mar 30, 2017 at 10:59:10AM +0200, Paolo Bonzini wrote:
> 
> 
> On 29/03/2017 21:41, Eduardo Habkost wrote:
> > QOM has a data model where class struct data is static: class
> > structs are initialized at class_init, and never changed again.
> 
> Isn't that just the way class data is being used?  There's no reason for
> class data to be static.  It happens to be that way because our
> hierarchies are pretty shallow and global static variables are used
> instead of class data.  But it doesn't _have_ to be like that.

I disagree. I believe this is how class data is meant to be used.
if we change per-class data at runtime outside class_init, we
have a hard time providing querying and introspection mechanisms
for types. If something really needs to be changed at runtime
outside class_init, it belongs to object instance fields, not
class data fields.

e.g. the main benefit we got from eliminating the compat_* global
variables in machine/pc code wasn't simply the global variable
elimination: it was making the compat data static and available
at the MachineClass structs, instead of burying it inside
machine_init functions. If we kept the old model where
class-specific data was initialized at machine_init-time,
extending query-machines with that info, and writing new machine
data queries would still be impossible.


For reference, this is how I think we could have dealt with the
existing cases of non-const class variables:

> >   qbus_realize(), code added by:
> >   commit 61de36761b565a4138d8ad7ec75489ab28fe84b6
> >   Date:   Thu Feb 6 16:08:15 2014 +0100
> >       qdev: Keep global allocation counter per bus

This one might make sense: it's easier to keep data in a BusClass
field than a automatic_id[bus_type] dictionary somewhere else.

But I would still prefer to have a automatic_id[bus_type]
dictionary inside MachineState instead of this.

> > 
> >   mips_jazz_init(), code added by:
> >   commit 54e755588cf1e90f0b1460c4e8e6b6a54b6d3a32
> >   Date:   Mon Nov 4 23:26:17 2013 +0100
> >       mips jazz: do not raise data bus exception when accessing invalid addresses

IMO, a simple MIPSCPU::ignore_invalid_exec_access boolean flag
would be better than hijacking TYPE_MIPS_CPU's
do_unassigned_access() method on the fly.

> > 
> >   xen_set_dynamic_sysbus(), code added by:
> >   commit 3a6c9172ac5951e6dac2b3f6cbce3cfccdec5894
> >   Date:   Tue Nov 22 07:10:58 2016 +0100
> >       xen: create qdev for each backend device

Here, setting has_dynamic_sysbus for all PC classes would be
better, so a future supported-device-types/device-slot querying
mechanism wouldn't incorrectly report xen-backend as unsupported.
But there are additional problems I want to sove regarding sysbus
before doing that.

BTW, this is the case that prompted me to write this series in
the first place. I believe changing
MachineClass::has_dynamic_sysbus at runtime was a mistake, and a
const object_get_class() would have helped us catch that.

> > 
> >   s390_cpu_realizefn(), code added by:
> >   commit c6644fc88bed1176f67b4b7a9df691bcf25c0c5b
> >   Date:   Fri Mar 4 12:34:31 2016 -0500
> >       s390x/cpu: Get rid of side effects when creating a vcpu

Here, I see no reason for a per-cpu-class field at all. Even a
static next_cpu_id variable wouldn't hurt.

Also, this is the only remaining code still using cpu_exists(),
and the same logic probably can be implemented using
MachineClass::possible_cpu_arch_ids() instead.

> 
> That said, the QUALIFIED_CAST concept is very interesting and I'd even
> extend it to OBJECT_CHECK, object_dynamic_cast and
> object_dynamic_cast_assert.  I'm just not sure about returning const
> from object_get_class()/*_GET_CLASS, which ironically is the thing that
> prompted you to write the series. :)

Makes sense. I will send extra patches to change the object cast
macros, too.

> 
> Paolo
> 

-- 
Eduardo

Re: [Qemu-devel] [RFC v2 0/9] qom: Make object_get_class()/*_GET_CLASS return const pointers
Posted by Eduardo Habkost 7 years ago
On Thu, Mar 30, 2017 at 10:59:10AM +0200, Paolo Bonzini wrote:
[...]
> That said, the QUALIFIED_CAST concept is very interesting and I'd even
> extend it to OBJECT_CHECK, object_dynamic_cast and
> object_dynamic_cast_assert.  I'm just not sure about returning const
> from object_get_class()/*_GET_CLASS, which ironically is the thing that
> prompted you to write the series. :)

When trying to change OBJECT and OBJECT_CHECK, I've found a
problem: gcc 6.2.1 can't evaluate typeof(*a) if *a has an
incomplete type, even inside the (const typeof(*(t)0) *)
expression used in QUALIFIED_CAST. It works on clang, though.

I'm not sure we want to introduce something that would report
errors only on clang only[1]. Especially when the error messages
look like this:
  hw/mem/pc-dimm.c:248:23: error: passing 'typeof (_Generic((const typeof (*((typeof ((a)))0)) *)0, typeof ((a)): (const Object *)(0), default: (Object *)(0)))' (aka 'const struct Object *') to parameter of type 'Object *' (aka 'struct Object *') discards qualifiers [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
      PCDIMMDevice *x = PC_DIMM(a);

Lucikly all the OBJECT_CLASS usage I've found never involved
incomplete types, but they are more common when dealing with
object pointers.

We could also require all users of OBJECT(x) to include the
header that defines the struct type of x. But I'm not sure it's
worth the effort.

-- 
Eduardo

Re: [Qemu-devel] [RFC v2 0/9] qom: Make object_get_class()/*_GET_CLASS return const pointers
Posted by Paolo Bonzini 7 years ago

On 02/04/2017 15:31, Eduardo Habkost wrote:
> When trying to change OBJECT and OBJECT_CHECK, I've found a
> problem: gcc 6.2.1 can't evaluate typeof(*a) if *a has an
> incomplete type, even inside the (const typeof(*(t)0) *)
> expression used in QUALIFIED_CAST. It works on clang, though.
> 
> I'm not sure we want to introduce something that would report
> errors only on clang only[1]. Especially when the error messages
> look like this:
>   hw/mem/pc-dimm.c:248:23: error: passing 'typeof (_Generic((const typeof (*((typeof ((a)))0)) *)0, typeof ((a)): (const Object *)(0), default: (Object *)(0)))' (aka 'const struct Object *') to parameter of type 'Object *' (aka 'struct Object *') discards qualifiers [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
>       PCDIMMDevice *x = PC_DIMM(a);
> 
> Lucikly all the OBJECT_CLASS usage I've found never involved
> incomplete types, but they are more common when dealing with
> object pointers.
> 
> We could also require all users of OBJECT(x) to include the
> header that defines the struct type of x. But I'm not sure it's
> worth the effort.

Fair enough!  Thanks for trying.

Paolo