[Mesa-dev] [PATCH] gallium/os: add os_wait_until_zero

Marek Olšák maraeo at gmail.com
Fri Jun 26 09:18:18 PDT 2015


My question was how to fix p_atomic_read? Would the volatile read that
I proposed work?

Marek


On Fri, Jun 26, 2015 at 5:59 PM, Ilia Mirkin <imirkin at alum.mit.edu> wrote:
> The compiler doesn't know that there's another thread. And it won't
> start to assume that there might always be another thread because then
> it could never optimize pointer derefs.
>
> On Fri, Jun 26, 2015 at 11:55 AM, Marek Olšák <maraeo at gmail.com> wrote:
>> I assumed the atomic operation in another thread would act as a
>> barrier in this case. Is that right?
>>
>> Marek
>>
>> On Fri, Jun 26, 2015 at 5:47 PM, Ilia Mirkin <imirkin at alum.mit.edu> wrote:
>>> On Fri, Jun 26, 2015 at 11:33 AM, Marek Olšák <maraeo at gmail.com> wrote:
>>>> I expect the variable will be changed using an atomic operation by the
>>>> CPU, or using a coherent store instruction by the GPU.
>>>>
>>>> If this is wrong and volatile is really required here, then
>>>> p_atomic_read is wrong too. Should we fix it? For example:
>>>>
>>>> #define p_atomic_read(_v) (*(volatile int*)(_v))
>>>>
>>>> Then, os_wait_until_zero can use p_atomic_read.
>>>
>>> The problem is the lack of a memory barrier. A function call to
>>> sched_yield implies a barrier (since the function could well have
>>> changed the memory that var points to), and so it's all fine. But on a
>>> non-PIPE_OS_UNIX os, this becomes
>>>
>>> while (*var);
>>>
>>> Which the compiler would be well within its right to rewrite to
>>>
>>> x = *var;
>>> while (x);
>>>
>>> which wouldn't end well. You need a barrier that tells the compiler
>>> that memory may be invalidated... I believe this maps to either mb()
>>> or barrier() in the linux kernel, and they have some fancy assembly
>>> syntax to tell the compiler "oops, memory may have changed". However
>>> in this case, it may be easier to just mark the var volatile.
>>>
>>>>
>>>> Marek
>>>>
>>>> On Fri, Jun 26, 2015 at 4:48 PM, Ilia Mirkin <imirkin at alum.mit.edu> wrote:
>>>>> On Fri, Jun 26, 2015 at 7:05 AM, Marek Olšák <maraeo at gmail.com> wrote:
>>>>>> From: Marek Olšák <marek.olsak at amd.com>
>>>>>>
>>>>>> This will be used by radeon and amdgpu winsyses.
>>>>>> Copied from the amdgpu winsys.
>>>>>> ---
>>>>>>  src/gallium/auxiliary/os/os_time.c | 36 +++++++++++++++++++++++++++++++++++-
>>>>>>  src/gallium/auxiliary/os/os_time.h | 10 ++++++++++
>>>>>>  2 files changed, 45 insertions(+), 1 deletion(-)
>>>>>>
>>>>>> diff --git a/src/gallium/auxiliary/os/os_time.c b/src/gallium/auxiliary/os/os_time.c
>>>>>> index f7e4ca4..63b6879 100644
>>>>>> --- a/src/gallium/auxiliary/os/os_time.c
>>>>>> +++ b/src/gallium/auxiliary/os/os_time.c
>>>>>> @@ -33,11 +33,12 @@
>>>>>>   */
>>>>>>
>>>>>>
>>>>>> -#include "pipe/p_config.h"
>>>>>> +#include "pipe/p_defines.h"
>>>>>>
>>>>>>  #if defined(PIPE_OS_UNIX)
>>>>>>  #  include <time.h> /* timeval */
>>>>>>  #  include <sys/time.h> /* timeval */
>>>>>> +#  include <sched.h> /* sched_yield */
>>>>>>  #elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
>>>>>>  #  include <windows.h>
>>>>>>  #else
>>>>>> @@ -92,3 +93,36 @@ os_time_sleep(int64_t usecs)
>>>>>>  }
>>>>>>
>>>>>>  #endif
>>>>>> +
>>>>>> +
>>>>>> +bool os_wait_until_zero(int *var, uint64_t timeout)
>>>>>
>>>>> Does this need to be volatile?
>>>>>
>>>>>> +{
>>>>>> +   if (!*var)
>>>>>> +      return true;
>>>>>> +
>>>>>> +   if (!timeout)
>>>>>> +      return false;
>>>>>> +
>>>>>> +   if (timeout == PIPE_TIMEOUT_INFINITE) {
>>>>>> +      while (*var) {
>>>>>> +#if defined(PIPE_OS_UNIX)
>>>>>> +         sched_yield();
>>>>>> +#endif
>>>>>> +      }
>>>>>> +      return true;
>>>>>> +   }
>>>>>> +   else {
>>>>>> +      int64_t start_time = os_time_get_nano();
>>>>>> +      int64_t end_time = start_time + timeout;
>>>>>> +
>>>>>> +      while (*var) {
>>>>>> +         if (os_time_timeout(start_time, end_time, os_time_get_nano()))
>>>>>> +            return false;
>>>>>> +
>>>>>> +#if defined(PIPE_OS_UNIX)
>>>>>> +         sched_yield();
>>>>>> +#endif
>>>>>> +      }
>>>>>> +      return true;
>>>>>> +   }
>>>>>> +}
>>>>>> diff --git a/src/gallium/auxiliary/os/os_time.h b/src/gallium/auxiliary/os/os_time.h
>>>>>> index 4fab03c..fdc8040 100644
>>>>>> --- a/src/gallium/auxiliary/os/os_time.h
>>>>>> +++ b/src/gallium/auxiliary/os/os_time.h
>>>>>> @@ -94,6 +94,16 @@ os_time_timeout(int64_t start,
>>>>>>  }
>>>>>>
>>>>>>
>>>>>> +/**
>>>>>> + * Wait until the variable at the given memory location is zero.
>>>>>> + *
>>>>>> + * \param var           variable
>>>>>> + * \param timeout       timeout, can be anything from 0 (no wait) to
>>>>>> + *                      PIPE_TIME_INFINITE (wait forever)
>>>>>> + * \return     true if the variable is zero
>>>>>> + */
>>>>>> +bool os_wait_until_zero(int *var, uint64_t timeout);
>>>>>> +
>>>>>>  #ifdef __cplusplus
>>>>>>  }
>>>>>>  #endif
>>>>>> --
>>>>>> 2.1.0
>>>>>>
>>>>>> _______________________________________________
>>>>>> mesa-dev mailing list
>>>>>> mesa-dev at lists.freedesktop.org
>>>>>> http://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list