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@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel