diff mbox series

[03/12] qom: Make object_class_property_add_uint*_ptr() get offset

Message ID 20201009160122.1662082-4-ehabkost@redhat.com
State New
Headers show
Series qom: Make all -object types use only class properties | expand

Commit Message

Eduardo Habkost Oct. 9, 2020, 4:01 p.m. UTC
The existing object_class_property_add_uint*_ptr() functions are
not very useful, because they need a pointer to the property
value, which can't really be provided before the object is
created.

Replace the pointer parameter in those functions with a
`ptrdiff_t offset` parameter.

Include a uint8 class property in check-qom-proplist unit tests,
to ensure the feature is working.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Daniel P. Berrangé" <berrange@redhat.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: qemu-devel@nongnu.org
---
 include/qom/object.h       |  8 ++++----
 qom/object.c               | 36 +++++++++++++++++++++++-------------
 tests/check-qom-proplist.c | 10 ++++++++--
 3 files changed, 35 insertions(+), 19 deletions(-)

Comments

Eric Blake Oct. 9, 2020, 5:24 p.m. UTC | #1
On 10/9/20 11:01 AM, Eduardo Habkost wrote:
> The existing object_class_property_add_uint*_ptr() functions are
> not very useful, because they need a pointer to the property
> value, which can't really be provided before the object is
> created.
> 
> Replace the pointer parameter in those functions with a
> `ptrdiff_t offset` parameter.
> 
> Include a uint8 class property in check-qom-proplist unit tests,
> to ensure the feature is working.
> 
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---

>  static void *pointer_property_get_ptr(Object *obj, PointerProperty *prop)
>  {
> -    return prop->ptr;
> +    if (prop->is_offset) {
> +        return (void *)obj + prop->offset;

Addition on void* is a gcc extension.  Does clang support it as well, or
should you be casting to char* instead?

> +    } else {
> +        return prop->ptr;
> +    }
>  }
>  

> +++ b/tests/check-qom-proplist.c
> @@ -61,6 +61,7 @@ struct DummyObject {
>      bool bv;
>      DummyAnimal av;
>      char *sv;
> +    uint8_t u8v;
>  };
>  
>  struct DummyObjectClass {
> @@ -141,6 +142,9 @@ static void dummy_class_init(ObjectClass *cls, void *data)
>                                     &dummy_animal_map,
>                                     dummy_get_av,
>                                     dummy_set_av);
> +    object_class_property_add_uint8_ptr(cls, "u8v",
> +                                        offsetof(DummyObject, u8v),
> +                                        OBJ_PROP_FLAG_READWRITE);

I like how it turns out.
Eduardo Habkost Oct. 9, 2020, 5:31 p.m. UTC | #2
On Fri, Oct 09, 2020 at 12:24:19PM -0500, Eric Blake wrote:
> On 10/9/20 11:01 AM, Eduardo Habkost wrote:
> > The existing object_class_property_add_uint*_ptr() functions are
> > not very useful, because they need a pointer to the property
> > value, which can't really be provided before the object is
> > created.
> > 
> > Replace the pointer parameter in those functions with a
> > `ptrdiff_t offset` parameter.
> > 
> > Include a uint8 class property in check-qom-proplist unit tests,
> > to ensure the feature is working.
> > 
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > ---
> 
> >  static void *pointer_property_get_ptr(Object *obj, PointerProperty *prop)
> >  {
> > -    return prop->ptr;
> > +    if (prop->is_offset) {
> > +        return (void *)obj + prop->offset;
> 
> Addition on void* is a gcc extension.  Does clang support it as well, or
> should you be casting to char* instead?

Both object_link_get_targetp() and object_link_get_targetp()
already use it, so it should be OK.
Igor Mammedov Oct. 21, 2020, 12:24 p.m. UTC | #3
On Fri,  9 Oct 2020 12:01:13 -0400
Eduardo Habkost <ehabkost@redhat.com> wrote:

> The existing object_class_property_add_uint*_ptr() functions are
> not very useful, because they need a pointer to the property
> value, which can't really be provided before the object is
> created.
> 
> Replace the pointer parameter in those functions with a
> `ptrdiff_t offset` parameter.
> 
> Include a uint8 class property in check-qom-proplist unit tests,
> to ensure the feature is working.


Not sure I like approach, it's reinventing qdev pointer properties in QOM form.
I had an impression that Paolo wanted qdev pointer properties be gone
and replaced by something like link properties.

object_property_add_uintXX_ptr() were introduced as a quick hack,
when ACPI code generation was moved from Seabios, to avoid more
code shuffling in device models and adding more boiler plate in
form of custom setters/getters (the later didn't seem to bother
us everywhere else where we use object_[class_]property_add() ).
Then it spread little bit to another places.

I'd rather get rid of object_property_add_uintXX_ptr() API altogether
in favor of object_[class_]property_add() like it is used in other places
to handle intXX properties.
Adding helpers similar to object_property_add_bool() for intXX
could reduce boiler plate need for converting current instances of
_ptr(), and such helpers would also help with reducing boilerplate
for the rest of instances where object_[class_]property_add()
currently is used for dealing with integers.


> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: "Daniel P. Berrangé" <berrange@redhat.com>
> Cc: Eduardo Habkost <ehabkost@redhat.com>
> Cc: qemu-devel@nongnu.org
> ---
>  include/qom/object.h       |  8 ++++----
>  qom/object.c               | 36 +++++++++++++++++++++++-------------
>  tests/check-qom-proplist.c | 10 ++++++++--
>  3 files changed, 35 insertions(+), 19 deletions(-)
> 
> diff --git a/include/qom/object.h b/include/qom/object.h
> index d378f13a11..1634294e4f 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -1747,7 +1747,7 @@ ObjectProperty *object_property_add_uint8_ptr(Object *obj, const char *name,
>  
>  ObjectProperty *object_class_property_add_uint8_ptr(ObjectClass *klass,
>                                           const char *name,
> -                                         const uint8_t *v,
> +                                         ptrdiff_t offset,
>                                           ObjectPropertyFlags flags);
>  
>  /**
> @@ -1768,7 +1768,7 @@ ObjectProperty *object_property_add_uint16_ptr(Object *obj, const char *name,
>  
>  ObjectProperty *object_class_property_add_uint16_ptr(ObjectClass *klass,
>                                            const char *name,
> -                                          const uint16_t *v,
> +                                          ptrdiff_t offset,
>                                            ObjectPropertyFlags flags);
>  
>  /**
> @@ -1789,7 +1789,7 @@ ObjectProperty *object_property_add_uint32_ptr(Object *obj, const char *name,
>  
>  ObjectProperty *object_class_property_add_uint32_ptr(ObjectClass *klass,
>                                            const char *name,
> -                                          const uint32_t *v,
> +                                          ptrdiff_t offset,
>                                            ObjectPropertyFlags flags);
>  
>  /**
> @@ -1810,7 +1810,7 @@ ObjectProperty *object_property_add_uint64_ptr(Object *obj, const char *name,
>  
>  ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass,
>                                            const char *name,
> -                                          const uint64_t *v,
> +                                          ptrdiff_t offset,
>                                            ObjectPropertyFlags flags);
>  
>  /**
> diff --git a/qom/object.c b/qom/object.c
> index 17692ed5c3..bb32f5d3ad 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -2450,13 +2450,22 @@ static char *object_get_type(Object *obj, Error **errp)
>  }
>  
>  typedef struct {
> -    /* Pointer to property value */
> -    void *ptr;
> +    bool is_offset;
> +    union {
> +        /* Pointer to property value.  Valid if is_offset=false */
> +        void *ptr;
> +        /* Offset in Object struct.  Valid if is_offset=true */
> +        ptrdiff_t offset;
> +    };
>  } PointerProperty;
>  
>  static void *pointer_property_get_ptr(Object *obj, PointerProperty *prop)
>  {
> -    return prop->ptr;
> +    if (prop->is_offset) {
> +        return (void *)obj + prop->offset;
> +    } else {
> +        return prop->ptr;
> +    }
>  }
>  
>  static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
> @@ -2573,10 +2582,11 @@ object_class_property_add_uint_ptr(ObjectClass *oc, const char *name,
>                                     ObjectPropertyAccessor getter,
>                                     ObjectPropertyAccessor setter,
>                                     ObjectPropertyFlags flags,
> -                                   void *ptr)
> +                                   ptrdiff_t offset)
>  {
>      PointerProperty *prop = g_new0(PointerProperty, 1);
> -    prop->ptr = ptr;
> +    prop->is_offset = true;
> +    prop->offset = offset;
>      return object_class_property_add(oc, name, type,
>                                       (flags & OBJ_PROP_FLAG_READ) ? getter : NULL,
>                                       (flags & OBJ_PROP_FLAG_WRITE) ? setter : NULL,
> @@ -2597,13 +2607,13 @@ object_property_add_uint8_ptr(Object *obj, const char *name,
>  
>  ObjectProperty *
>  object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
> -                                    const uint8_t *v,
> +                                    ptrdiff_t offset,
>                                      ObjectPropertyFlags flags)
>  {
>      return object_class_property_add_uint_ptr(klass, name, "uint8",
>                                                property_get_uint8_ptr,
>                                                property_set_uint8_ptr,
> -                                              flags, (void *)v);
> +                                              flags, offset);
>  }
>  
>  ObjectProperty *
> @@ -2620,13 +2630,13 @@ object_property_add_uint16_ptr(Object *obj, const char *name,
>  
>  ObjectProperty *
>  object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
> -                                     const uint16_t *v,
> +                                     ptrdiff_t offset,
>                                       ObjectPropertyFlags flags)
>  {
>      return object_class_property_add_uint_ptr(klass, name, "uint16",
>                                                property_get_uint16_ptr,
>                                                property_set_uint16_ptr,
> -                                              flags, (void *)v);
> +                                              flags, offset);
>  }
>  
>  ObjectProperty *
> @@ -2643,13 +2653,13 @@ object_property_add_uint32_ptr(Object *obj, const char *name,
>  
>  ObjectProperty *
>  object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
> -                                     const uint32_t *v,
> +                                     ptrdiff_t offset,
>                                       ObjectPropertyFlags flags)
>  {
>      return object_class_property_add_uint_ptr(klass, name, "uint32",
>                                                property_get_uint32_ptr,
>                                                property_set_uint32_ptr,
> -                                              flags, (void *)v);
> +                                              flags, offset);
>  }
>  
>  ObjectProperty *
> @@ -2666,13 +2676,13 @@ object_property_add_uint64_ptr(Object *obj, const char *name,
>  
>  ObjectProperty *
>  object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
> -                                     const uint64_t *v,
> +                                     ptrdiff_t offset,
>                                       ObjectPropertyFlags flags)
>  {
>      return object_class_property_add_uint_ptr(klass, name, "uint64",
>                                                property_get_uint64_ptr,
>                                                property_set_uint64_ptr,
> -                                              flags, (void *)v);
> +                                              flags, offset);
>  }
>  
>  typedef struct {
> diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
> index 1b76581980..fba30c20b2 100644
> --- a/tests/check-qom-proplist.c
> +++ b/tests/check-qom-proplist.c
> @@ -61,6 +61,7 @@ struct DummyObject {
>      bool bv;
>      DummyAnimal av;
>      char *sv;
> +    uint8_t u8v;
>  };
>  
>  struct DummyObjectClass {
> @@ -141,6 +142,9 @@ static void dummy_class_init(ObjectClass *cls, void *data)
>                                     &dummy_animal_map,
>                                     dummy_get_av,
>                                     dummy_set_av);
> +    object_class_property_add_uint8_ptr(cls, "u8v",
> +                                        offsetof(DummyObject, u8v),
> +                                        OBJ_PROP_FLAG_READWRITE);
>  }
>  
>  
> @@ -385,12 +389,14 @@ static void test_dummy_createlist(void)
>                     "bv", "yes",
>                     "sv", "Hiss hiss hiss",
>                     "av", "platypus",
> +                   "u8v", "42",
>                     NULL));
>  
>      g_assert(err == NULL);
>      g_assert_cmpstr(dobj->sv, ==, "Hiss hiss hiss");
>      g_assert(dobj->bv == true);
>      g_assert(dobj->av == DUMMY_PLATYPUS);
> +    g_assert_cmpint(dobj->u8v, ==, 42);
>  
>      g_assert(object_resolve_path_component(parent, "dummy0")
>               == OBJECT(dobj));
> @@ -531,7 +537,7 @@ static void test_dummy_iterator(void)
>  {
>      const char *expected[] = {
>          "type",                 /* inherited from TYPE_OBJECT */
> -        "sv", "av",             /* class properties */
> +        "sv", "av", "u8v",      /* class properties */
>          "bv"};                  /* instance property */
>      Object *parent = object_get_objects_root();
>      DummyObject *dobj = DUMMY_OBJECT(
> @@ -552,7 +558,7 @@ static void test_dummy_iterator(void)
>  
>  static void test_dummy_class_iterator(void)
>  {
> -    const char *expected[] = { "type", "av", "sv" };
> +    const char *expected[] = { "type", "av", "sv", "u8v" };
>      ObjectPropertyIterator iter;
>      ObjectClass *klass = object_class_by_name(TYPE_DUMMY);
>
Eduardo Habkost Oct. 21, 2020, 1:30 p.m. UTC | #4
On Wed, Oct 21, 2020 at 02:24:08PM +0200, Igor Mammedov wrote:
> On Fri,  9 Oct 2020 12:01:13 -0400
> Eduardo Habkost <ehabkost@redhat.com> wrote:
> 
> > The existing object_class_property_add_uint*_ptr() functions are
> > not very useful, because they need a pointer to the property
> > value, which can't really be provided before the object is
> > created.
> > 
> > Replace the pointer parameter in those functions with a
> > `ptrdiff_t offset` parameter.
> > 
> > Include a uint8 class property in check-qom-proplist unit tests,
> > to ensure the feature is working.
> 
> 
> Not sure I like approach, it's reinventing qdev pointer properties in QOM form.

Yes, and that's on purpose.  If we want to eventually merge the
two competing APIs into a single one, we need to make them
converge.

> I had an impression that Paolo wanted qdev pointer properties be gone
> and replaced by something like link properties.

This is completely unrelated to qdev pointer properties and link
properties.  The properties that use object_property_add_uint*_ptr()
today are not qdev pointer properties and will never be link
properties.  They are just integer properties.

> 
> object_property_add_uintXX_ptr() were introduced as a quick hack,
> when ACPI code generation was moved from Seabios, to avoid more
> code shuffling in device models and adding more boiler plate in
> form of custom setters/getters (the later didn't seem to bother
> us everywhere else where we use object_[class_]property_add() ).
> Then it spread little bit to another places.
> 
> I'd rather get rid of object_property_add_uintXX_ptr() API altogether
> in favor of object_[class_]property_add() like it is used in other places
> to handle intXX properties.
> Adding helpers similar to object_property_add_bool() for intXX
> could reduce boiler plate need for converting current instances of
> _ptr(), and such helpers would also help with reducing boilerplate
> for the rest of instances where object_[class_]property_add()
> currently is used for dealing with integers.

I find object_property_add_bool() terrible.  It requires too much
boilerplate.  I actually have plans to introduce
object*_property_add_bool_ptr() to simplify existing
object_property_add_bool() callers.

I don't love object*_property_add_*_ptr() either.  I consider the
qdev property API better.  But we need a reasonable alternative,
because the qdev API can't be used by non-device objects yet.
I don't think object*_property_add() and
object*_property_add_bool() are reasonable alternatives.

> 
> 
> > Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> > ---
> > Cc: Paolo Bonzini <pbonzini@redhat.com>
> > Cc: "Daniel P. Berrangé" <berrange@redhat.com>
> > Cc: Eduardo Habkost <ehabkost@redhat.com>
> > Cc: qemu-devel@nongnu.org
> > ---
> >  include/qom/object.h       |  8 ++++----
> >  qom/object.c               | 36 +++++++++++++++++++++++-------------
> >  tests/check-qom-proplist.c | 10 ++++++++--
> >  3 files changed, 35 insertions(+), 19 deletions(-)
> > 
> > diff --git a/include/qom/object.h b/include/qom/object.h
> > index d378f13a11..1634294e4f 100644
> > --- a/include/qom/object.h
> > +++ b/include/qom/object.h
> > @@ -1747,7 +1747,7 @@ ObjectProperty *object_property_add_uint8_ptr(Object *obj, const char *name,
> >  
> >  ObjectProperty *object_class_property_add_uint8_ptr(ObjectClass *klass,
> >                                           const char *name,
> > -                                         const uint8_t *v,
> > +                                         ptrdiff_t offset,
> >                                           ObjectPropertyFlags flags);
> >  
> >  /**
> > @@ -1768,7 +1768,7 @@ ObjectProperty *object_property_add_uint16_ptr(Object *obj, const char *name,
> >  
> >  ObjectProperty *object_class_property_add_uint16_ptr(ObjectClass *klass,
> >                                            const char *name,
> > -                                          const uint16_t *v,
> > +                                          ptrdiff_t offset,
> >                                            ObjectPropertyFlags flags);
> >  
> >  /**
> > @@ -1789,7 +1789,7 @@ ObjectProperty *object_property_add_uint32_ptr(Object *obj, const char *name,
> >  
> >  ObjectProperty *object_class_property_add_uint32_ptr(ObjectClass *klass,
> >                                            const char *name,
> > -                                          const uint32_t *v,
> > +                                          ptrdiff_t offset,
> >                                            ObjectPropertyFlags flags);
> >  
> >  /**
> > @@ -1810,7 +1810,7 @@ ObjectProperty *object_property_add_uint64_ptr(Object *obj, const char *name,
> >  
> >  ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass,
> >                                            const char *name,
> > -                                          const uint64_t *v,
> > +                                          ptrdiff_t offset,
> >                                            ObjectPropertyFlags flags);
> >  
> >  /**
> > diff --git a/qom/object.c b/qom/object.c
> > index 17692ed5c3..bb32f5d3ad 100644
> > --- a/qom/object.c
> > +++ b/qom/object.c
> > @@ -2450,13 +2450,22 @@ static char *object_get_type(Object *obj, Error **errp)
> >  }
> >  
> >  typedef struct {
> > -    /* Pointer to property value */
> > -    void *ptr;
> > +    bool is_offset;
> > +    union {
> > +        /* Pointer to property value.  Valid if is_offset=false */
> > +        void *ptr;
> > +        /* Offset in Object struct.  Valid if is_offset=true */
> > +        ptrdiff_t offset;
> > +    };
> >  } PointerProperty;
> >  
> >  static void *pointer_property_get_ptr(Object *obj, PointerProperty *prop)
> >  {
> > -    return prop->ptr;
> > +    if (prop->is_offset) {
> > +        return (void *)obj + prop->offset;
> > +    } else {
> > +        return prop->ptr;
> > +    }
> >  }
> >  
> >  static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
> > @@ -2573,10 +2582,11 @@ object_class_property_add_uint_ptr(ObjectClass *oc, const char *name,
> >                                     ObjectPropertyAccessor getter,
> >                                     ObjectPropertyAccessor setter,
> >                                     ObjectPropertyFlags flags,
> > -                                   void *ptr)
> > +                                   ptrdiff_t offset)
> >  {
> >      PointerProperty *prop = g_new0(PointerProperty, 1);
> > -    prop->ptr = ptr;
> > +    prop->is_offset = true;
> > +    prop->offset = offset;
> >      return object_class_property_add(oc, name, type,
> >                                       (flags & OBJ_PROP_FLAG_READ) ? getter : NULL,
> >                                       (flags & OBJ_PROP_FLAG_WRITE) ? setter : NULL,
> > @@ -2597,13 +2607,13 @@ object_property_add_uint8_ptr(Object *obj, const char *name,
> >  
> >  ObjectProperty *
> >  object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
> > -                                    const uint8_t *v,
> > +                                    ptrdiff_t offset,
> >                                      ObjectPropertyFlags flags)
> >  {
> >      return object_class_property_add_uint_ptr(klass, name, "uint8",
> >                                                property_get_uint8_ptr,
> >                                                property_set_uint8_ptr,
> > -                                              flags, (void *)v);
> > +                                              flags, offset);
> >  }
> >  
> >  ObjectProperty *
> > @@ -2620,13 +2630,13 @@ object_property_add_uint16_ptr(Object *obj, const char *name,
> >  
> >  ObjectProperty *
> >  object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
> > -                                     const uint16_t *v,
> > +                                     ptrdiff_t offset,
> >                                       ObjectPropertyFlags flags)
> >  {
> >      return object_class_property_add_uint_ptr(klass, name, "uint16",
> >                                                property_get_uint16_ptr,
> >                                                property_set_uint16_ptr,
> > -                                              flags, (void *)v);
> > +                                              flags, offset);
> >  }
> >  
> >  ObjectProperty *
> > @@ -2643,13 +2653,13 @@ object_property_add_uint32_ptr(Object *obj, const char *name,
> >  
> >  ObjectProperty *
> >  object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
> > -                                     const uint32_t *v,
> > +                                     ptrdiff_t offset,
> >                                       ObjectPropertyFlags flags)
> >  {
> >      return object_class_property_add_uint_ptr(klass, name, "uint32",
> >                                                property_get_uint32_ptr,
> >                                                property_set_uint32_ptr,
> > -                                              flags, (void *)v);
> > +                                              flags, offset);
> >  }
> >  
> >  ObjectProperty *
> > @@ -2666,13 +2676,13 @@ object_property_add_uint64_ptr(Object *obj, const char *name,
> >  
> >  ObjectProperty *
> >  object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
> > -                                     const uint64_t *v,
> > +                                     ptrdiff_t offset,
> >                                       ObjectPropertyFlags flags)
> >  {
> >      return object_class_property_add_uint_ptr(klass, name, "uint64",
> >                                                property_get_uint64_ptr,
> >                                                property_set_uint64_ptr,
> > -                                              flags, (void *)v);
> > +                                              flags, offset);
> >  }
> >  
> >  typedef struct {
> > diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
> > index 1b76581980..fba30c20b2 100644
> > --- a/tests/check-qom-proplist.c
> > +++ b/tests/check-qom-proplist.c
> > @@ -61,6 +61,7 @@ struct DummyObject {
> >      bool bv;
> >      DummyAnimal av;
> >      char *sv;
> > +    uint8_t u8v;
> >  };
> >  
> >  struct DummyObjectClass {
> > @@ -141,6 +142,9 @@ static void dummy_class_init(ObjectClass *cls, void *data)
> >                                     &dummy_animal_map,
> >                                     dummy_get_av,
> >                                     dummy_set_av);
> > +    object_class_property_add_uint8_ptr(cls, "u8v",
> > +                                        offsetof(DummyObject, u8v),
> > +                                        OBJ_PROP_FLAG_READWRITE);
> >  }
> >  
> >  
> > @@ -385,12 +389,14 @@ static void test_dummy_createlist(void)
> >                     "bv", "yes",
> >                     "sv", "Hiss hiss hiss",
> >                     "av", "platypus",
> > +                   "u8v", "42",
> >                     NULL));
> >  
> >      g_assert(err == NULL);
> >      g_assert_cmpstr(dobj->sv, ==, "Hiss hiss hiss");
> >      g_assert(dobj->bv == true);
> >      g_assert(dobj->av == DUMMY_PLATYPUS);
> > +    g_assert_cmpint(dobj->u8v, ==, 42);
> >  
> >      g_assert(object_resolve_path_component(parent, "dummy0")
> >               == OBJECT(dobj));
> > @@ -531,7 +537,7 @@ static void test_dummy_iterator(void)
> >  {
> >      const char *expected[] = {
> >          "type",                 /* inherited from TYPE_OBJECT */
> > -        "sv", "av",             /* class properties */
> > +        "sv", "av", "u8v",      /* class properties */
> >          "bv"};                  /* instance property */
> >      Object *parent = object_get_objects_root();
> >      DummyObject *dobj = DUMMY_OBJECT(
> > @@ -552,7 +558,7 @@ static void test_dummy_iterator(void)
> >  
> >  static void test_dummy_class_iterator(void)
> >  {
> > -    const char *expected[] = { "type", "av", "sv" };
> > +    const char *expected[] = { "type", "av", "sv", "u8v" };
> >      ObjectPropertyIterator iter;
> >      ObjectClass *klass = object_class_by_name(TYPE_DUMMY);
> >  
>
Markus Armbruster Oct. 22, 2020, 5:06 a.m. UTC | #5
Eduardo Habkost <ehabkost@redhat.com> writes:

> On Wed, Oct 21, 2020 at 02:24:08PM +0200, Igor Mammedov wrote:
>> On Fri,  9 Oct 2020 12:01:13 -0400
>> Eduardo Habkost <ehabkost@redhat.com> wrote:
>> 
>> > The existing object_class_property_add_uint*_ptr() functions are
>> > not very useful, because they need a pointer to the property
>> > value, which can't really be provided before the object is
>> > created.
>> > 
>> > Replace the pointer parameter in those functions with a
>> > `ptrdiff_t offset` parameter.
>> > 
>> > Include a uint8 class property in check-qom-proplist unit tests,
>> > to ensure the feature is working.
>> 
>> 
>> Not sure I like approach, it's reinventing qdev pointer properties in QOM form.
>
> Yes, and that's on purpose.  If we want to eventually merge the
> two competing APIs into a single one, we need to make them
> converge.
>
>> I had an impression that Paolo wanted qdev pointer properties be gone
>> and replaced by something like link properties.
>
> This is completely unrelated to qdev pointer properties and link
> properties.  The properties that use object_property_add_uint*_ptr()
> today are not qdev pointer properties and will never be link
> properties.  They are just integer properties.
>
>> 
>> object_property_add_uintXX_ptr() were introduced as a quick hack,
>> when ACPI code generation was moved from Seabios, to avoid more
>> code shuffling in device models and adding more boiler plate in
>> form of custom setters/getters (the later didn't seem to bother
>> us everywhere else where we use object_[class_]property_add() ).
>> Then it spread little bit to another places.
>> 
>> I'd rather get rid of object_property_add_uintXX_ptr() API altogether
>> in favor of object_[class_]property_add() like it is used in other places
>> to handle intXX properties.
>> Adding helpers similar to object_property_add_bool() for intXX
>> could reduce boiler plate need for converting current instances of
>> _ptr(), and such helpers would also help with reducing boilerplate
>> for the rest of instances where object_[class_]property_add()
>> currently is used for dealing with integers.
>
> I find object_property_add_bool() terrible.  It requires too much
> boilerplate.  I actually have plans to introduce
> object*_property_add_bool_ptr() to simplify existing
> object_property_add_bool() callers.
>
> I don't love object*_property_add_*_ptr() either.  I consider the
> qdev property API better.  But we need a reasonable alternative,
> because the qdev API can't be used by non-device objects yet.

Emphasis on *yet*: we should be able to lift it up into QOM, shouldn't
we?

> I don't think object*_property_add() and
> object*_property_add_bool() are reasonable alternatives.
Eduardo Habkost Oct. 22, 2020, 9:34 p.m. UTC | #6
On Thu, Oct 22, 2020 at 07:06:58AM +0200, Markus Armbruster wrote:
[...]
> > I don't love object*_property_add_*_ptr() either.  I consider the
> > qdev property API better.  But we need a reasonable alternative,
> > because the qdev API can't be used by non-device objects yet.
> 
> Emphasis on *yet*: we should be able to lift it up into QOM, shouldn't
> we?

We should, yes.  My plan is to make object_property_*_ptr() and
PropertyInfo code converge until they look exactly the same and
become a single API.
Igor Mammedov Oct. 23, 2020, 3:33 p.m. UTC | #7
On Wed, 21 Oct 2020 09:30:41 -0400
Eduardo Habkost <ehabkost@redhat.com> wrote:

> On Wed, Oct 21, 2020 at 02:24:08PM +0200, Igor Mammedov wrote:
> > On Fri,  9 Oct 2020 12:01:13 -0400
> > Eduardo Habkost <ehabkost@redhat.com> wrote:
> >   
> > > The existing object_class_property_add_uint*_ptr() functions are
> > > not very useful, because they need a pointer to the property
> > > value, which can't really be provided before the object is
> > > created.
> > > 
> > > Replace the pointer parameter in those functions with a
> > > `ptrdiff_t offset` parameter.
> > > 
> > > Include a uint8 class property in check-qom-proplist unit tests,
> > > to ensure the feature is working.  
> > 
> > 
> > Not sure I like approach, it's reinventing qdev pointer properties in QOM form.  
> 
> Yes, and that's on purpose.  If we want to eventually merge the
> two competing APIs into a single one, we need to make them
> converge.
> 
> > I had an impression that Paolo wanted qdev pointer properties be gone
> > and replaced by something like link properties.  
> 
> This is completely unrelated to qdev pointer properties and link
> properties.  The properties that use object_property_add_uint*_ptr()
> today are not qdev pointer properties and will never be link
> properties.  They are just integer properties.

right, _prt confused me for a while.

> 
> > 
> > object_property_add_uintXX_ptr() were introduced as a quick hack,
> > when ACPI code generation was moved from Seabios, to avoid more
> > code shuffling in device models and adding more boiler plate in
> > form of custom setters/getters (the later didn't seem to bother
> > us everywhere else where we use object_[class_]property_add() ).
> > Then it spread little bit to another places.
> > 
> > I'd rather get rid of object_property_add_uintXX_ptr() API altogether
> > in favor of object_[class_]property_add() like it is used in other places
> > to handle intXX properties.
> > Adding helpers similar to object_property_add_bool() for intXX
> > could reduce boiler plate need for converting current instances of
> > _ptr(), and such helpers would also help with reducing boilerplate
> > for the rest of instances where object_[class_]property_add()
> > currently is used for dealing with integers.  
> 
> I find object_property_add_bool() terrible.  It requires too much
> boilerplate.  I actually have plans to introduce
> object*_property_add_bool_ptr() to simplify existing
> object_property_add_bool() callers.

But boiler-plate related to QOM properties set/get methods was considered
tolerable back then.
It was a long time ago, so I don't recall why we decided to abandon
qdev properties API.

> I don't love object*_property_add_*_ptr() either.  I consider the
> qdev property API better.  But we need a reasonable alternative,
> because the qdev API can't be used by non-device objects yet.
> I don't think object*_property_add() and
> object*_property_add_bool() are reasonable alternatives.

I also like old qdev API as it can be introspected (it's just data at
class level), very concise when used and has default values.

Instead of duplicating all that pointer arithmetic from qdev properties
in QOM API, it could be better to fix qdev properties so that they
would work for Object as well.
At least all that thrown away type safety would stay constrained/hidden
inside of qdev property macros, instead of being opencoded (offsets) all
over the place.

How hard it would be make qdev properties to work with Object and what
makes you duplicate ugly part of it in QOM instead of making them to
handle Object strait away?
That would also result in huge removal of boiler plate of current QOM
properties.

That should suit your goal to make (most) properties introspectable
and statically described.

[...]
Eduardo Habkost Oct. 27, 2020, 10:18 p.m. UTC | #8
On Fri, Oct 23, 2020 at 05:33:14PM +0200, Igor Mammedov wrote:
> On Wed, 21 Oct 2020 09:30:41 -0400
> Eduardo Habkost <ehabkost@redhat.com> wrote:
[...]
> > I don't love object*_property_add_*_ptr() either.  I consider the
> > qdev property API better.  But we need a reasonable alternative,
> > because the qdev API can't be used by non-device objects yet.
> > I don't think object*_property_add() and
> > object*_property_add_bool() are reasonable alternatives.
> 
> I also like old qdev API as it can be introspected (it's just data at
> class level), very concise when used and has default values.
> 
> Instead of duplicating all that pointer arithmetic from qdev properties
> in QOM API, it could be better to fix qdev properties so that they
> would work for Object as well.
> At least all that thrown away type safety would stay constrained/hidden
> inside of qdev property macros, instead of being opencoded (offsets) all
> over the place.
> 
> How hard it would be make qdev properties to work with Object and what
> makes you duplicate ugly part of it in QOM instead of making them to
> handle Object strait away?

It is doable, but lots of work.  I'm working on this right now.

> That would also result in huge removal of boiler plate of current QOM
> properties.

Yep.

> 
> That should suit your goal to make (most) properties introspectable
> and statically described.

That's correct.  I just don't want a huge qdev refactor to be a
reason to delay important work in other areas.
Paolo Bonzini Oct. 28, 2020, 3:22 p.m. UTC | #9
On 23/10/20 17:33, Igor Mammedov wrote:
> On Wed, 21 Oct 2020 09:30:41 -0400
> Eduardo Habkost <ehabkost@redhat.com> wrote:
> 
>> On Wed, Oct 21, 2020 at 02:24:08PM +0200, Igor Mammedov wrote:
>>> On Fri,  9 Oct 2020 12:01:13 -0400
>>> Eduardo Habkost <ehabkost@redhat.com> wrote:
>>>   
>>>> The existing object_class_property_add_uint*_ptr() functions are
>>>> not very useful, because they need a pointer to the property
>>>> value, which can't really be provided before the object is
>>>> created.
>>>>
>>>> Replace the pointer parameter in those functions with a
>>>> `ptrdiff_t offset` parameter.
>>>>
>>>> Include a uint8 class property in check-qom-proplist unit tests,
>>>> to ensure the feature is working.  
>>>
>>>
>>> Not sure I like approach, it's reinventing qdev pointer properties in QOM form.  
>>
>> Yes, and that's on purpose.  If we want to eventually merge the
>> two competing APIs into a single one, we need to make them
>> converge.
>>
>>> I had an impression that Paolo wanted qdev pointer properties be gone
>>> and replaced by something like link properties.  
>>
>> This is completely unrelated to qdev pointer properties and link
>> properties.  The properties that use object_property_add_uint*_ptr()
>> today are not qdev pointer properties and will never be link
>> properties.  They are just integer properties.

I think this series a step in the right direction, but please take more
"inspiration" from link properties, which are done right.  In
particular, properties should have an optional check function and be
read-only unless the check function is there.

You can make the check function take an uint64_t for simplicity, so that
all the check functions for uint properties have the same prototype.
For example a single "property_check_uint_allow" function can allow
setting the property (which is almost always wrong, but an easy cop out
for this series).

Paolo
Igor Mammedov Oct. 28, 2020, 3:53 p.m. UTC | #10
On Wed, 28 Oct 2020 16:22:40 +0100
Paolo Bonzini <pbonzini@redhat.com> wrote:

> On 23/10/20 17:33, Igor Mammedov wrote:
> > On Wed, 21 Oct 2020 09:30:41 -0400
> > Eduardo Habkost <ehabkost@redhat.com> wrote:
> >   
> >> On Wed, Oct 21, 2020 at 02:24:08PM +0200, Igor Mammedov wrote:  
> >>> On Fri,  9 Oct 2020 12:01:13 -0400
> >>> Eduardo Habkost <ehabkost@redhat.com> wrote:
> >>>     
> >>>> The existing object_class_property_add_uint*_ptr() functions are
> >>>> not very useful, because they need a pointer to the property
> >>>> value, which can't really be provided before the object is
> >>>> created.
> >>>>
> >>>> Replace the pointer parameter in those functions with a
> >>>> `ptrdiff_t offset` parameter.
> >>>>
> >>>> Include a uint8 class property in check-qom-proplist unit tests,
> >>>> to ensure the feature is working.    
> >>>
> >>>
> >>> Not sure I like approach, it's reinventing qdev pointer properties in QOM form.    
> >>
> >> Yes, and that's on purpose.  If we want to eventually merge the
> >> two competing APIs into a single one, we need to make them
> >> converge.
> >>  
> >>> I had an impression that Paolo wanted qdev pointer properties be gone
> >>> and replaced by something like link properties.    
> >>
> >> This is completely unrelated to qdev pointer properties and link
> >> properties.  The properties that use object_property_add_uint*_ptr()
> >> today are not qdev pointer properties and will never be link
> >> properties.  They are just integer properties.  
> 
> I think this series a step in the right direction, but please take more
> "inspiration" from link properties, which are done right.  In
> particular, properties should have an optional check function and be
> read-only unless the check function is there.

object_class_property_add_uint*_ptr() is similar to what we have in QDEV
properties already implemented. But that is all hidden behind macro
magic, so users aren't using it directly.

But what I dislike the most is adding _class_ variants of those with
offsets exposed to users call site without any type checking.
It might be easier and safer to make current QDEV properties to work
with Object in one go, instead of duplication small parts of it in
object_foo() API.
But then I haven't actually tried so ...


> You can make the check function take an uint64_t for simplicity, so that
> all the check functions for uint properties have the same prototype.
> For example a single "property_check_uint_allow" function can allow
> setting the property (which is almost always wrong, but an easy cop out
> for this series).
> 
> Paolo
>
Eduardo Habkost Oct. 29, 2020, 12:56 p.m. UTC | #11
On Wed, Oct 28, 2020 at 04:22:40PM +0100, Paolo Bonzini wrote:
> On 23/10/20 17:33, Igor Mammedov wrote:
> > On Wed, 21 Oct 2020 09:30:41 -0400
> > Eduardo Habkost <ehabkost@redhat.com> wrote:
> > 
> >> On Wed, Oct 21, 2020 at 02:24:08PM +0200, Igor Mammedov wrote:
> >>> On Fri,  9 Oct 2020 12:01:13 -0400
> >>> Eduardo Habkost <ehabkost@redhat.com> wrote:
> >>>   
> >>>> The existing object_class_property_add_uint*_ptr() functions are
> >>>> not very useful, because they need a pointer to the property
> >>>> value, which can't really be provided before the object is
> >>>> created.
> >>>>
> >>>> Replace the pointer parameter in those functions with a
> >>>> `ptrdiff_t offset` parameter.
> >>>>
> >>>> Include a uint8 class property in check-qom-proplist unit tests,
> >>>> to ensure the feature is working.  
> >>>
> >>>
> >>> Not sure I like approach, it's reinventing qdev pointer properties in QOM form.  
> >>
> >> Yes, and that's on purpose.  If we want to eventually merge the
> >> two competing APIs into a single one, we need to make them
> >> converge.
> >>
> >>> I had an impression that Paolo wanted qdev pointer properties be gone
> >>> and replaced by something like link properties.  
> >>
> >> This is completely unrelated to qdev pointer properties and link
> >> properties.  The properties that use object_property_add_uint*_ptr()
> >> today are not qdev pointer properties and will never be link
> >> properties.  They are just integer properties.
> 
> I think this series a step in the right direction, but please take more
> "inspiration" from link properties, which are done right.  In
> particular, properties should have an optional check function and be
> read-only unless the check function is there.
> 
> You can make the check function take an uint64_t for simplicity, so that
> all the check functions for uint properties have the same prototype.
> For example a single "property_check_uint_allow" function can allow
> setting the property (which is almost always wrong, but an easy cop out
> for this series).

A property check callback that needs the property value is a more
complex use case, and would require too much property-type-specific
boilerplate today.  I plan to address it, but not right now.

In my next series that makes static properties usable by any QOM
object, I will add a separate "allow_set" callback to the
internal QOM property API, which will not take the property value
as argument.  This would be enough for the dev->realized checks
that are currently in qdev.

Interestingly, there is only one link property check callback
function in the QEMU tree that actually cares about the property
value: isa_ipmi_bmc_check().  All other cases either don't care
about the property value at all (qdev_prop_allow_set_link_before_realize(),
object_property_allow_set_link()), or are being misused for
something other than property checking (xlnx_dp_set_dpdma()).
Igor Mammedov Oct. 29, 2020, 1:37 p.m. UTC | #12
On Thu, 29 Oct 2020 08:56:34 -0400
Eduardo Habkost <ehabkost@redhat.com> wrote:

> On Wed, Oct 28, 2020 at 04:22:40PM +0100, Paolo Bonzini wrote:
> > On 23/10/20 17:33, Igor Mammedov wrote:  
> > > On Wed, 21 Oct 2020 09:30:41 -0400
> > > Eduardo Habkost <ehabkost@redhat.com> wrote:
> > >   
> > >> On Wed, Oct 21, 2020 at 02:24:08PM +0200, Igor Mammedov wrote:  
> > >>> On Fri,  9 Oct 2020 12:01:13 -0400
> > >>> Eduardo Habkost <ehabkost@redhat.com> wrote:
> > >>>     
> > >>>> The existing object_class_property_add_uint*_ptr() functions are
> > >>>> not very useful, because they need a pointer to the property
> > >>>> value, which can't really be provided before the object is
> > >>>> created.
> > >>>>
> > >>>> Replace the pointer parameter in those functions with a
> > >>>> `ptrdiff_t offset` parameter.
> > >>>>
> > >>>> Include a uint8 class property in check-qom-proplist unit tests,
> > >>>> to ensure the feature is working.    
> > >>>
> > >>>
> > >>> Not sure I like approach, it's reinventing qdev pointer properties in QOM form.    
> > >>
> > >> Yes, and that's on purpose.  If we want to eventually merge the
> > >> two competing APIs into a single one, we need to make them
> > >> converge.
> > >>  
> > >>> I had an impression that Paolo wanted qdev pointer properties be gone
> > >>> and replaced by something like link properties.    
> > >>
> > >> This is completely unrelated to qdev pointer properties and link
> > >> properties.  The properties that use object_property_add_uint*_ptr()
> > >> today are not qdev pointer properties and will never be link
> > >> properties.  They are just integer properties.  
> > 
> > I think this series a step in the right direction, but please take more
> > "inspiration" from link properties, which are done right.  In
> > particular, properties should have an optional check function and be
> > read-only unless the check function is there.
> > 
> > You can make the check function take an uint64_t for simplicity, so that
> > all the check functions for uint properties have the same prototype.
> > For example a single "property_check_uint_allow" function can allow
> > setting the property (which is almost always wrong, but an easy cop out
> > for this series).  
> 
> A property check callback that needs the property value is a more
> complex use case, and would require too much property-type-specific
> boilerplate today.  I plan to address it, but not right now.
sounds good to me,
as long as user don't have deal with offsets directly and macro does
its type check thing.


> In my next series that makes static properties usable by any QOM
> object, I will add a separate "allow_set" callback to the
> internal QOM property API, which will not take the property value
> as argument.  This would be enough for the dev->realized checks
> that are currently in qdev.
> 
> Interestingly, there is only one link property check callback
> function in the QEMU tree that actually cares about the property
> value: isa_ipmi_bmc_check().  All other cases either don't care
> about the property value at all (qdev_prop_allow_set_link_before_realize(),
> object_property_allow_set_link()), or are being misused for
> something other than property checking (xlnx_dp_set_dpdma()).
>
diff mbox series

Patch

diff --git a/include/qom/object.h b/include/qom/object.h
index d378f13a11..1634294e4f 100644
--- a/include/qom/object.h
+++ b/include/qom/object.h
@@ -1747,7 +1747,7 @@  ObjectProperty *object_property_add_uint8_ptr(Object *obj, const char *name,
 
 ObjectProperty *object_class_property_add_uint8_ptr(ObjectClass *klass,
                                          const char *name,
-                                         const uint8_t *v,
+                                         ptrdiff_t offset,
                                          ObjectPropertyFlags flags);
 
 /**
@@ -1768,7 +1768,7 @@  ObjectProperty *object_property_add_uint16_ptr(Object *obj, const char *name,
 
 ObjectProperty *object_class_property_add_uint16_ptr(ObjectClass *klass,
                                           const char *name,
-                                          const uint16_t *v,
+                                          ptrdiff_t offset,
                                           ObjectPropertyFlags flags);
 
 /**
@@ -1789,7 +1789,7 @@  ObjectProperty *object_property_add_uint32_ptr(Object *obj, const char *name,
 
 ObjectProperty *object_class_property_add_uint32_ptr(ObjectClass *klass,
                                           const char *name,
-                                          const uint32_t *v,
+                                          ptrdiff_t offset,
                                           ObjectPropertyFlags flags);
 
 /**
@@ -1810,7 +1810,7 @@  ObjectProperty *object_property_add_uint64_ptr(Object *obj, const char *name,
 
 ObjectProperty *object_class_property_add_uint64_ptr(ObjectClass *klass,
                                           const char *name,
-                                          const uint64_t *v,
+                                          ptrdiff_t offset,
                                           ObjectPropertyFlags flags);
 
 /**
diff --git a/qom/object.c b/qom/object.c
index 17692ed5c3..bb32f5d3ad 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -2450,13 +2450,22 @@  static char *object_get_type(Object *obj, Error **errp)
 }
 
 typedef struct {
-    /* Pointer to property value */
-    void *ptr;
+    bool is_offset;
+    union {
+        /* Pointer to property value.  Valid if is_offset=false */
+        void *ptr;
+        /* Offset in Object struct.  Valid if is_offset=true */
+        ptrdiff_t offset;
+    };
 } PointerProperty;
 
 static void *pointer_property_get_ptr(Object *obj, PointerProperty *prop)
 {
-    return prop->ptr;
+    if (prop->is_offset) {
+        return (void *)obj + prop->offset;
+    } else {
+        return prop->ptr;
+    }
 }
 
 static void property_get_uint8_ptr(Object *obj, Visitor *v, const char *name,
@@ -2573,10 +2582,11 @@  object_class_property_add_uint_ptr(ObjectClass *oc, const char *name,
                                    ObjectPropertyAccessor getter,
                                    ObjectPropertyAccessor setter,
                                    ObjectPropertyFlags flags,
-                                   void *ptr)
+                                   ptrdiff_t offset)
 {
     PointerProperty *prop = g_new0(PointerProperty, 1);
-    prop->ptr = ptr;
+    prop->is_offset = true;
+    prop->offset = offset;
     return object_class_property_add(oc, name, type,
                                      (flags & OBJ_PROP_FLAG_READ) ? getter : NULL,
                                      (flags & OBJ_PROP_FLAG_WRITE) ? setter : NULL,
@@ -2597,13 +2607,13 @@  object_property_add_uint8_ptr(Object *obj, const char *name,
 
 ObjectProperty *
 object_class_property_add_uint8_ptr(ObjectClass *klass, const char *name,
-                                    const uint8_t *v,
+                                    ptrdiff_t offset,
                                     ObjectPropertyFlags flags)
 {
     return object_class_property_add_uint_ptr(klass, name, "uint8",
                                               property_get_uint8_ptr,
                                               property_set_uint8_ptr,
-                                              flags, (void *)v);
+                                              flags, offset);
 }
 
 ObjectProperty *
@@ -2620,13 +2630,13 @@  object_property_add_uint16_ptr(Object *obj, const char *name,
 
 ObjectProperty *
 object_class_property_add_uint16_ptr(ObjectClass *klass, const char *name,
-                                     const uint16_t *v,
+                                     ptrdiff_t offset,
                                      ObjectPropertyFlags flags)
 {
     return object_class_property_add_uint_ptr(klass, name, "uint16",
                                               property_get_uint16_ptr,
                                               property_set_uint16_ptr,
-                                              flags, (void *)v);
+                                              flags, offset);
 }
 
 ObjectProperty *
@@ -2643,13 +2653,13 @@  object_property_add_uint32_ptr(Object *obj, const char *name,
 
 ObjectProperty *
 object_class_property_add_uint32_ptr(ObjectClass *klass, const char *name,
-                                     const uint32_t *v,
+                                     ptrdiff_t offset,
                                      ObjectPropertyFlags flags)
 {
     return object_class_property_add_uint_ptr(klass, name, "uint32",
                                               property_get_uint32_ptr,
                                               property_set_uint32_ptr,
-                                              flags, (void *)v);
+                                              flags, offset);
 }
 
 ObjectProperty *
@@ -2666,13 +2676,13 @@  object_property_add_uint64_ptr(Object *obj, const char *name,
 
 ObjectProperty *
 object_class_property_add_uint64_ptr(ObjectClass *klass, const char *name,
-                                     const uint64_t *v,
+                                     ptrdiff_t offset,
                                      ObjectPropertyFlags flags)
 {
     return object_class_property_add_uint_ptr(klass, name, "uint64",
                                               property_get_uint64_ptr,
                                               property_set_uint64_ptr,
-                                              flags, (void *)v);
+                                              flags, offset);
 }
 
 typedef struct {
diff --git a/tests/check-qom-proplist.c b/tests/check-qom-proplist.c
index 1b76581980..fba30c20b2 100644
--- a/tests/check-qom-proplist.c
+++ b/tests/check-qom-proplist.c
@@ -61,6 +61,7 @@  struct DummyObject {
     bool bv;
     DummyAnimal av;
     char *sv;
+    uint8_t u8v;
 };
 
 struct DummyObjectClass {
@@ -141,6 +142,9 @@  static void dummy_class_init(ObjectClass *cls, void *data)
                                    &dummy_animal_map,
                                    dummy_get_av,
                                    dummy_set_av);
+    object_class_property_add_uint8_ptr(cls, "u8v",
+                                        offsetof(DummyObject, u8v),
+                                        OBJ_PROP_FLAG_READWRITE);
 }
 
 
@@ -385,12 +389,14 @@  static void test_dummy_createlist(void)
                    "bv", "yes",
                    "sv", "Hiss hiss hiss",
                    "av", "platypus",
+                   "u8v", "42",
                    NULL));
 
     g_assert(err == NULL);
     g_assert_cmpstr(dobj->sv, ==, "Hiss hiss hiss");
     g_assert(dobj->bv == true);
     g_assert(dobj->av == DUMMY_PLATYPUS);
+    g_assert_cmpint(dobj->u8v, ==, 42);
 
     g_assert(object_resolve_path_component(parent, "dummy0")
              == OBJECT(dobj));
@@ -531,7 +537,7 @@  static void test_dummy_iterator(void)
 {
     const char *expected[] = {
         "type",                 /* inherited from TYPE_OBJECT */
-        "sv", "av",             /* class properties */
+        "sv", "av", "u8v",      /* class properties */
         "bv"};                  /* instance property */
     Object *parent = object_get_objects_root();
     DummyObject *dobj = DUMMY_OBJECT(
@@ -552,7 +558,7 @@  static void test_dummy_iterator(void)
 
 static void test_dummy_class_iterator(void)
 {
-    const char *expected[] = { "type", "av", "sv" };
+    const char *expected[] = { "type", "av", "sv", "u8v" };
     ObjectPropertyIterator iter;
     ObjectClass *klass = object_class_by_name(TYPE_DUMMY);