Skip to content

Commit

Permalink
test/futex: test additions and flag changes
Browse files Browse the repository at this point in the history
1) Use the FUTEX2 flags as this is what the API is mandating now
2) Test that we don't have leftover completions
3) Add test cases for nr == 0 for wakes
4) Add test cases for passing invalid flags

Signed-off-by: Jens Axboe <axboe@kernel.dk>
  • Loading branch information
axboe committed Sep 27, 2023
1 parent 04250a6 commit 54f0f9a
Showing 1 changed file with 175 additions and 3 deletions.
178 changes: 175 additions & 3 deletions test/futex.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@
#define LOOPS 500
#define NFUTEX 8

#ifndef FUTEX2_SIZE_U8
#define FUTEX2_SIZE_U8 0x00
#define FUTEX2_SIZE_U16 0x01
#define FUTEX2_SIZE_U32 0x02
#define FUTEX2_SIZE_U64 0x03
#define FUTEX2_NUMA 0x04
/* 0x08 */
/* 0x10 */
/* 0x20 */
/* 0x40 */
#define FUTEX2_PRIVATE FUTEX_PRIVATE_FLAG

#define FUTEX2_SIZE_MASK 0x03
#endif

static int no_futex;

static void *fwake(void *data)
Expand Down Expand Up @@ -68,7 +83,7 @@ static int __test(struct io_uring *ring, int vectored, int async,
for (i = 0; i < nfutex; i++) {
fw[i].val = 0;
fw[i].uaddr = (unsigned long) &futex[i];
fw[i].flags = FUTEX_32;
fw[i].flags = FUTEX2_SIZE_U32;
fw[i].__reserved = 0;
}

Expand Down Expand Up @@ -108,6 +123,12 @@ static int __test(struct io_uring *ring, int vectored, int async,
io_uring_cqe_seen(ring, cqe);
}

ret = io_uring_peek_cqe(ring, &cqe);
if (!ret) {
fprintf(stderr, "peek found cqe!\n");
return 1;
}

for (i = 0; i < nfutex; i++)
pthread_join(threads[i], &tret);

Expand Down Expand Up @@ -157,7 +178,7 @@ static int test_order(int vectored, int async)

fw.val = 0;
fw.uaddr = (unsigned long) futex;
fw.flags = FUTEX_32;
fw.flags = FUTEX2_SIZE_U32;
fw.__reserved = 0;

/*
Expand Down Expand Up @@ -237,7 +258,7 @@ static int test_multi_wake(int vectored)

fw.val = 0;
fw.uaddr = (unsigned long) futex;
fw.flags = FUTEX_32;
fw.flags = FUTEX2_SIZE_U32;
fw.__reserved = 0;

/*
Expand Down Expand Up @@ -286,6 +307,145 @@ static int test_multi_wake(int vectored)
io_uring_cqe_seen(&ring, cqe);
}

ret = io_uring_peek_cqe(&ring, &cqe);
if (!ret) {
fprintf(stderr, "peek found cqe!\n");
return 1;
}

io_uring_queue_exit(&ring);
return 0;
}

/*
* Test that waking 0 futexes returns 0
*/
static int test_wake_zero(void)
{
struct io_uring_sqe *sqe;
struct io_uring_cqe *cqe;
struct io_uring ring;
unsigned int *futex;
int ret;

ret = io_uring_queue_init(8, &ring, 0);
if (ret)
return ret;

futex = malloc(sizeof(*futex));
*futex = 0;

sqe = io_uring_get_sqe(&ring);
sqe->user_data = 1;
io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY, 0);

io_uring_submit(&ring);

sqe = io_uring_get_sqe(&ring);
sqe->user_data = 2;
io_uring_prep_futex_wake(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY, 0);

io_uring_submit(&ring);

ret = io_uring_wait_cqe(&ring, &cqe);

/*
* Should get zero res and it should be the wake
*/
if (cqe->res || cqe->user_data != 2) {
fprintf(stderr, "cqe res %d, data %ld\n", cqe->res, (long) cqe->user_data);
return 1;
}
io_uring_cqe_seen(&ring, cqe);

/*
* Should not have the wait complete
*/
ret = io_uring_peek_cqe(&ring, &cqe);
if (!ret) {
fprintf(stderr, "peek found cqe!\n");
return 1;
}

io_uring_queue_exit(&ring);
return 0;
}

/*
* Test invalid wait/wake/waitv flags
*/
static int test_invalid(void)
{
struct io_uring_sqe *sqe;
struct io_uring_cqe *cqe;
struct futex_waitv fw;
struct io_uring ring;
unsigned int *futex;
int ret;

ret = io_uring_queue_init(8, &ring, 0);
if (ret)
return ret;

futex = malloc(sizeof(*futex));
*futex = 0;

sqe = io_uring_get_sqe(&ring);
sqe->user_data = 1;
io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY, 0x1000);

io_uring_submit(&ring);

ret = io_uring_wait_cqe(&ring, &cqe);

/*
* Should get zero res and it should be the wake
*/
if (cqe->res != -EINVAL) {
fprintf(stderr, "wait cqe res %d\n", cqe->res);
return 1;
}
io_uring_cqe_seen(&ring, cqe);

sqe = io_uring_get_sqe(&ring);
sqe->user_data = 1;
io_uring_prep_futex_wake(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY, 0x1000);

io_uring_submit(&ring);

ret = io_uring_wait_cqe(&ring, &cqe);

/*
* Should get zero res and it should be the wake
*/
if (cqe->res != -EINVAL) {
fprintf(stderr, "wake cqe res %d\n", cqe->res);
return 1;
}
io_uring_cqe_seen(&ring, cqe);

fw.val = 0;
fw.uaddr = (unsigned long) futex;
fw.flags = FUTEX2_SIZE_U32 | 0x1000;
fw.__reserved = 0;

sqe = io_uring_get_sqe(&ring);
sqe->user_data = 1;
io_uring_prep_futex_waitv(sqe, &fw, 1, 0);

io_uring_submit(&ring);

ret = io_uring_wait_cqe(&ring, &cqe);

/*
* Should get zero res and it should be the wake
*/
if (cqe->res != -EINVAL) {
fprintf(stderr, "waitv cqe res %d\n", cqe->res);
return 1;
}
io_uring_cqe_seen(&ring, cqe);

io_uring_queue_exit(&ring);
return 0;
}
Expand All @@ -311,6 +471,18 @@ int main(int argc, char *argv[])
return T_EXIT_FAIL;
}

ret = test_wake_zero();
if (ret) {
fprintf(stderr, "wake 0 failed\n");
return T_EXIT_FAIL;
}

ret = test_invalid();
if (ret) {
fprintf(stderr, "test invalid failed\n");
return T_EXIT_FAIL;
}

ret = test(IORING_SETUP_SQPOLL, 0);
if (ret) {
fprintf(stderr, "test sqpoll 0 failed\n");
Expand Down

0 comments on commit 54f0f9a

Please sign in to comment.