qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

test-thread-pool: be more reliable

There is a rare race between the atomic_cmpxchg and
bdrv_aio_cancel/bdrv_aio_cancel_async invocations. Detect it, the
only sensible we can do about it is to exit long_cb immediately.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

+21 -11
+21 -11
tests/test-thread-pool.c
··· 27 27 static int long_cb(void *opaque) 28 28 { 29 29 WorkerTestData *data = opaque; 30 - atomic_inc(&data->n); 31 - g_usleep(2000000); 32 - atomic_inc(&data->n); 30 + if (atomic_cmpxchg(&data->n, 0, 1) == 0) { 31 + g_usleep(2000000); 32 + atomic_or(&data->n, 2); 33 + } 33 34 return 0; 34 35 } 35 36 ··· 171 172 /* Cancel the jobs that haven't been started yet. */ 172 173 num_canceled = 0; 173 174 for (i = 0; i < 100; i++) { 174 - if (atomic_cmpxchg(&data[i].n, 0, 3) == 0) { 175 + if (atomic_cmpxchg(&data[i].n, 0, 4) == 0) { 175 176 data[i].ret = -ECANCELED; 176 177 if (sync) { 177 178 bdrv_aio_cancel(data[i].aiocb); ··· 185 186 g_assert_cmpint(num_canceled, <, 100); 186 187 187 188 for (i = 0; i < 100; i++) { 188 - if (data[i].aiocb && data[i].n != 3) { 189 + if (data[i].aiocb && atomic_read(&data[i].n) < 4) { 189 190 if (sync) { 190 191 /* Canceling the others will be a blocking operation. */ 191 192 bdrv_aio_cancel(data[i].aiocb); ··· 201 202 } 202 203 g_assert_cmpint(active, ==, 0); 203 204 for (i = 0; i < 100; i++) { 204 - if (data[i].n == 3) { 205 + g_assert(data[i].aiocb == NULL); 206 + switch (data[i].n) { 207 + case 0: 208 + fprintf(stderr, "Callback not canceled but never started?\n"); 209 + abort(); 210 + case 3: 211 + /* Couldn't be canceled asynchronously, must have completed. */ 212 + g_assert_cmpint(data[i].ret, ==, 0); 213 + break; 214 + case 4: 215 + /* Could be canceled asynchronously, never started. */ 205 216 g_assert_cmpint(data[i].ret, ==, -ECANCELED); 206 - g_assert(data[i].aiocb == NULL); 207 - } else { 208 - g_assert_cmpint(data[i].n, ==, 2); 209 - g_assert(data[i].ret == 0 || data[i].ret == -ECANCELED); 210 - g_assert(data[i].aiocb == NULL); 217 + break; 218 + default: 219 + fprintf(stderr, "Callback aborted while running?\n"); 220 + abort(); 211 221 } 212 222 } 213 223 }