void futex_numa_32_lock(struct futex_numa_32 *lock)
{ for (;;) { struct futex_numa_32 new, old = {
.full = __atomic_load_n(&lock->full, __ATOMIC_RELAXED),
};
for (;;) { new = old; if (old.val == 0) { /* no waiter, no lock -> first lock, set no-node */ new.node = fnode;
} if (old.val & N_LOCK) { /* contention, set waiter */ new.val |= N_WAITERS;
} new.val |= N_LOCK;
/* nothing changed, ready to block */ if (old.full == new.full) break;
/* * Use u64 cmpxchg to set the futex value and node in a * consistent manner.
*/ if (__atomic_compare_exchange_n(&lock->full,
&old.full, new.full, /* .weak */ false,
__ATOMIC_ACQUIRE,
__ATOMIC_RELAXED)) {
/* if we just set N_LOCK, we own it */ if (!(old.val & N_LOCK)) return;
/* go block */ break;
}
}
futex2_wait(lock, new.val, fflags, NULL, 0);
}
}
void futex_numa_32_unlock(struct futex_numa_32 *lock)
{
u32 val = __atomic_sub_fetch(&lock->val, N_LOCK, __ATOMIC_RELEASE);
assert((s32)val >= 0); if (val & N_WAITERS) { int woken = futex2_wake(lock, 1, fflags);
assert(val == N_WAITERS); if (!woken) {
__atomic_compare_exchange_n(&lock->val, &val, 0U, false, __ATOMIC_RELAXED,
__ATOMIC_RELAXED);
}
}
}
staticlong nanos = 50000;
struct thread_args {
pthread_t tid; volatileint * done; struct futex_numa_32 *lock; int val; int *val1, *val2; int node;
};
while (!*args->done) { /* * futex2_wait() will take hb-lock, verify *var == val and * queue/abort. By knowingly setting val 'wrong' this will * abort and thereby generate hb-lock contention.
*/
futex2_wait(&args->lock->val, ~0U, fflags, NULL, 0);
args->val++;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.