All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eduardo Habkost <ehabkost@redhat.com>
To: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Kevin Wolf" <kwolf@redhat.com>,
	"Daniel P. Berrange" <berrange@redhat.com>,
	"Philippe Mathieu-Daudé" <philmd@redhat.com>,
	qemu-devel@nongnu.org, "Markus Armbruster" <armbru@redhat.com>,
	"Igor Mammedov" <imammedo@redhat.com>,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>,
	"John Snow" <jsnow@redhat.com>,
	"Stefan Berger" <stefanb@linux.ibm.com>
Subject: Re: [PATCH v2 00/44] Make qdev static property API usable by any QOM type
Date: Mon, 9 Nov 2020 13:55:58 -0500	[thread overview]
Message-ID: <20201109185558.GB5733@habkost.net> (raw)
In-Reply-To: <098ca211-3ad5-b194-e9f5-678291fe641e@redhat.com>

On Mon, Nov 09, 2020 at 06:33:04PM +0100, Paolo Bonzini wrote:
> On 09/11/20 18:16, Eduardo Habkost wrote:
> > On Mon, Nov 09, 2020 at 05:34:01PM +0100, Paolo Bonzini wrote:
> > > On 09/11/20 16:21, Eduardo Habkost wrote:
> > > > Nothing prevents us from describing those properties inside the
> > > > same property array.
> > > 
> > > Do you mean adding PropertyInfos for them?  Adding a once-only PropertyInfo
> > > is worse than writing a custom getter/setter pair, because:
> > > 
> > > - without (DEFINE_)PROP_* you lose the type safety.
> > > 
> > > - with (DEFINE_)PROP_* you have much more boilerplate to write
> > 
> > I mean extending the API to let custom setters and getters appear
> > on the Property array, not using the existing API.
> 
> That seems like conflicting goals.  The field property API is based on
> getters and setters hidden in PropertyInfo.  The "other" property API is
> based on getters and setters in plain sight in the declaration of the
> property.

There's nothing that prevents a
  void object_class_add_properties(oc, Property *props);
function from supporting both.

> 
> > > > > > I think having different ways for different things (class vs. object) is
> > > > > > better than having different ways for the same things (class in qdev vs.
> > > > > > class in non-qdev).
> > > > > 
> > > > > Right, but qdev's DEFINE_PROP_STRING would be easy to change to something
> > > > > like
> > > > > 
> > > > > - DEFINE_PROP_STRING("name", ...),
> > > > > + device_class_add_field_property(dc, "name", PROP_STRING(...));
> > > > 
> > > > I'm not worried about this direction of conversion (which is
> > > > easy).  I'm worried about the function call => QAPI schema
> > > > conversion.  Function calls are too flexible and requires parsing
> > > > and executing C code.
> > > 
> > > Converting DEFINE_PROP_STRING to a schema also requires parsing C code,
> > > since you can have handwritten Property literals (especially for custom
> > > PropertyInfo).  Converting DEFINE_PROP_STRING it also requires matching the
> > > array against calls to object_class_add_field_properties (which could be
> > > hidden behind helpers such as device_class_set_props).  (Plus matching
> > > class_init functions against TypeInfo).
> > 
> > Parsing an array containing a handful of macros (a tiny subset of
> > C) isn't even comparable to parsing and executing C code where
> > object*_property_add*() calls can be buried deep in many levels
> > of C function calls (which may or may not be conditional).
> 
> Finding the array would also require finding calls buried deep in C code,
> wouldn't they?

Yes, but I don't expect this to happen if the API doesn't
encourage that.

> 
> > (Also, I don't think we should allow handwritten Property literals.)
> 
> How would you do custom setters and getters then---without separate
> PropertyInfos, without Property literals, and without an exploding number of
> macros?

Property with struct field:

  /* We call this DEFINE_PROP_UINT32 today.  We can keep the
   * existing name just to reduce churn.
   */
  DEFINE_PROP_UINT32_FIELD("myproperty", MyState, my_field)


Prop with struct field but custom setter:

  DEFINE_PROP_UINT32_FIELD("myproperty", MyState, my_field,
                           .custom_setter = my_custom_setter)

Prop with no struct field, and custom setter/getter:

  DEFINE_PROP("myproperty", prop_type_uint32,
              .custom_getter = my_getter,
              .custom_setter = my_setter)


Definitions for above:

#define DEFINE_PROP(_name, _typeinfo, ...) \
    { .name = _name,
      .info = &_typeinfo,
      __VA_ARGS__
    }

#define DEFINE_FIELD_PROP(name, typeinfo, type, state, field, ...) \
    DEFINE_PROP(name, typeinfo,
                .offset = offsetof(state, field) +
                          type_check(typeof_field(state, field), type),
                __VA_ARGS__)

#define DEFINE_PROP_UINT32_FIELD(name, state, field, ...) \
    DEFINE_FIELD_PROP(name, prop_type_uint32, uint32_t, state, field, __VA_ARGS__)


Alternative DEFINE_FIELD_PROP definition if we implement some
macro magic to declare the expected type for each typeinfo
variable:

/* Will make ACTUAL_C_TYPE(prop_type_uint32) expand to uint32_t */
DECLARE_QOM_TYPE(prop_type_uint32, uint32_t)
/* Will make ACTUAL_C_TYPE(prop_type_uint64) expand to uint64_t) 
DECLARE_QOM_TYPE(prop_type_uint64, uint64_t)

#define DEFINE_FIELD_PROP(name, typeinfo, state, field, ...) \
    DEFINE_PROP(name, typeinfo,
                .offset = offsetof(state, field) +
                          type_check(typeof_field(state, field),
                                     ACTUAL_C_TYPE(typeinfo)),
                __VA_ARGS__)


> 
> > > So, you don't save any parsing by using arrays.  (In fact I would probably
> > > skip the parsing, and use your suggestion of *executing* C code: write the
> > > QAPI schema generator in C, link into QEMU and run it just once to generate
> > > the QOM schema).
> > 
> > If we do that with the existing code, we can't be sure the
> > generated schema doesn't depend on configure flags or run time
> > checks inside class_init.
> 
> We can use grep or Coccinelle or manual code review to identify problematic
> cases.

We can, but I believe it is better and simpler to have an API
that enforces (or at least encourages) this.

> 
> > Even locating the cases where this is
> > happening is being a challenge because the API is too flexible.
> > 
> > However, if we require the property list to be always evaluated
> > at compile time, we can be sure that this method will be
> > reliable.
> > 
> > > QOM has been using function calls for many years, are there any cases of
> > > misuse of that flexibility that you have in mind?  I can only think of two
> > > *uses*, in fact.  One is eepro100_register_types is the only case I can
> > > remember where types are registered dynamically.  The other is S390 CPU
> > > features.  [...]
> > 
> > The list of tricky dynamic properties is large and I don't think
> > we even found all cases yet.  John documented many of them here:
> > 
> > https://gitlab.com/jsnow/qemu/-/blob/cli_audit/docs/cli_audit.md
> > 
> > Look, for example, for the sections named "Features" for CPU
> > options.
> 
> Yes, I'm only considering object_class_property calls.  Those are the ones
> that I claim aren't being misused enough for this to be a problem.
> 

instance-level properties are where most of the complexity was
introduced because the class API didn't exist yet.  I don't think
we should ignore them, or we risk having the same issues when
converting them to class properties.


> Making instance-level properties appear in the schema is a completely
> different kind of conversion, because there is plenty of manual work (and
> unsolved problems for e.g. subobject property aliases).

I'd like us to convert instance-level properties to an API that
is easy to use and where the same problems won't happen again.

> 
> > You are also ignoring the complexity of the code path that leads
> > to the object*_property_add*() calls, which is the main problem
> > on most cases.
> 
> I would like an example of the complexity of those code paths.  I don't see
> much complexity, as long as the object exists at all, and I don't see how it
> would be simpler to find the code paths that lead to
> object_class_add_field_properties.

Possibly the most complex case is x86_cpu_register_bit_prop().
The qdev_property_add_static() calls at arm_cpu_post_init() are
tricky too.

If object*_property_add*() is hidden behind a function call or a
`if` statement, it's already too much complexity to me.  I don't
want us to need a second audit like the one John made when we
decide to represent QOM class properties in a QAPI schema.

-- 
Eduardo



  reply	other threads:[~2020-11-09 18:57 UTC|newest]

Thread overview: 77+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-04 15:59 [PATCH v2 00/44] Make qdev static property API usable by any QOM type Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 01/44] cs4231: Get rid of empty property array Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 02/44] cpu: Move cpu_common_props to hw/core/cpu.c Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 03/44] qdev: Move property code to qdev-properties.[ch] Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 04/44] qdev: Check dev->realized at set_size() Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 05/44] sparc: Check dev->realized at sparc_set_nwindows() Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 06/44] qdev: Don't use dev->id on set_size32() error message Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 07/44] qdev: Make PropertyInfo.print method get Object* argument Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 08/44] qdev: Make bit_prop_set() " Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 09/44] qdev: Make qdev_get_prop_ptr() get Object* arg Eduardo Habkost
2020-11-04 15:59   ` Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 10/44] qdev: Make qdev_find_global_prop() get Object* argument Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 11/44] qdev: Make check_prop_still_unset() " Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 12/44] qdev: Make error_set_from_qdev_prop_error() " Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 13/44] qdev: Move UUID property to qdev-properties-system.c Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 14/44] qdev: Move softmmu properties to qdev-properties-system.h Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 15/44] qdev: Reuse DEFINE_PROP in all DEFINE_PROP_* macros Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 16/44] sparc: Use DEFINE_PROP for nwindows property Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 17/44] qdev: Get just property name at error_set_from_qdev_prop_error() Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 18/44] qdev: Avoid using prop->name unnecessarily Eduardo Habkost
2020-11-04 17:25   ` Stefan Berger
2020-11-04 15:59 ` [PATCH v2 19/44] qdev: Add name parameter to qdev_class_add_property() Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 20/44] qdev: Add name argument to PropertyInfo.create method Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 21/44] qdev: Wrap getters and setters in separate helpers Eduardo Habkost
2020-11-04 15:59 ` [PATCH v2 22/44] qdev: Move dev->realized check to qdev_property_set() Eduardo Habkost
2020-11-04 15:59   ` Eduardo Habkost
2020-11-04 17:28   ` Stefan Berger
2020-11-04 17:28     ` Stefan Berger
2020-11-04 16:00 ` [PATCH v2 23/44] qdev: Make PropertyInfo.create return ObjectProperty* Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 24/44] qdev: Make qdev_class_add_property() more flexible Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 25/44] qdev: Separate generic and device-specific property registration Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 26/44] qdev: Rename Property.name to Property.qdev_prop_name Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 27/44] qdev: Don't set qdev_prop_name for array elements Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 28/44] qdev: Avoid unnecessary DeviceState* variable at set_prop_arraylen() Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 29/44] qdev: Remove ArrayElementProperty.propname field Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 30/44] qdev: Get rid of ArrayElementProperty struct Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 31/44] qdev: Reuse object_property_add_field() when adding array elements Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 32/44] qom: Add allow_set callback to ObjectProperty Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 33/44] qdev: Make qdev_prop_allow_set() a ObjectProperty.allow_set callback Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 34/44] qdev: Make qdev_propinfo_get_uint16() static Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 35/44] qdev: Rename qdev_propinfo_* to field_prop_* Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 36/44] qdev: Rename qdev_get_prop_ptr() to object_field_prop_ptr() Eduardo Habkost
2020-11-04 16:00   ` Eduardo Habkost
2020-11-05 18:49   ` Stefan Berger
2020-11-05 18:49     ` Stefan Berger
2020-11-04 16:00 ` [PATCH v2 37/44] qdev: Move qdev_prop_tpm declaration to tpm_prop.h Eduardo Habkost
2020-11-05 18:50   ` Stefan Berger
2020-11-04 16:00 ` [PATCH v2 38/44] qdev: Rename qdev_prop_* to prop_info_* Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 39/44] qdev: PROP_* macros Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 40/44] qdev: Move core field property code to QOM Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 41/44] qdev: Move base property types to qom/property-types.c Eduardo Habkost
2020-11-04 16:36   ` Paolo Bonzini
2020-11-04 20:50     ` Eduardo Habkost
2020-11-05  9:36       ` Paolo Bonzini
2020-11-04 16:00 ` [PATCH v2 42/44] qom: Include static property API reference in documentation Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 43/44] tests: Use field properties at check-qom-proplist test case Eduardo Habkost
2020-11-04 16:00 ` [PATCH v2 44/44] machine: Register most properties as field properties Eduardo Habkost
2020-11-04 16:36 ` [PATCH v2 00/44] Make qdev static property API usable by any QOM type no-reply
2020-11-06  9:45 ` Kevin Wolf
2020-11-06 15:50   ` Eduardo Habkost
2020-11-06 21:10     ` Eduardo Habkost
2020-11-08 14:05       ` Paolo Bonzini
2020-11-09 11:34         ` Kevin Wolf
2020-11-09 14:15           ` Paolo Bonzini
2020-11-09 15:21             ` Eduardo Habkost
2020-11-09 16:34               ` Paolo Bonzini
2020-11-09 17:16                 ` Eduardo Habkost
2020-11-09 17:33                   ` Paolo Bonzini
2020-11-09 18:55                     ` Eduardo Habkost [this message]
2020-11-09 19:27                       ` Paolo Bonzini
2020-11-09 20:28                         ` Eduardo Habkost
2020-11-10 10:38                           ` Kevin Wolf
2020-11-11 18:39                             ` Eduardo Habkost
2020-11-12  8:11                               ` Paolo Bonzini
2020-11-12 14:53                                 ` Eduardo Habkost
2020-11-10 10:58                           ` Paolo Bonzini
2020-11-10 17:03                             ` Eduardo Habkost

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201109185558.GB5733@habkost.net \
    --to=ehabkost@redhat.com \
    --cc=armbru@redhat.com \
    --cc=berrange@redhat.com \
    --cc=imammedo@redhat.com \
    --cc=jsnow@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=philmd@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanb@linux.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.