This is a small fallout from a work to allow batching WW mutex locks and
unlocks.
Our Wound-Wait mutexes actually don't use the Wound-Wait algorithm but
the Wait-Die algorithm. One could perhaps rename those mutexes tree-wide to
"Wait-Die mutexes" or "Deadlock Avoidance mutexes". Another approach suggested
here is to implement also the "Wound-Wait" algorithm as a per-WW-class
choice, as it has advantages in some cases. See for example
http://www.mathcs.emory.edu/~cheung/Courses/554/Syllabus/8-recv+serial/dead…
Now Wound-Wait is a preemptive algorithm, and the preemption is implemented
using a lazy scheme: If a wounded transaction is about to go to sleep on
a contended WW mutex, we return -EDEADLK. That is sufficient for deadlock
prevention. Since with WW mutexes we also require the aborted transaction to
sleep waiting to lock the WW mutex it was aborted on, this choice also provides
a suitable WW mutex to sleep on. If we were to return -EDEADLK on the first
WW mutex lock after the transaction was wounded whether the WW mutex was
contended or not, the transaction might frequently be restarted without a wait,
which is far from optimal. Note also that with the lazy preemption scheme,
contrary to Wait-Die there will be no rollbacks on lock contention of locks
held by a transaction that has completed its locking sequence.
The modeset locks are then changed from Wait-Die to Wound-Wait since the
typical locking pattern of those locks very well matches the criterion for
a substantial reduction in the number of rollbacks. For reservation objects,
the benefit is more unclear at this point and they remain using Wait-Die.
Cc: Ingo Molnar <mingo(a)redhat.com>
Cc: Jonathan Corbet <corbet(a)lwn.net>
Cc: Gustavo Padovan <gustavo(a)padovan.org>
Cc: Maarten Lankhorst <maarten.lankhorst(a)linux.intel.com>
Cc: Sean Paul <seanpaul(a)chromium.org>
Cc: David Airlie <airlied(a)linux.ie>
Cc: Davidlohr Bueso <dave(a)stgolabs.net>
Cc: "Paul E. McKenney" <paulmck(a)linux.vnet.ibm.com>
Cc: Josh Triplett <josh(a)joshtriplett.org>
Cc: Thomas Gleixner <tglx(a)linutronix.de>
Cc: Kate Stewart <kstewart(a)linuxfoundation.org>
Cc: Philippe Ombredanne <pombredanne(a)nexb.com>
Cc: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Cc: linux-doc(a)vger.kernel.org
Cc: linux-media(a)vger.kernel.org
Cc: linaro-mm-sig(a)lists.linaro.org
v2:
Updated DEFINE_WW_CLASS() API, minor code- and comment fixes as
detailed in each patch.
v3:
Included cleanup patch from Peter Zijlstra. Documentation fixes and
a small correctness fix.
v4:
Reworked the correctness fix.
On 12/19/18 5:39 PM, Zengtao (B) wrote:
> Hi laura:
>
>> -----Original Message-----
>> From: Laura Abbott [mailto:labbott@redhat.com]
>> Sent: Thursday, December 20, 2018 2:10 AM
>> To: Zengtao (B) <prime.zeng(a)hisilicon.com>; sumit.semwal(a)linaro.org
>> Cc: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>; Arve Hjønnevåg
>> <arve(a)android.com>; Todd Kjos <tkjos(a)android.com>; Martijn Coenen
>> <maco(a)android.com>; Joel Fernandes <joel(a)joelfernandes.org>;
>> devel(a)driverdev.osuosl.org; dri-devel(a)lists.freedesktop.org;
>> linaro-mm-sig(a)lists.linaro.org; linux-kernel(a)vger.kernel.org
>> Subject: Re: [PATCH] staging: android: ion: add buffer flag update ioctl
>>
>> On 12/19/18 9:19 AM, Zeng Tao wrote:
>>> In some usecases, the buffer cached attribute is not determined at
>>> allocation time, it's determined just before the real cpu mapping.
>>> And from the memory view of point, a buffer should not have the
>> cached
>>> attribute util is really mapped by the cpu. So in this patch, we
>>> introduced the new ioctl command to target the requirement.
>>>
>>
>> This is racy and error prone. Can you explain more what problem you are
>> trying to solve?
>
> My use case is like this:
> 1. There are two process A and B, A takes case of ion buffer allocation, and
> pass the buffer fd to B, then B maps and uses it.
> 2. Process B need to map the buffer with different cached attribute for
> different use case, for example, if the buffer is used for pure software algorithm,
> then we need to map it as cached, otherwise non-cached, and B needs to deal
> with both cases.
> And unfortunately the mmap syscall takes no cached flags and we can't decide
> the cache attribute when we are doing the mmap, so I introduce new the ioctl
> even though I think the solution is not as good.
>
>
Thanks for the explanation, this was about the use case I expected.
I'm pretty sure I had this exact problem once upon a time and we
didn't come up with a solution. I'd still like to get rid of
uncached buffers in general and just use cached buffers
(see http://driverdev.linuxdriverproject.org/pipermail/driverdev-devel/2018-Nove…)
What's your usecase for uncached buffers?
>>
>>> Signed-off-by: Zeng Tao <prime.zeng(a)hisilicon.com>
>>> ---
>>> drivers/staging/android/ion/ion-ioctl.c | 4 ++++
>>> drivers/staging/android/ion/ion.c | 17 +++++++++++++++++
>>> drivers/staging/android/ion/ion.h | 1 +
>>> drivers/staging/android/uapi/ion.h | 22
>> ++++++++++++++++++++++
>>> 4 files changed, 44 insertions(+)
>>>
>>> diff --git a/drivers/staging/android/ion/ion-ioctl.c
>>> b/drivers/staging/android/ion/ion-ioctl.c
>>> index a8d3cc4..60bb702 100644
>>> --- a/drivers/staging/android/ion/ion-ioctl.c
>>> +++ b/drivers/staging/android/ion/ion-ioctl.c
>>> @@ -12,6 +12,7 @@
>>>
>>> union ion_ioctl_arg {
>>> struct ion_allocation_data allocation;
>>> + struct ion_buffer_flag_data update;
>>> struct ion_heap_query query;
>>> };
>>>
>>> @@ -83,6 +84,9 @@ long ion_ioctl(struct file *filp, unsigned int cmd,
>>> unsigned long arg)
>>>
>>> break;
>>> }
>>> + case ION_IOC_BUFFER_UPDATE:
>>> + ret = ion_buffer_update(data.update.fd, data.update.flags);
>>> + break;
>>> case ION_IOC_HEAP_QUERY:
>>> ret = ion_query_heaps(&data.query);
>>> break;
>>> diff --git a/drivers/staging/android/ion/ion.c
>>> b/drivers/staging/android/ion/ion.c
>>> index 9907332..f1404dc 100644
>>> --- a/drivers/staging/android/ion/ion.c
>>> +++ b/drivers/staging/android/ion/ion.c
>>> @@ -436,6 +436,23 @@ int ion_alloc(size_t len, unsigned int
>> heap_id_mask, unsigned int flags)
>>> return fd;
>>> }
>>>
>>> +int ion_buffer_update(unsigned int fd, unsigned int flags) {
>>> + struct dma_buf *dmabuf;
>>> + struct ion_buffer *buffer;
>>> +
>>> + dmabuf = dma_buf_get(fd);
>>> +
>>> + if (!dmabuf)
>>> + return -EINVAL;
>>> +
>>> + buffer = dmabuf->priv;
>>> + buffer->flags = flags;
>>> + dma_buf_put(dmabuf);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> int ion_query_heaps(struct ion_heap_query *query)
>>> {
>>> struct ion_device *dev = internal_dev; diff --git
>>> a/drivers/staging/android/ion/ion.h
>>> b/drivers/staging/android/ion/ion.h
>>> index c006fc1..99bf9ab 100644
>>> --- a/drivers/staging/android/ion/ion.h
>>> +++ b/drivers/staging/android/ion/ion.h
>>> @@ -199,6 +199,7 @@ int ion_heap_pages_zero(struct page *page,
>> size_t size, pgprot_t pgprot);
>>> int ion_alloc(size_t len,
>>> unsigned int heap_id_mask,
>>> unsigned int flags);
>>> +int ion_buffer_update(unsigned int fd, unsigned int flags);
>>>
>>> /**
>>> * ion_heap_init_shrinker
>>> diff --git a/drivers/staging/android/uapi/ion.h
>>> b/drivers/staging/android/uapi/ion.h
>>> index 5d70098..99753fc 100644
>>> --- a/drivers/staging/android/uapi/ion.h
>>> +++ b/drivers/staging/android/uapi/ion.h
>>> @@ -74,6 +74,20 @@ struct ion_allocation_data {
>>> __u32 unused;
>>> };
>>>
>>> +/**
>>> + * struct ion_buffer_flag_data - metadata passed from userspace for
>>> +update
>>> + * buffer flags
>>> + * @fd: file descriptor of the buffer
>>> + * @flags: flags passed to the buffer
>>> + *
>>> + * Provided by userspace as an argument to the ioctl */
>>> +
>>> +struct ion_buffer_flag_data {
>>> + __u32 fd;
>>> + __u32 flags;
>>> +}
>>> +
>>> #define MAX_HEAP_NAME 32
>>>
>>> /**
>>> @@ -116,6 +130,14 @@ struct ion_heap_query {
>>> struct ion_allocation_data)
>>>
>>> /**
>>> + * DOC: ION_IOC_BUFFER_UPDATE - update the specified ion buffer
>> flags
>>> + *
>>> + * Takes an ion_buffer_flag_data structure and returns the result of
>>> +the
>>> + * buffer flag update operation.
>>> + */
>>> +#define ION_IOC_BUFFER_UPDATE _IOWR(ION_IOC_MAGIC, 1, \
>>> + struct ion_buffer_flag_data)
>>> +/**
>>> * DOC: ION_IOC_HEAP_QUERY - information about available heaps
>>> *
>>> * Takes an ion_heap_query structure and populates information
>> about
>>>
>