From 3b3325f761b09ebbfef04c44eed546cc4fdeb329 Mon Sep 17 00:00:00 2001 From: Kacper Date: Mon, 15 Dec 2025 02:01:33 +0100 Subject: Added aio and eventfd support, along with sleep and yes utilities --- lib/libc/aio/aio.c | 150 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 lib/libc/aio/aio.c (limited to 'lib/libc/aio/aio.c') 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 +#include +#include +#include +#include +#include + +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; +} -- cgit v1.2.3