diff options
| author | Kacper <kacper@mail.openlinux.dev> | 2025-12-15 02:01:33 +0100 |
|---|---|---|
| committer | Kacper <kacper@mail.openlinux.dev> | 2025-12-15 02:01:59 +0100 |
| commit | 3b3325f761b09ebbfef04c44eed546cc4fdeb329 (patch) | |
| tree | aa19ea259bcda2410c2b3dd4512f19fb85aeaf8f /lib | |
| parent | 15d2df7811ef3cb79cc3e501d0d5f9b993d42bea (diff) | |
Added aio and eventfd support, along with sleep and yes utilities
Diffstat (limited to 'lib')
28 files changed, 688 insertions, 4 deletions
diff --git a/lib/libc/Kbuild b/lib/libc/Kbuild index 55ec6422..7de874f6 100644 --- a/lib/libc/Kbuild +++ b/lib/libc/Kbuild @@ -2,6 +2,7 @@ lib-y := libc.a cflags-y += -I $(src)/include +obj-y += aio/ obj-y += arch/ obj-y += arpa/ obj-y += assert/ diff --git a/lib/libc/aio/Kbuild b/lib/libc/aio/Kbuild new file mode 100644 index 00000000..6bd83c98 --- /dev/null +++ b/lib/libc/aio/Kbuild @@ -0,0 +1,9 @@ +obj-y += aio.o +obj-y += aio_cancel.o +obj-y += aio_error.o +obj-y += aio_fsync.o +obj-y += aio_read.o +obj-y += aio_return.o +obj-y += aio_suspend.o +obj-y += aio_write.o +obj-y += lio_listio.o diff --git a/lib/libc/aio/aio.c b/lib/libc/aio/aio.c new file mode 100644 index 00000000..0ca2ec64 --- /dev/null +++ b/lib/libc/aio/aio.c @@ -0,0 +1,150 @@ +#include <__aio.h> +#include <io_uring.h> +#include <signal.h> +#include <stdint.h> +#include <string.h> +#include <sys/mman.h> +#include <unistd.h> + +struct aio_context __aio_context = { 0 }; + +// TODO +// static void *__aio_thread_notify(void *arg) +// { +// struct sigevent *sev = arg; +// sev->sigev_notify_function(sev->sigev_value); +// return NULL; +// } + +static void __aio_deliver_signal(struct sigevent *sev) +{ + if (!sev) + return; + + switch (sev->sigev_notify) { + case SIGEV_SIGNAL: + kill(getpid(), sev->sigev_signo); + break; + + case SIGEV_THREAD: { + // TODO + // pthread_t thread; + // pthread_create(&thread, NULL, __aio_thread_notify, sev); + // pthread_detach(thread); + break; + } + + default: + break; + } +} + +static void __aio_complete(struct aio_request *req, int res) +{ + req->result = res; + req->status = AIO_REQUEST_STATUS_COMPLETED; + + if (req->grp) { + if (res < 0) + req->grp->error = 1; + + if (--req->grp->pending == 0) { + uint64_t one = 1; + write(req->grp->eventfd, &one, sizeof(one)); + + if (req->grp->sig) { + __aio_deliver_signal(req->grp->sig); + } + } + } +} + +int __aio_request(struct aio_request *req, int opcode) +{ + struct io_uring_sqe *sqe; + unsigned index, tail; + + if (req == NULL) + return -1; + + tail = *__io_uring.sq.tail; + index = tail & *__io_uring.sq.ring_mask; + + sqe = &__io_uring.sq.sqes[index]; + memset(sqe, 0, sizeof(*sqe)); + sqe->opcode = opcode; + sqe->fd = req->aiocbp->aio_fildes; + sqe->addr = (uint64_t)req->aiocbp->aio_buf; + sqe->len = req->aiocbp->aio_nbytes; + sqe->off = req->aiocbp->aio_offset; + sqe->user_data = (uint64_t)req; + + __io_uring.sq.array[index] = index; + *__io_uring.sq.tail = tail + 1; + + io_uring_enter(__io_uring.fd, 1, 0, IORING_ENTER_GETEVENTS, NULL, 0); + + req->status = AIO_REQUEST_STATUS_PENDING; + req->next = NULL; + + if (__aio_context.head == NULL) { + __aio_context.head = __aio_context.tail = req; + } else { + __aio_context.tail->next = req; + __aio_context.tail = req; + } + + return 0; +} + +void __aio_poll(void) +{ + unsigned head = *__io_uring.cq.head; + unsigned tail = *__io_uring.cq.tail; + + while (head != tail) { + struct io_uring_cqe *cqe = + &__io_uring.cq.cqes[head & *__io_uring.cq.ring_mask]; + + struct aio_request *req = (struct aio_request *)cqe->user_data; + + __aio_complete(req, cqe->res); + + head++; + } + + *__io_uring.cq.head = head; +} + +struct aio_request *__aio_lookup(const struct aiocb *aiocbp) +{ + struct aio_request *req = __aio_context.head; + + while (req != NULL) { + if (req->aiocbp == aiocbp) + return req; + + req = req->next; + } + + return NULL; +} + +struct aio_request *__aio_remove(const struct aiocb *aiocbp) +{ + struct aio_request **cur = &__aio_context.head; + struct aio_request *req = NULL; + + while (*cur) { + if ((*cur)->aiocbp == aiocbp) { + req = *cur; + *cur = req->next; + if (__aio_context.tail == req) + __aio_context.tail = NULL; + break; + } + cur = &(*cur)->next; + } + + return req; +} diff --git a/lib/libc/aio/aio_cancel.c b/lib/libc/aio/aio_cancel.c new file mode 100644 index 00000000..b4d373bf --- /dev/null +++ b/lib/libc/aio/aio_cancel.c @@ -0,0 +1,47 @@ +#include <__aio.h> +#include <errno.h> +#include <io_uring.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <sys/cdefs.h> + +int aio_cancel(int __unused fildes, struct aiocb *aiocbp) +{ + unsigned tail; + struct aio_request *req; + struct io_uring_sqe sqe; + + if (aiocbp == NULL) { + errno = EINVAL; + return -1; + } + + req = __aio_lookup(aiocbp); + + if (req == NULL) { + errno = EINVAL; + return -1; + } + + if (req->status == AIO_REQUEST_STATUS_COMPLETED) { + return AIO_ALLDONE; + } + + memset(&sqe, 0, sizeof(sqe)); + sqe.opcode = IORING_OP_ASYNC_CANCEL; + sqe.user_data = (uint64_t)req; + + tail = *__io_uring.sq.tail; + __io_uring.sq.sqes[tail % IO_URING_ENTRIES] = sqe; + __io_uring.sq.array[tail % IO_URING_ENTRIES] = tail % IO_URING_ENTRIES; + *__io_uring.sq.tail = tail + 1; + + io_uring_enter(__io_uring.fd, 1, 0, IORING_ENTER_GETEVENTS, NULL, 0); + + __aio_remove(aiocbp); + free(req); + + return AIO_CANCELED; +} diff --git a/lib/libc/aio/aio_error.c b/lib/libc/aio/aio_error.c new file mode 100644 index 00000000..27c7f134 --- /dev/null +++ b/lib/libc/aio/aio_error.c @@ -0,0 +1,26 @@ +#include <__aio.h> +#include <errno.h> +#include <stddef.h> + +int aio_error(const struct aiocb *aiocbp) +{ + struct aio_request *req; + + if (aiocbp == NULL) { + errno = EINVAL; + return -1; + } + + req = __aio_lookup(aiocbp); + + if (req == NULL) { + errno = EINVAL; + return -1; + } + + if (req->status == AIO_REQUEST_STATUS_PENDING) { + return EINPROGRESS; + } + + return req->result < 0 ? -req->result : 0; +} diff --git a/lib/libc/aio/aio_fsync.c b/lib/libc/aio/aio_fsync.c new file mode 100644 index 00000000..00d56b42 --- /dev/null +++ b/lib/libc/aio/aio_fsync.c @@ -0,0 +1,26 @@ +#include <__aio.h> +#include <aio.h> +#include <errno.h> +#include <fcntl.h> +#include <io_uring.h> + +int aio_fsync(int op, struct aiocb *aiocbp) +{ + int opcode; + struct aio_request *req; + + req = __aio_lookup(aiocbp); + + if (req == NULL) { + errno = EINVAL; + return -1; + } + + if (op == O_DSYNC) { + opcode = IORING_OP_FSYNC | IORING_FSYNC_DATASYNC; + } else { + opcode = IORING_OP_FSYNC; + } + + return __aio_request(req, opcode); +} diff --git a/lib/libc/aio/aio_read.c b/lib/libc/aio/aio_read.c new file mode 100644 index 00000000..286b2d02 --- /dev/null +++ b/lib/libc/aio/aio_read.c @@ -0,0 +1,16 @@ +#include <__aio.h> +#include <aio.h> +#include <io_uring.h> +#include <stdlib.h> + +int aio_read(struct aiocb *aiocbp) +{ + struct aio_request *req = malloc(sizeof(*req)); + + if (req == NULL) + return -1; + + req->aiocbp = aiocbp; + + return __aio_request(req, IORING_OP_READ); +} diff --git a/lib/libc/aio/aio_return.c b/lib/libc/aio/aio_return.c new file mode 100644 index 00000000..45b0d795 --- /dev/null +++ b/lib/libc/aio/aio_return.c @@ -0,0 +1,26 @@ +#include <__aio.h> +#include <errno.h> +#include <stddef.h> +#include <stdlib.h> + +ssize_t aio_return(struct aiocb *aiocbp) +{ + ssize_t result; + struct aio_request *req; + + if (aiocbp == NULL) { + errno = EINVAL; + return -1; + } + + req = __aio_remove(aiocbp); + + if (req->status == AIO_REQUEST_STATUS_PENDING) { + free(req); + return -1; + } + + result = req->result; + free(req); + return result; +} diff --git a/lib/libc/aio/aio_suspend.c b/lib/libc/aio/aio_suspend.c new file mode 100644 index 00000000..939b9d6b --- /dev/null +++ b/lib/libc/aio/aio_suspend.c @@ -0,0 +1,57 @@ +#include <__aio.h> +#include <aio.h> +#include <errno.h> +#include <io_uring.h> +#include <poll.h> +#include <stdint.h> +#include <time.h> +#include <unistd.h> + +int aio_suspend(const struct aiocb *const list[], int nent, + const struct timespec *timeout) +{ + struct pollfd pfd; + struct aio_request *req; + + if ((void *)list == NULL || nent <= 0) { + errno = EINVAL; + return -1; + } + + while (1) { + int timeout_ms, ret; + __aio_poll(); + + for (int i = 0; i < nent; i++) { + req = __aio_lookup((struct aiocb *)list[i]); + if (req && req->status == AIO_REQUEST_STATUS_COMPLETED) + return 0; + } + + pfd.fd = __io_uring.eventfd; + pfd.events = POLLIN; + + if (timeout) { + timeout_ms = timeout->tv_sec * 1000 + + timeout->tv_nsec / 1000000; + } else { + timeout_ms = -1; + } + + ret = poll(&pfd, 1, timeout_ms); + + if (ret == 0) { + errno = EAGAIN; + return -1; + } + + if (ret < 0) { + return -1; + } + + uint64_t val; + read(__io_uring.eventfd, &val, sizeof(val)); + io_uring_enter(__io_uring.fd, 0, 0, IORING_ENTER_GETEVENTS, + NULL, 0); + } +} diff --git a/lib/libc/aio/aio_write.c b/lib/libc/aio/aio_write.c new file mode 100644 index 00000000..4254fdcd --- /dev/null +++ b/lib/libc/aio/aio_write.c @@ -0,0 +1,16 @@ +#include <__aio.h> +#include <aio.h> +#include <io_uring.h> +#include <stdlib.h> + +int aio_write(struct aiocb *aiocbp) +{ + struct aio_request *req = malloc(sizeof(*req)); + + if (req == NULL) + return -1; + + req->aiocbp = aiocbp; + + return __aio_request(req, IORING_OP_WRITE); +} diff --git a/lib/libc/aio/lio_listio.c b/lib/libc/aio/lio_listio.c new file mode 100644 index 00000000..0a345c16 --- /dev/null +++ b/lib/libc/aio/lio_listio.c @@ -0,0 +1,82 @@ +#include <__aio.h> +#include <aio.h> +#include <errno.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <sys/eventfd.h> +#include <unistd.h> +#include <stdint.h> + +int lio_listio(int mode, struct aiocb *restrict const list[restrict], int nent, + struct sigevent *restrict sig) +{ + struct lio_group *grp = NULL; + + if ((void *)list == NULL || nent <= 0) { + errno = EINVAL; + return -1; + } + + if (mode != LIO_WAIT && mode != LIO_NOWAIT) { + errno = EINVAL; + return -1; + } + + grp = malloc(sizeof(*grp)); + memset(grp, 0, sizeof(*grp)); + + grp->eventfd = eventfd(0, EFD_CLOEXEC); + grp->sig = sig; + + for (int i = 0; i < nent; i++) { + int ret; + struct aio_request *req; + struct aiocb *aiocbp = list[i]; + + if (aiocbp == NULL) { + continue; + } + + switch (aiocbp->aio_lio_opcode) { + case LIO_READ: + ret = aio_read(aiocbp); + break; + case LIO_WRITE: + ret = aio_write(aiocbp); + break; + case LIO_NOP: + ret = 0; + continue; + default: + errno = EINVAL; + return -1; + } + + if (ret < 0) { + return -1; + } + + req = __aio_lookup(aiocbp); + req->grp = grp; + grp->pending++; + } + + if (mode == LIO_NOWAIT) { + return 0; + } + + while (grp->pending > 0) { + uint64_t val; + if (read(grp->eventfd, &val, sizeof(val)) < 0) { + return -1; + } + } + + if (grp->error) { + errno = EIO; + return -1; + } + + return 0; +} diff --git a/lib/libc/arch/x86_64/crt0.c b/lib/libc/arch/x86_64/crt0.c index a278c525..c60239d3 100644 --- a/lib/libc/arch/x86_64/crt0.c +++ b/lib/libc/arch/x86_64/crt0.c @@ -1,9 +1,9 @@ +#include "asm/auxvec.h" // for AT_SYSINFO_EHDR +#include <io_uring.h> #include <linux/auxvec.h> // for AT_NULL #include <linux/elf.h> // for Elf64_Ehdr -#include "asm/auxvec.h" // for AT_SYSINFO_EHDR - -#include <stdint.h> // for uintptr_t -#include <stdlib.h> // for exit +#include <stdint.h> // for uintptr_t +#include <stdlib.h> // for exit #define weak_reference(old, new) \ extern __typeof(old) new __attribute__((__weak__, __alias__(#old))) @@ -23,6 +23,11 @@ static void __vdso_setup(Elf64_Ehdr *vdso_addr __attribute__((unused))) weak_reference(__vdso_setup, vdso_setup); +static void __io_uring_setup_(void) +{ +} +weak_reference(__io_uring_setup_, __io_uring_setup); + __attribute__((used)) void __libc_start(uintptr_t *sp) { char **argv; @@ -46,6 +51,8 @@ __attribute__((used)) void __libc_start(uintptr_t *sp) __auxv++; } + __io_uring_setup_(); + exit(main(argc, argv)); } diff --git a/lib/libc/err/err.c b/lib/libc/err/err.c index 5b1b2b02..95e079d5 100644 --- a/lib/libc/err/err.c +++ b/lib/libc/err/err.c @@ -1,3 +1,4 @@ +#include "sys/cdefs.h" #include <err.h> #include <stdarg.h> diff --git a/lib/libc/err/errx.c b/lib/libc/err/errx.c index 0afe999e..ab9c609d 100644 --- a/lib/libc/err/errx.c +++ b/lib/libc/err/errx.c @@ -1,3 +1,4 @@ +#include "sys/cdefs.h" #include <err.h> #include <stdarg.h> diff --git a/lib/libc/err/verr.c b/lib/libc/err/verr.c index d769c15c..75023ab3 100644 --- a/lib/libc/err/verr.c +++ b/lib/libc/err/verr.c @@ -1,3 +1,4 @@ +#include "sys/cdefs.h" #include <err.h> #include <stdarg.h> #include <stdlib.h> diff --git a/lib/libc/err/verrx.c b/lib/libc/err/verrx.c index d769c15c..75023ab3 100644 --- a/lib/libc/err/verrx.c +++ b/lib/libc/err/verrx.c @@ -1,3 +1,4 @@ +#include "sys/cdefs.h" #include <err.h> #include <stdarg.h> #include <stdlib.h> diff --git a/lib/libc/err/vwarn.c b/lib/libc/err/vwarn.c index 2f485d93..c90286fb 100644 --- a/lib/libc/err/vwarn.c +++ b/lib/libc/err/vwarn.c @@ -1,3 +1,4 @@ +#include "stddef.h" #include <stdarg.h> #include <stdio.h> diff --git a/lib/libc/err/vwarnx.c b/lib/libc/err/vwarnx.c index 2f485d93..c90286fb 100644 --- a/lib/libc/err/vwarnx.c +++ b/lib/libc/err/vwarnx.c @@ -1,3 +1,4 @@ +#include "stddef.h" #include <stdarg.h> #include <stdio.h> diff --git a/lib/libc/include/__aio.h b/lib/libc/include/__aio.h new file mode 100644 index 00000000..93cb1f79 --- /dev/null +++ b/lib/libc/include/__aio.h @@ -0,0 +1,35 @@ +#ifndef __LIBC_AIO_H +#define __LIBC_AIO_H + +#include <aio.h> + +#define AIO_REQUEST_STATUS_PENDING 0 +#define AIO_REQUEST_STATUS_COMPLETED 1 + +struct lio_group { + int pending; + int error; + int eventfd; + struct sigevent *sig; +}; + +struct aio_context { + struct aio_request *head; + struct aio_request *tail; +}; + +struct aio_request { + struct aiocb *aiocbp; + int status; + ssize_t result; + struct aio_request *next; + struct lio_group *grp; +}; + +void __aio_poll(void); + +int __aio_request(struct aio_request *, int); +struct aio_request *__aio_lookup(const struct aiocb *); +struct aio_request *__aio_remove(const struct aiocb *); + +#endif diff --git a/lib/libc/include/io_uring.h b/lib/libc/include/io_uring.h new file mode 100644 index 00000000..4dac4583 --- /dev/null +++ b/lib/libc/include/io_uring.h @@ -0,0 +1,53 @@ +#ifndef __LIBC_IO_URING_H +#define __LIBC_IO_URING_H + +#include <linux/io_uring.h> +#include <signal.h> + +#define IO_URING_ENTRIES 256 + +struct io_uring_sq { + void *ring; + size_t ring_size; + struct io_uring_sqe *sqes; + + unsigned *head; + unsigned *tail; + unsigned *ring_mask; + unsigned *ring_entries; + unsigned *flags; + unsigned *dropped; + unsigned *array; +}; + +struct io_uring_cq { + void *ring; + size_t ring_size; + + unsigned *head; + unsigned *tail; + unsigned *ring_mask; + unsigned *ring_entries; + unsigned *overflow; + struct io_uring_cqe *cqes; + unsigned *flags; +}; + +struct io_uring { + int fd; + int eventfd; + + struct io_uring_sq sq; + struct io_uring_cq cq; +}; + +extern struct io_uring __io_uring; + +int io_uring_setup(unsigned int, struct io_uring_params *); + +int io_uring_register(unsigned int, unsigned int, void *, unsigned int); + +int io_uring_enter(unsigned int, unsigned int, unsigned int, unsigned int, + sigset_t *, size_t); + +#endif diff --git a/lib/libc/string/strerror.c b/lib/libc/string/strerror.c index 2d3ea611..62bcea76 100644 --- a/lib/libc/string/strerror.c +++ b/lib/libc/string/strerror.c @@ -1,5 +1,6 @@ #include "features.h" // for __weak +#include "stddef.h" #include <errno.h> // for ERANGE, E2BIG, EACCES, EADDRINUSE, EADDRNOTAVAIL #include <libc.h> // for __unused #include <string.h> // for memcpy, size_t, strerror, strlen, locale_t diff --git a/lib/libc/sys/Kbuild b/lib/libc/sys/Kbuild index 1bf1dcba..fe9d0bfc 100644 --- a/lib/libc/sys/Kbuild +++ b/lib/libc/sys/Kbuild @@ -1,3 +1,9 @@ +obj-y += eventfd_read.o +obj-y += eventfd_write.o +obj-y += eventfd.o +obj-y += io_uring_enter.o +obj-y += io_uring_register.o +obj-y += io_uring_setup.o obj-y += ioctl.o obj-y += mount.o obj-y += reboot.o diff --git a/lib/libc/sys/eventfd.c b/lib/libc/sys/eventfd.c new file mode 100644 index 00000000..b0fb5d86 --- /dev/null +++ b/lib/libc/sys/eventfd.c @@ -0,0 +1,6 @@ +#include <syscall.h> + +int eventfd(unsigned int initval, int flags) +{ + return syscall(eventfd2, initval, flags); +} diff --git a/lib/libc/sys/eventfd_read.c b/lib/libc/sys/eventfd_read.c new file mode 100644 index 00000000..78d73623 --- /dev/null +++ b/lib/libc/sys/eventfd_read.c @@ -0,0 +1,8 @@ +#include <sys/eventfd.h> +#include <syscall.h> +#include <unistd.h> + +int eventfd_read(int fildes, eventfd_t *value) +{ + return (sizeof(*value) == read(fildes, value, sizeof(*value))) ? 0 : -1; +} diff --git a/lib/libc/sys/eventfd_write.c b/lib/libc/sys/eventfd_write.c new file mode 100644 index 00000000..9c89b388 --- /dev/null +++ b/lib/libc/sys/eventfd_write.c @@ -0,0 +1,8 @@ +#include <sys/eventfd.h> +#include <syscall.h> +#include <unistd.h> + +int eventfd_write(int fildes, eventfd_t value) +{ + return (sizeof(value) == write(fildes, &value, sizeof(value))) ? 0 : -1; +} diff --git a/lib/libc/sys/io_uring_enter.c b/lib/libc/sys/io_uring_enter.c new file mode 100644 index 00000000..5fe0773d --- /dev/null +++ b/lib/libc/sys/io_uring_enter.c @@ -0,0 +1,10 @@ +#include <signal.h> +#include <syscall.h> + +int io_uring_enter(unsigned int fd, unsigned int to_submit, + unsigned int min_complete, unsigned int flags, sigset_t *sig, + size_t sz) +{ + return syscall(io_uring_enter, fd, to_submit, min_complete, flags, sig, + sz); +} diff --git a/lib/libc/sys/io_uring_register.c b/lib/libc/sys/io_uring_register.c new file mode 100644 index 00000000..bee2355f --- /dev/null +++ b/lib/libc/sys/io_uring_register.c @@ -0,0 +1,7 @@ +#include <syscall.h> + +int io_uring_register(unsigned int fd, unsigned int opcode, void *arg, + unsigned int nr_args) +{ + return syscall(io_uring_register, fd, opcode, arg, nr_args); +} diff --git a/lib/libc/sys/io_uring_setup.c b/lib/libc/sys/io_uring_setup.c new file mode 100644 index 00000000..0a368a81 --- /dev/null +++ b/lib/libc/sys/io_uring_setup.c @@ -0,0 +1,81 @@ +#include <sys/eventfd.h> +#include <io_uring.h> +#include <string.h> +#include <sys/mman.h> +#include <syscall.h> + +struct io_uring __io_uring; + +int io_uring_setup(unsigned int entries, struct io_uring_params *params) +{ + return syscall(io_uring_setup, entries, params); +} + +int __io_uring_setup(void) +{ + struct io_uring_params p; + memset(&p, 0, sizeof(p)); + + __io_uring.fd = io_uring_setup(IO_URING_ENTRIES, &p); + + if (__io_uring.fd < 0) + return -1; + + __io_uring.sq.ring_size = + p.sq_off.array + p.sq_entries * sizeof(unsigned int); + __io_uring.sq.ring = mmap(NULL, __io_uring.sq.ring_size, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE, __io_uring.fd, + IORING_OFF_SQ_RING); + + if (__io_uring.sq.ring == MAP_FAILED) + return -1; + + __io_uring.sq.head = __io_uring.sq.ring + p.sq_off.head; + __io_uring.sq.tail = __io_uring.sq.ring + p.sq_off.tail; + __io_uring.sq.ring_mask = __io_uring.sq.ring + p.sq_off.ring_mask; + __io_uring.sq.ring_entries = __io_uring.sq.ring + p.sq_off.ring_entries; + __io_uring.sq.flags = __io_uring.sq.ring + p.sq_off.flags; + __io_uring.sq.dropped = __io_uring.sq.ring + p.sq_off.dropped; + __io_uring.sq.array = __io_uring.sq.ring + p.sq_off.array; + __io_uring.sq.sqes = + mmap(NULL, p.sq_entries * sizeof(struct io_uring_sqe), + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, + __io_uring.fd, IORING_OFF_SQES); + + if (__io_uring.sq.sqes == MAP_FAILED) { + munmap(__io_uring.sq.ring, __io_uring.sq.ring_size); + return -1; + } + + __io_uring.cq.ring_size = + p.cq_off.cqes + p.cq_entries * sizeof(struct io_uring_cqe); + __io_uring.cq.ring = mmap(NULL, __io_uring.cq.ring_size, + PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_POPULATE, __io_uring.fd, + IORING_OFF_CQ_RING); + + if (__io_uring.cq.ring == MAP_FAILED) { + munmap(__io_uring.sq.ring, __io_uring.sq.ring_size); + munmap(__io_uring.sq.sqes, + p.sq_entries * sizeof(struct io_uring_sqe)); + return -1; + } + + __io_uring.eventfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); + if (__io_uring.eventfd < 0) + return -1; + + io_uring_register(__io_uring.fd, IORING_REGISTER_EVENTFD, + &__io_uring.eventfd, 1); + + __io_uring.cq.head = __io_uring.cq.ring + p.cq_off.head; + __io_uring.cq.tail = __io_uring.cq.ring + p.cq_off.tail; + __io_uring.cq.ring_mask = __io_uring.cq.ring + p.cq_off.ring_mask; + __io_uring.cq.ring_entries = __io_uring.cq.ring + p.cq_off.ring_entries; + __io_uring.cq.overflow = __io_uring.cq.ring + p.cq_off.overflow; + __io_uring.cq.cqes = __io_uring.cq.ring + p.cq_off.cqes; + __io_uring.cq.flags = __io_uring.cq.ring + p.cq_off.flags; + + return 0; +} |
