On Thu, Dec 03, 2015 at 04:37:26PM +0000, Will Deacon wrote:Will the following work?
Right, but I'm having a hard time constructing something pretty that can+#define smp_cond_acquire(cond) do { \I think we spoke about this before, but what would work really well for
+ while (!(cond)) \
+ cpu_relax(); \
+ smp_rmb(); /* ctrl + rmb := acquire */ \
+} while (0)
+ smp_cond_acquire(!((val = atomic_read(&lock->val))& _Q_LOCKED_PENDING_MASK));
arm64 here is if we could override smp_cond_acquire in such a way that
the atomic_read could be performed explicitly in the macro. That would
allow us to use an LDXR to set the exclusive monitor, which in turn
means we can issue a WFE and get a cheap wakeup when lock->val is
actually modified.
With the current scheme, there's not enough information expressed in the
"cond" parameter to perform this optimisation.
do that. Lambda functions would be lovely, but we don't have those :/
While we can easily pass a pointer to an arbitrary type, we need
an expression to evaluate the result of the pointer load to act as our
condition.
smp_cond_acquire(&lock->val.counter,
[](int val){ return !(val& _Q_LOCKED_PENDING_MASK); });
Would be nice, but alas.
The best we can do is hardcode a variable name; maybe something like:
#define smp_cond_acquire(ptr, expr) do { \
typeof(*ptr) val; \
while ((val = READ_ONCE(*ptr)), expr) \
cpu_relax(); \
smp_rmb(); /* ctrl + rmb := acquire */ \
} while (0)
Which would let us write:
smp_cond_acquire(&lock->val.counter, !(val& _Q_LOCKED_PENDING_MASK));
Thoughts?