[PATCH v4 2/4] mutex: add support for wound/wait style locks, v5

Inki Dae inki.dae at samsung.com
Wed May 29 03:33:26 PDT 2013


Hi,

Just minor comments

+Usage
> +-----
> +
> +Three different ways to acquire locks within the same w/w class. Common
> +definitions for methods #1 and #2:
> +
> +static DEFINE_WW_CLASS(ww_class);
> +
> +struct obj {
> +       struct ww_mutex lock;
> +       /* obj data */
> +};
> +
> +struct obj_entry {
> +       struct list_head *list;
> +       struct obj *obj;
> +};
> +
> +Method 1, using a list in execbuf->buffers that's not allowed to be
> reordered.
> +This is useful if a list of required objects is already tracked somewhere.
> +Furthermore the lock helper can use propagate the -EALREADY return code
> back to
> +the caller as a signal that an object is twice on the list. This is
> useful if
> +the list is constructed from userspace input and the ABI requires
> userspace to
> +not have duplicate entries (e.g. for a gpu commandbuffer submission
> ioctl).
> +
> +int lock_objs(struct list_head *list, struct ww_acquire_ctx *ctx)
> +{
> +       struct obj *res_obj = NULL;
> +       struct obj_entry *contended_entry = NULL;
> +       struct obj_entry *entry;
> +
> +       ww_acquire_init(ctx, &ww_class);
> +
> +retry:
> +       list_for_each_entry (list, entry) {
> +               if (entry == res_obj) {
>

if (entry->obj == res_obj) {


> +                       res_obj = NULL;
> +                       continue;
> +               }
> +               ret = ww_mutex_lock(&entry->obj->lock, ctx);
> +               if (ret < 0) {
> +                       contended_obj = entry;
>

contended_entry = entry;


> +                       goto err;
> +               }
> +       }
> +
> +       ww_acquire_done(ctx);
> +       return 0;
> +
> +err:
> +       list_for_each_entry_continue_reverse (list, contended_entry, entry)
>

list_for_each_entry_continue_reverse(entry, list, list)?


> +               ww_mutex_unlock(&entry->obj->lock);
> +
> +       if (res_obj)
> +               ww_mutex_unlock(&res_obj->lock);
> +
> +       if (ret == -EDEADLK) {
> +               /* we lost out in a seqno race, lock and retry.. */
> +               ww_mutex_lock_slow(&contended_entry->obj->lock, ctx);
> +               res_obj = contended_entry->obj;
> +               goto retry;
> +       }
> +       ww_acquire_fini(ctx);
> +
> +       return ret;
> +}
> +
> +Method 2, using a list in execbuf->buffers that can be reordered. Same
> semantics
> +of duplicate entry detection using -EALREADY as method 1 above. But the
> +list-reordering allows for a bit more idiomatic code.
> +
> +int lock_objs(struct list_head *list, struct ww_acquire_ctx *ctx)
> +{
> +       struct obj_entry *entry, *entry2;
> +
> +       ww_acquire_init(ctx, &ww_class);
> +
> +       list_for_each_entry (list, entry) {
> +               ret = ww_mutex_lock(&entry->obj->lock, ctx);
> +               if (ret < 0) {
> +                       entry2 = entry;
> +
> +                       list_for_each_entry_continue_reverse (list, entry2)
>

list_for_each_entry_continue_reverse(entry, list, list)?


> +                               ww_mutex_unlock(&entry->obj->lock);
> +
> +                       if (ret != -EDEADLK) {
> +                               ww_acquire_fini(ctx);
> +                               return ret;
> +                       }
> +
> +                       /* we lost out in a seqno race, lock and retry.. */
> +                       ww_mutex_lock_slow(&entry->obj->lock, ctx);
>

shouldn't the wounded task acquire slowpath lock to the above dead locked
entry like this, ww_mutex_lock_slow(&entry2->obj->lock, ctx)?


> +
> +                       /*
> +                        * Move buf to head of the list, this will point
> +                        * buf->next to the first unlocked entry,
> +                        * restarting the for loop.
> +                        */
> +                       list_del(&entry->list);
> +                       list_add(&entry->list, list);
> +               }
> +       }
> +
> +       ww_acquire_done(ctx);
> +       return 0;
> +}
> +
> +Unlocking works the same way for both methods #1 and #2:
> +
> +void unlock_objs(struct list_head *list, struct ww_acquire_ctx *ctx)
> +{
> +       struct obj_entry *entry;
> +
> +       list_for_each_entry (list, entry)
> +               ww_mutex_unlock(&entry->obj->lock);
> +
> +       ww_acquire_fini(ctx);
> +}
> +
>
> _______________________________________________
> dri-devel mailing list
> dri-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/dri-devel/attachments/20130529/3f2d4157/attachment-0001.html>


More information about the dri-devel mailing list