[PATCH] drm/gem: support BO freeing without dev->struct_mutex
Daniel Vetter
daniel at ffwll.ch
Wed May 4 10:26:25 UTC 2016
On Tue, May 03, 2016 at 11:59:19AM -0400, Alex Deucher wrote:
> On Mon, May 2, 2016 at 4:40 AM, Daniel Vetter <daniel.vetter at ffwll.ch> wrote:
> > Finally all the core gem and a lot of drivers are entirely free of
> > dev->struct_mutex depencies, and we can start to have an entirely
> > lockless unref path.
> >
> > To make sure that no one who touches the core code accidentally breaks
> > existing drivers which still require dev->struct_mutex I've made the
> > might_lock check unconditional.
> >
> > While at it de-inline the ref/unref functions, they've become a bit
> > too big.
> >
> > v2: Make it not leak like a sieve.
> >
> > v3: Review from Lucas:
> > - drop != NULL in pointer checks.
> > - fixup copypasted kerneldoc to actually match the functions.
> >
> > v4:
> > Add __drm_gem_object_unreference as a fastpath helper for drivers who
> > abolished dev->struct_mutex, requested by Chris.
> >
> > v5: Fix silly mistake in drm_gem_object_unreference_unlocked caught by
> > intel-gfx CI - I checked for gem_free_object instead of
> > gem_free_object_unlocked ...
> >
> > Cc: Chris Wilson <chris at chris-wilson.co.uk>
> > Cc: Alex Deucher <alexdeucher at gmail.com>
> > Cc: Lucas Stach <l.stach at pengutronix.de>
> > Reviewed-by: Lucas Stach <l.stach at pengutronix.de> (v3)
> > Reviewed-by: Chris Wilson <chris at chris-wilson.co.uk> (v4)
> > Signed-off-by: Daniel Vetter <daniel.vetter at intel.com>
>
> Reviewed-by: Alex Deucher <alexander.deucher at amd.com>
Thanks for the review. I merged this one plus the driver patches acked by
maintainers to drm-misc.
-Daniel
>
> > ---
> > drivers/gpu/drm/drm_gem.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++-
> > include/drm/drmP.h | 15 ++++++++++---
> > include/drm/drm_gem.h | 48 +++++++++++++----------------------------
> > 3 files changed, 80 insertions(+), 37 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
> > index 25dac31eef37..973eb8805ce0 100644
> > --- a/drivers/gpu/drm/drm_gem.c
> > +++ b/drivers/gpu/drm/drm_gem.c
> > @@ -806,12 +806,64 @@ drm_gem_object_free(struct kref *kref)
> >
> > WARN_ON(!mutex_is_locked(&dev->struct_mutex));
> >
> > - if (dev->driver->gem_free_object != NULL)
> > + if (dev->driver->gem_free_object_unlocked)
> > + dev->driver->gem_free_object_unlocked(obj);
> > + else if (dev->driver->gem_free_object)
> > dev->driver->gem_free_object(obj);
> > }
> > EXPORT_SYMBOL(drm_gem_object_free);
> >
> > /**
> > + * drm_gem_object_unreference_unlocked - release a GEM BO reference
> > + * @obj: GEM buffer object
> > + *
> > + * This releases a reference to @obj. Callers must not hold the
> > + * dev->struct_mutex lock when calling this function.
> > + *
> > + * See also __drm_gem_object_unreference().
> > + */
> > +void
> > +drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
> > +{
> > + struct drm_device *dev;
> > +
> > + if (!obj)
> > + return;
> > +
> > + dev = obj->dev;
> > + might_lock(&dev->struct_mutex);
> > +
> > + if (dev->driver->gem_free_object_unlocked)
> > + kref_put(&obj->refcount, drm_gem_object_free);
> > + else if (kref_put_mutex(&obj->refcount, drm_gem_object_free,
> > + &dev->struct_mutex))
> > + mutex_unlock(&dev->struct_mutex);
> > +}
> > +EXPORT_SYMBOL(drm_gem_object_unreference_unlocked);
> > +
> > +/**
> > + * drm_gem_object_unreference - release a GEM BO reference
> > + * @obj: GEM buffer object
> > + *
> > + * This releases a reference to @obj. Callers must hold the dev->struct_mutex
> > + * lock when calling this function, even when the driver doesn't use
> > + * dev->struct_mutex for anything.
> > + *
> > + * For drivers not encumbered with legacy locking use
> > + * drm_gem_object_unreference_unlocked() instead.
> > + */
> > +void
> > +drm_gem_object_unreference(struct drm_gem_object *obj)
> > +{
> > + if (obj) {
> > + WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
> > +
> > + kref_put(&obj->refcount, drm_gem_object_free);
> > + }
> > +}
> > +EXPORT_SYMBOL(drm_gem_object_unreference);
> > +
> > +/**
> > * drm_gem_vm_open - vma->ops->open implementation for GEM
> > * @vma: VM area structure
> > *
> > diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> > index c81dd2250fc6..bd7b262d7af0 100644
> > --- a/include/drm/drmP.h
> > +++ b/include/drm/drmP.h
> > @@ -580,12 +580,21 @@ struct drm_driver {
> > void (*debugfs_cleanup)(struct drm_minor *minor);
> >
> > /**
> > - * Driver-specific constructor for drm_gem_objects, to set up
> > - * obj->driver_private.
> > + * @gem_free_object: deconstructor for drm_gem_objects
> > *
> > - * Returns 0 on success.
> > + * This is deprecated and should not be used by new drivers. Use
> > + * @gem_free_object_unlocked instead.
> > */
> > void (*gem_free_object) (struct drm_gem_object *obj);
> > +
> > + /**
> > + * @gem_free_object_unlocked: deconstructor for drm_gem_objects
> > + *
> > + * This is for drivers which are not encumbered with dev->struct_mutex
> > + * legacy locking schemes. Use this hook instead of @gem_free_object.
> > + */
> > + void (*gem_free_object_unlocked) (struct drm_gem_object *obj);
> > +
> > int (*gem_open_object) (struct drm_gem_object *, struct drm_file *);
> > void (*gem_close_object) (struct drm_gem_object *, struct drm_file *);
> >
> > diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h
> > index 0b3e11ab8757..408d6c47d98b 100644
> > --- a/include/drm/drm_gem.h
> > +++ b/include/drm/drm_gem.h
> > @@ -200,47 +200,29 @@ drm_gem_object_reference(struct drm_gem_object *obj)
> > }
> >
> > /**
> > - * drm_gem_object_unreference - release a GEM BO reference
> > + * __drm_gem_object_unreference - raw function to release a GEM BO reference
> > * @obj: GEM buffer object
> > *
> > - * This releases a reference to @obj. Callers must hold the dev->struct_mutex
> > - * lock when calling this function, even when the driver doesn't use
> > - * dev->struct_mutex for anything.
> > + * This function is meant to be used by drivers which are not encumbered with
> > + * dev->struct_mutex legacy locking and which are using the
> > + * gem_free_object_unlocked callback. It avoids all the locking checks and
> > + * locking overhead of drm_gem_object_unreference() and
> > + * drm_gem_object_unreference_unlocked().
> > *
> > - * For drivers not encumbered with legacy locking use
> > - * drm_gem_object_unreference_unlocked() instead.
> > + * Drivers should never call this directly in their code. Instead they should
> > + * wrap it up into a driver_gem_object_unreference(struct driver_gem_object
> > + * *obj) wrapper function, and use that. Shared code should never call this, to
> > + * avoid breaking drivers by accident which still depend upon dev->struct_mutex
> > + * locking.
> > */
> > static inline void
> > -drm_gem_object_unreference(struct drm_gem_object *obj)
> > +__drm_gem_object_unreference(struct drm_gem_object *obj)
> > {
> > - if (obj != NULL) {
> > - WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex));
> > -
> > - kref_put(&obj->refcount, drm_gem_object_free);
> > - }
> > + kref_put(&obj->refcount, drm_gem_object_free);
> > }
> >
> > -/**
> > - * drm_gem_object_unreference_unlocked - release a GEM BO reference
> > - * @obj: GEM buffer object
> > - *
> > - * This releases a reference to @obj. Callers must not hold the
> > - * dev->struct_mutex lock when calling this function.
> > - */
> > -static inline void
> > -drm_gem_object_unreference_unlocked(struct drm_gem_object *obj)
> > -{
> > - struct drm_device *dev;
> > -
> > - if (!obj)
> > - return;
> > -
> > - dev = obj->dev;
> > - if (kref_put_mutex(&obj->refcount, drm_gem_object_free, &dev->struct_mutex))
> > - mutex_unlock(&dev->struct_mutex);
> > - else
> > - might_lock(&dev->struct_mutex);
> > -}
> > +void drm_gem_object_unreference_unlocked(struct drm_gem_object *obj);
> > +void drm_gem_object_unreference(struct drm_gem_object *obj);
> >
> > int drm_gem_handle_create(struct drm_file *file_priv,
> > struct drm_gem_object *obj,
> > --
> > 2.8.1
> >
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
More information about the dri-devel
mailing list