summaryrefslogtreecommitdiff
path: root/examples/ucontext-cp.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2019-09-20 07:10:08 -0600
committerJens Axboe <axboe@kernel.dk>2019-09-20 07:10:08 -0600
commit9fd8049cac30daab23d504ab67476c44d6a88251 (patch)
tree3c15fb348247ff35f8d540536b729b47450b47ad /examples/ucontext-cp.c
parentefb4e867013f64df7db92a3dee9f9d497f7de3b6 (diff)
parent20b3ce6c52d7f81e32395e4a94846d0c25ddfc34 (diff)
downloadliburing-9fd8049cac30daab23d504ab67476c44d6a88251.tar.gz
liburing-9fd8049cac30daab23d504ab67476c44d6a88251.tar.bz2
Merge branch 'master' of https://github.com/CarterLi/liburing
* 'master' of https://github.com/CarterLi/liburing: examples/ucontext-cp: use ucontext with liburing
Diffstat (limited to 'examples/ucontext-cp.c')
-rw-r--r--examples/ucontext-cp.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/examples/ucontext-cp.c b/examples/ucontext-cp.c
new file mode 100644
index 0000000..1f76a09
--- /dev/null
+++ b/examples/ucontext-cp.c
@@ -0,0 +1,188 @@
+/*
+ * gcc -Wall -O2 -D_GNU_SOURCE -o ucontext-cp ucontext-cp.c -luring
+ */
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+#include <ucontext.h>
+#include <signal.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include "liburing.h"
+
+#define QD 64
+#define BS (32*1024)
+
+typedef struct {
+ struct io_uring ring;
+ unsigned char stack_buf[SIGSTKSZ];
+ ucontext_t ctx_main, ctx_fnew;
+} async_context;
+
+typedef struct {
+ async_context *pctx;
+ int ret;
+ int infd;
+ int outfd;
+} arguments_bundle;
+
+#define DEFINE_AWAIT_OP(operation) \
+static ssize_t await_##operation( \
+ async_context *pctx, \
+ int fd, \
+ const struct iovec *ioves, \
+ unsigned int nr_vecs, \
+ off_t offset) \
+{ \
+ struct io_uring_sqe *sqe = io_uring_get_sqe(&pctx->ring); \
+\
+ if (!sqe) { \
+ return -1; \
+ } \
+\
+ io_uring_prep_##operation(sqe, fd, ioves, nr_vecs, offset); \
+ io_uring_sqe_set_data(sqe, pctx); \
+ io_uring_submit(&pctx->ring); \
+ swapcontext(&pctx->ctx_fnew, &pctx->ctx_main); \
+ struct io_uring_cqe *cqe; \
+ if (io_uring_peek_cqe(&pctx->ring, &cqe) < 0) { \
+ return -1; \
+ } \
+ io_uring_cqe_seen(&pctx->ring, cqe); \
+\
+ return cqe->res; \
+}
+
+DEFINE_AWAIT_OP(readv)
+DEFINE_AWAIT_OP(writev)
+#undef DEFINE_AWAIT_OP
+
+static int setup_context(unsigned entries, async_context *pctx)
+{
+ int ret;
+
+ ret = io_uring_queue_init(entries, &pctx->ring, 0);
+ if (ret < 0) {
+ fprintf(stderr, "queue_init: %s\n", strerror(-ret));
+ return -1;
+ }
+
+ ret = getcontext(&pctx->ctx_fnew);
+ if (ret < 0) {
+ perror("getcontext");
+ return -1;
+ }
+ pctx->ctx_fnew.uc_stack.ss_sp = &pctx->stack_buf;
+ pctx->ctx_fnew.uc_stack.ss_size = sizeof(pctx->stack_buf);
+ pctx->ctx_fnew.uc_link = &pctx->ctx_main;
+
+ return 0;
+}
+
+static int copy_file(async_context *pctx, int infd, int outfd, struct iovec* piov)
+{
+ off_t offset = 0;
+
+ for (;;) {
+ ssize_t bytes_read;
+
+ if ((bytes_read = await_readv(pctx, infd, piov, 1, offset)) < 0) {
+ perror("await_readv");
+ return 1;
+ }
+ if (bytes_read == 0) return 0;
+ piov->iov_len = bytes_read;
+
+ if (await_writev(pctx, outfd, piov, 1, offset) != bytes_read) {
+ perror("await_writev");
+ return 1;
+ }
+ if (bytes_read < BS) return 0;
+ offset += bytes_read;
+ }
+}
+
+static void copy_file_wrapper(arguments_bundle *pbundle) {
+ struct iovec iov = {
+ .iov_base = malloc(BS),
+ .iov_len = BS,
+ };
+ async_context *pctx = pbundle->pctx;
+
+ pbundle->ret = copy_file(pctx, pbundle->infd, pbundle->outfd, &iov);
+
+ free(iov.iov_base);
+ swapcontext(&pctx->ctx_fnew, &pctx->ctx_main);
+}
+
+int main(int argc, char *argv[])
+{
+ async_context ctx;
+ int infd, outfd;
+ struct io_uring_cqe *cqe;
+
+ if (argc < 3) {
+ printf("%s: infile outfile\n", argv[0]);
+ return 1;
+ }
+
+ infd = open(argv[1], O_RDONLY);
+ if (infd < 0) {
+ perror("open infile");
+ return 1;
+ }
+ outfd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (outfd < 0) {
+ perror("open outfile");
+ return 1;
+ }
+
+ if (setup_context(QD, &ctx))
+ return 1;
+
+ arguments_bundle bundle = {
+ .pctx = &ctx,
+ .ret = -1,
+ .infd = infd,
+ .outfd = outfd,
+ };
+
+ makecontext(&ctx.ctx_fnew, (void (*)(void)) copy_file_wrapper, 1, &bundle);
+
+ if (swapcontext(&ctx.ctx_main, &ctx.ctx_fnew)) {
+ perror("swapcontext");
+ return 1;
+ }
+
+ // event loop
+ while (bundle.ret == -1) {
+ int ret;
+ async_context* pctx;
+
+ // usually be timed waiting
+ ret = io_uring_wait_cqe(&ctx.ring, &cqe);
+ if (ret < 0) {
+ fprintf(stderr, "wait_cqe: %s\n", strerror(-ret));
+ return 1;
+ }
+
+ pctx = io_uring_cqe_get_data(cqe);
+ assert(pctx == &ctx);
+
+ if (swapcontext(&pctx->ctx_main, &pctx->ctx_fnew)) {
+ perror("swapcontext");
+ return 1;
+ }
+ }
+
+ close(outfd);
+ close(infd);
+ io_uring_queue_exit(&ctx.ring);
+
+ return 0;
+}