On Wed, Sep 11, 2019 at 06:10:28PM +0100, Dr. David Alan Gilbert wrote:
> * Daniel P. Berrangé (berra...@redhat.com) wrote:
> > On Wed, Sep 11, 2019 at 06:04:23PM +0100, Dr. David Alan Gilbert wrote:
> > > * Daniel P. Berrangé (berra...@redhat.com) wrote:
> > > > On Wed, Sep 11, 2019 at 05:42:00PM +0100, Dr. David Alan Gilbert (git) 
> > > > wrote:
> > > > > From: "Dr. David Alan Gilbert" <dgilb...@redhat.com>
> > > > > 
> > > > > RCU_READ_LOCK_AUTO takes the rcu_read_lock  and then uses glib's
> > > > > g_auto infrastrcture (and thus whatever the compilers hooks are) to
> > > > > release it on all exits of the block.
> > > > > 
> > > > > Note this macro has a variable declaration in, and hence is not in
> > > > > a while loop.
> > > > > 
> > > > > Signed-off-by: Dr. David Alan Gilbert <dgilb...@redhat.com>
> > > > > ---
> > > > >  include/qemu/rcu.h | 12 ++++++++++++
> > > > >  1 file changed, 12 insertions(+)
> > > > > 
> > > > > diff --git a/include/qemu/rcu.h b/include/qemu/rcu.h
> > > > > index 22876d1428..6a25b27d28 100644
> > > > > --- a/include/qemu/rcu.h
> > > > > +++ b/include/qemu/rcu.h
> > > > > @@ -154,6 +154,18 @@ extern void call_rcu1(struct rcu_head *head, 
> > > > > RCUCBFunc *func);
> > > > >        }),                                                            
> > > > >     \
> > > > >        (RCUCBFunc *)g_free);
> > > > >  
> > > > > +typedef char rcu_read_auto_t;
> > > > > +static inline void rcu_read_auto_unlock(rcu_read_auto_t *r)
> > > > > +{
> > > > > +  rcu_read_unlock();
> > > > > +}
> > > > > +
> > > > > +G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(rcu_read_auto_t, 
> > > > > rcu_read_auto_unlock)
> > > > >
> > > > > +#define RCU_READ_LOCK_AUTO g_auto(rcu_read_auto_t) \
> > > > > +    _rcu_read_auto = 'x'; \
> > > > > +    rcu_read_lock();
> > > > > +
> > > > 
> > > > Functionally this works, but my gut feeling would be to follow
> > > > the design of GMutexLocker as-is:
> > > > 
> > > >   
> > > > https://developer.gnome.org/glib/stable/glib-Threads.html#g-mutex-locker-new
> > > > 
> > > > so you get a use pattern of
> > > > 
> > > >   g_autoptr(rcu_read_locker) locker = rcu_read_locker_new();
> > > > 
> > > > This makes it explicit that the code is creating a variable here, which
> > > > in turns means it is clear to force unlock early with
> > > > 
> > > >   g_clear_pointer(&locker, rcu_read_locker_free)
> > > 
> > > The difference compared to the g-mutex-locker is that I don't have
> > > another object to use as my pointer; that uses the address of the GMutex
> > > as the dummy pointer value.  I did try an experiment with g_autoptr
> > > and found that it did need to return a non-NULL value for it to work,
> > > which then lead me to think what value to use - while it seems to work
> > > if I return (void *)1 it makes me nervous.
> > 
> > Yeah, '(void*)1' would have been what I'd pick. The only thing that the
> > value is used for is to pass to the rcu_read_locker_free() function
> > which ignores it, which seems safe enough.
> 
> glib seems to be at least checking it; if you pass NULL the free'r
> doesn't get called; so it worries me that we'd be relying on the current
> definition.

This NULL check is part of the API semantics defined for
G_DEFINE_AUTO_CLEANUO_FREE_FUNC. It lets you define
what the "empty" value is, typically 'NULL', but
in fact you don't need to use a pointer type at all. You
can use an 'int', for example, and declare that '-1'
is your "empty" value:

  
https://developer.gnome.org/glib/stable/glib-Miscellaneous-Macros.html#G-DEFINE-AUTO-CLEANUP-FREE-FUNC:CAPS


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|

Reply via email to