136 lines
2.3 KiB
C
136 lines
2.3 KiB
C
/* SPDX-License-Identifier: MIT */
|
|
/*
|
|
* Description: test that thread pool issued requests don't cancel on thread
|
|
* exit, but do get canceled once the parent exits. Do both
|
|
* writes that finish and a poll request that sticks around.
|
|
*
|
|
*/
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
#include <sys/poll.h>
|
|
#include <pthread.h>
|
|
|
|
#include "helpers.h"
|
|
#include "liburing.h"
|
|
|
|
#define NR_IOS 8
|
|
#define WSIZE 512
|
|
|
|
struct d {
|
|
int fd;
|
|
struct io_uring *ring;
|
|
unsigned long off;
|
|
int pipe_fd;
|
|
int err;
|
|
};
|
|
|
|
static void *do_io(void *data)
|
|
{
|
|
struct d *d = data;
|
|
struct io_uring_sqe *sqe;
|
|
char *buffer;
|
|
int ret;
|
|
|
|
buffer = t_malloc(WSIZE);
|
|
memset(buffer, 0x5a, WSIZE);
|
|
sqe = io_uring_get_sqe(d->ring);
|
|
if (!sqe) {
|
|
d->err++;
|
|
return NULL;
|
|
}
|
|
io_uring_prep_write(sqe, d->fd, buffer, WSIZE, d->off);
|
|
sqe->user_data = d->off;
|
|
|
|
sqe = io_uring_get_sqe(d->ring);
|
|
if (!sqe) {
|
|
d->err++;
|
|
return NULL;
|
|
}
|
|
io_uring_prep_poll_add(sqe, d->pipe_fd, POLLIN);
|
|
|
|
ret = io_uring_submit(d->ring);
|
|
if (ret != 2)
|
|
d->err++;
|
|
|
|
free(buffer);
|
|
return NULL;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
struct io_uring ring;
|
|
const char *fname;
|
|
pthread_t thread;
|
|
int ret, do_unlink, i, fd;
|
|
struct d d;
|
|
int fds[2];
|
|
|
|
if (pipe(fds) < 0) {
|
|
perror("pipe");
|
|
return 1;
|
|
}
|
|
|
|
ret = io_uring_queue_init(32, &ring, 0);
|
|
if (ret) {
|
|
fprintf(stderr, "ring setup failed\n");
|
|
return 1;
|
|
}
|
|
|
|
if (argc > 1) {
|
|
fname = argv[1];
|
|
do_unlink = 0;
|
|
} else {
|
|
fname = ".thread.exit";
|
|
do_unlink = 1;
|
|
}
|
|
|
|
if (do_unlink)
|
|
t_create_file(fname, 4096);
|
|
|
|
fd = open(fname, O_WRONLY);
|
|
if (fd < 0) {
|
|
perror("open");
|
|
return 1;
|
|
}
|
|
|
|
d.fd = fd;
|
|
d.ring = ˚
|
|
d.off = 0;
|
|
d.pipe_fd = fds[0];
|
|
d.err = 0;
|
|
for (i = 0; i < NR_IOS; i++) {
|
|
memset(&thread, 0, sizeof(thread));
|
|
pthread_create(&thread, NULL, do_io, &d);
|
|
pthread_join(thread, NULL);
|
|
d.off += WSIZE;
|
|
}
|
|
|
|
for (i = 0; i < NR_IOS; i++) {
|
|
struct io_uring_cqe *cqe;
|
|
|
|
ret = io_uring_wait_cqe(&ring, &cqe);
|
|
if (ret) {
|
|
fprintf(stderr, "io_uring_wait_cqe=%d\n", ret);
|
|
goto err;
|
|
}
|
|
if (cqe->res != WSIZE) {
|
|
fprintf(stderr, "cqe->res=%d, Expected %d\n", cqe->res,
|
|
WSIZE);
|
|
goto err;
|
|
}
|
|
io_uring_cqe_seen(&ring, cqe);
|
|
}
|
|
|
|
if (do_unlink)
|
|
unlink(fname);
|
|
return d.err;
|
|
err:
|
|
if (do_unlink)
|
|
unlink(fname);
|
|
return 1;
|
|
}
|