in st-dma-fence.c [444:509]
static int thread_signal_callback(void *arg)
{
const struct race_thread *t = arg;
unsigned long pass = 0;
unsigned long miss = 0;
int err = 0;
while (!err && !kthread_should_stop()) {
struct dma_fence *f1, *f2;
struct simple_cb cb;
f1 = mock_fence();
if (!f1) {
err = -ENOMEM;
break;
}
rcu_assign_pointer(t->fences[t->id], f1);
smp_wmb();
rcu_read_lock();
do {
f2 = dma_fence_get_rcu_safe(&t->fences[!t->id]);
} while (!f2 && !kthread_should_stop());
rcu_read_unlock();
if (t->before)
dma_fence_signal(f1);
smp_store_mb(cb.seen, false);
if (!f2 ||
dma_fence_add_callback(f2, &cb.cb, simple_callback)) {
miss++;
cb.seen = true;
}
if (!t->before)
dma_fence_signal(f1);
if (!cb.seen) {
dma_fence_wait(f2, false);
__wait_for_callbacks(f2);
}
if (!READ_ONCE(cb.seen)) {
pr_err("Callback not seen on thread %d, pass %lu (%lu misses), signaling %s add_callback; fence signaled? %s\n",
t->id, pass, miss,
t->before ? "before" : "after",
dma_fence_is_signaled(f2) ? "yes" : "no");
err = -EINVAL;
}
dma_fence_put(f2);
rcu_assign_pointer(t->fences[t->id], NULL);
smp_wmb();
dma_fence_put(f1);
pass++;
}
pr_info("%s[%d] completed %lu passes, %lu misses\n",
__func__, t->id, pass, miss);
return err;
}