1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
/* SPDX-License-Identifier: MIT */
/*
* Description: Test FUTEX2_PRIVATE with an active waiter being killed
*
*/
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <linux/futex.h>
#include "liburing.h"
#include "helpers.h"
#ifndef FUTEX2_SIZE_U32
#define FUTEX2_SIZE_U32 0x02
#endif
#ifndef FUTEX2_PRIVATE
#define FUTEX2_PRIVATE 128
#endif
static int do_child(int ring_flags, int async, int vectored)
{
struct io_uring_params p = { .flags = ring_flags, };
struct io_uring_sqe *sqe;
struct io_uring ring;
struct futex_waitv fw = { };
unsigned int *futex;
int ret;
ret = t_create_ring_params(16, &ring, &p);
if (ret) {
if (ret == T_SETUP_SKIP)
return T_EXIT_SKIP;
fprintf(stderr, "ring setup failed\n");
return T_EXIT_FAIL;
}
futex = malloc(sizeof(*futex));
*futex = 0;
fw.uaddr = (unsigned long) futex;
fw.flags = FUTEX2_SIZE_U32|FUTEX2_PRIVATE;
sqe = io_uring_get_sqe(&ring);
if (!vectored)
io_uring_prep_futex_wait(sqe, futex, 0, FUTEX_BITSET_MATCH_ANY,
FUTEX2_SIZE_U32|FUTEX2_PRIVATE, 0);
else
io_uring_prep_futex_waitv(sqe, &fw, 1, 0);
if (async)
sqe->flags |= IOSQE_ASYNC;
io_uring_submit(&ring);
return T_EXIT_PASS;
}
static int test(int sqpoll, int async, int vectored)
{
int status, ring_flags = 0;
pid_t pid;
if (sqpoll)
ring_flags |= IORING_SETUP_SQPOLL;
pid = fork();
if (pid < 0) {
perror("fork");
return T_EXIT_FAIL;
} else if (!pid) {
exit(do_child(ring_flags, async, vectored));
}
usleep(10000);
kill(pid, 9);
waitpid(pid, &status, 0);
return T_EXIT_PASS;
}
int main(int argc, char *argv[])
{
int ret;
ret = test(0, 0, 0);
if (ret == T_EXIT_FAIL) {
fprintf(stderr, "test 0 0 0 failed\n");
return T_EXIT_FAIL;
} else if (ret == T_EXIT_SKIP) {
return T_EXIT_SKIP;
}
ret = test(0, 1, 0);
if (ret == T_EXIT_FAIL) {
fprintf(stderr, "test 0 1 0 failed\n");
return T_EXIT_FAIL;
}
ret = test(0, 0, 1);
if (ret == T_EXIT_FAIL) {
fprintf(stderr, "test 0 0 1 failed\n");
return T_EXIT_FAIL;
}
ret = test(0, 1, 1);
if (ret == T_EXIT_FAIL) {
fprintf(stderr, "test 0 1 1 failed\n");
return T_EXIT_FAIL;
}
ret = test(IORING_SETUP_SQPOLL, 0, 0);
if (ret == T_EXIT_FAIL) {
fprintf(stderr, "test SQPOLL 0 0 failed\n");
return T_EXIT_FAIL;
}
ret = test(IORING_SETUP_SQPOLL, 1, 0);
if (ret == T_EXIT_FAIL) {
fprintf(stderr, "test SQPOLL 1 0 failed\n");
return T_EXIT_FAIL;
}
ret = test(IORING_SETUP_SQPOLL, 0, 1);
if (ret == T_EXIT_FAIL) {
fprintf(stderr, "test SQPOLL 0 1 failed\n");
return T_EXIT_FAIL;
}
ret = test(IORING_SETUP_SQPOLL, 1, 1);
if (ret == T_EXIT_FAIL) {
fprintf(stderr, "test SQPOLL 1 1 failed\n");
return T_EXIT_FAIL;
}
return T_EXIT_PASS;
}
|