+++ /dev/null
-*.rej
-*.orig
-*~
-/*.patch
-
-*.o
-*.o[ls]
-
-/src/libaio.a
-/src/libaio.so*
NAME=libaio
SPECFILE=$(NAME).spec
VERSION=$(shell awk '/Version:/ { print $$2 }' $(SPECFILE))
-RELEASE=$(shell awk '/Release:/ { print $$2 }' $(SPECFILE))
-CVSTAG = $(NAME)_$(subst .,-,$(VERSION))_$(subst .,-,$(RELEASE))
+TAG = $(NAME)-$(VERSION)
RPMBUILD=$(shell `which rpmbuild >&/dev/null` && echo "rpmbuild" || echo "rpm")
prefix=/usr
@$(MAKE) -C harness clean
tag-archive:
- @cvs -Q tag -F $(CVSTAG)
-
-create-archive: tag-archive
- @rm -rf /tmp/$(NAME)
- @cd /tmp; cvs -Q -d $(CVSROOT) export -r$(CVSTAG) $(NAME) || echo GRRRrrrrr -- ignore [export aborted]
- @mv /tmp/$(NAME) /tmp/$(NAME)-$(VERSION)
- @cd /tmp; tar czSpf $(NAME)-$(VERSION).tar.gz $(NAME)-$(VERSION)
- @rm -rf /tmp/$(NAME)-$(VERSION)
- @cp /tmp/$(NAME)-$(VERSION).tar.gz .
- @rm -f /tmp/$(NAME)-$(VERSION).tar.gz
- @echo " "
+ @git tag $(TAG)
+
+create-archive:
+ @git archive --prefix=$(NAME)-$(VERSION)/ -o $(NAME)-$(VERSION).tar.gz $(TAG)
@echo "The final archive is ./$(NAME)-$(VERSION).tar.gz."
archive: clean tag-archive create-archive
HARNESS_SRCS:=main.c
# io_queue.c
-CFLAGS+=-Wall -Werror -I../src -g -O
+CFLAGS+=-Wall -Werror -I../src -g -O2 -DPAGE_SIZE=$(shell getconf PAGESIZE)
#-lpthread -lrt
all: $(PROGS)
$(PROGS): %.p: %.t $(HARNESS_SRCS)
- $(CC) $(CFLAGS) -DTEST_NAME=\"$<\" -o $@ main.c ../src/libaio.a
+ $(CC) $(CFLAGS) -DTEST_NAME=\"$<\" -o $@ main.c ../src/libaio.a -lpthread
clean:
rm -f $(PROGS) *.o runtests.out rofile wofile rwfile
--- /dev/null
+/*
+ * Copyright (C) 2014, Dan Aloni, Kernelim Ltd.
+ * Copyright (C) 2014, Benjamin LaHaise <bcrl@kvack.org>.
+ * Copyright (C) 2014, Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+/*
+ * Description:
+ * This regression test ensures that submitting more events than can
+ * fit in the completion ring will not result in a hung task.
+ */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+#include <assert.h>
+#include <errno.h>
+#include <libaio.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/wait.h>
+
+const int max_events = 32;
+const int io_size = 0x1000;
+struct iocb *io;
+struct iocb **iops;
+struct iovec *iovecs;
+struct io_event *events;
+char *data;
+
+long submitted = 0;
+long completed = 0;
+long pending = 0;
+
+#define SYS_IO_GETEVENTS 0
+#define USER_GETEVENTS 1
+
+static volatile sig_atomic_t done = 0;
+
+struct aio_ring {
+ unsigned id; /* kernel internal index number */
+ unsigned nr; /* number of io_events */
+ volatile unsigned head;
+ volatile unsigned tail;
+
+ unsigned magic;
+ unsigned compat_features;
+ unsigned incompat_features;
+ unsigned header_length; /* size of aio_ring */
+
+ struct io_event io_events[0];
+};
+
+int get_ring_size(int nr_events)
+{
+ io_context_t ctx;
+ int ret, ring_size;
+ struct aio_ring *ring;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ret = io_setup(nr_events, &ctx);
+ assert(!ret);
+
+ ring = (void *)ctx;
+ ring_size = ring->nr;
+
+ ret = io_destroy(ctx);
+ assert(!ret);
+
+ return ring_size;
+}
+
+int user_getevents(io_context_t ctx, int nr_events, struct io_event *event)
+{
+ struct aio_ring *ring = (void *)ctx;
+ int completed = 0;
+ while ((completed < nr_events) && (ring->head != ring->tail)) {
+ unsigned new_head = ring->head;
+ *event = ring->io_events[new_head];
+ new_head += 1;
+ new_head %= ring->nr;
+ ring->head = new_head;
+ completed++;
+ }
+ return completed;
+}
+
+void prune(io_context_t io_ctx, int max_ios, int getevents_type)
+{
+ int ret;
+
+ if (getevents_type == USER_GETEVENTS)
+ ret = user_getevents(io_ctx, max_ios, events);
+ else
+ ret = io_getevents(io_ctx, pending, max_ios, events, NULL);
+ if (ret > 0) {
+ printf("Completed: %d\n", ret);
+ completed += ret;
+ pending -= ret;
+ }
+}
+
+void run_test(int max_ios, int getevents_type)
+{
+ int fd, ret;
+ long i, to_submit;
+ struct iocb **iocb_sub;
+ io_context_t io_ctx;
+ const char *filename = "testfile";
+
+ printf("MAX_IOS: %d, %s\n", max_ios, getevents_type == USER_GETEVENTS ?
+ "USER_GETEVENTS" : "IO_GETEVENTS");
+ memset(&io_ctx, 0, sizeof(io_ctx));
+ ret = io_setup(max_events, &io_ctx);
+ assert(!ret);
+
+ io = calloc(max_ios, sizeof(*io));
+ iops = calloc(max_ios, sizeof(*iops));
+ iovecs = calloc(max_ios, sizeof(*iovecs));
+ events = calloc(max_ios, sizeof(*events));
+
+ unlink(filename);
+ fd = open(filename, O_CREAT | O_RDWR | O_DIRECT, 0644);
+ assert(fd >= 0);
+
+ ret = ftruncate(fd, max_ios * io_size);
+ assert(!ret);
+
+ data = mmap(NULL, io_size * max_ios, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ assert(data != MAP_FAILED);
+
+ for (i = 0; i < max_ios; i++) {
+ iops[i] = &io[i];
+ io[i].data = io;
+ iovecs[i].iov_base = &data[io_size * i];
+ iovecs[i].iov_len = io_size;
+ io_prep_preadv(&io[i], fd, &iovecs[i], 1, 0);
+ }
+
+ submitted = completed = pending = 0;
+
+ to_submit = max_ios;
+ iocb_sub = iops;
+
+ while (submitted < max_ios) {
+ printf("Submitting: %ld\n", to_submit);
+
+ ret = io_submit(io_ctx, to_submit, iocb_sub);
+ if (ret >= 0) {
+ printf("Submitted: %d\n", ret);
+ submitted += ret;
+ iocb_sub += ret;
+ pending += ret;
+ to_submit -= ret;
+ } else {
+ if (ret == -EAGAIN) {
+ printf("Submitted too much, that's okay\n");
+ prune(io_ctx, max_ios, getevents_type);
+ }
+ }
+ }
+
+ prune(io_ctx, max_ios, getevents_type);
+ io_destroy(io_ctx);
+ close(fd);
+ ret = munmap(data, io_size * max_ios);
+ assert(!ret);
+
+ printf("Verifying...\n");
+
+ assert(completed == submitted);
+
+ printf("OK\n");
+}
+
+void run_child(void)
+{
+ int ring_size;
+
+ ring_size = get_ring_size(max_events);
+
+ printf("aio ring size: %d\n", ring_size);
+
+ run_test(ring_size-1, SYS_IO_GETEVENTS);
+ run_test(ring_size, SYS_IO_GETEVENTS);
+ run_test(ring_size+1, SYS_IO_GETEVENTS);
+ run_test(ring_size*2, SYS_IO_GETEVENTS);
+ run_test(ring_size*4, SYS_IO_GETEVENTS);
+
+ run_test(ring_size-1, USER_GETEVENTS);
+ run_test(ring_size, USER_GETEVENTS);
+ run_test(ring_size+1, USER_GETEVENTS);
+ run_test(ring_size*2, USER_GETEVENTS);
+ run_test(ring_size*4, USER_GETEVENTS);
+
+ exit(0);
+}
+
+void sighandler(int signo)
+{
+ assert(signo == SIGCHLD);
+ done = 1;
+}
+
+int test_main(void)
+{
+ unsigned int ret;
+ sighandler_t oldhandler;
+ pid_t child;
+
+ switch (child = fork()) {
+ case 0: /* child */
+ run_child();
+ break;
+ case -1:
+ perror("fork");
+ exit(1);
+ default:
+ oldhandler = signal(SIGCHLD, sighandler);
+ assert(oldhandler != SIG_ERR);
+ break;
+ }
+
+ ret = sleep(10);
+ if (ret != 0) {
+ pid_t pid;
+ int status;
+
+ assert(done);
+
+ pid = wait(&status);
+ if (pid != child) {
+ perror("wait");
+ exit(1);
+ }
+
+ return WEXITSTATUS(status);
+ }
+
+ return 1; /* failed */
+}
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 8
+ * End:
+ */
--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+/*
+ * Author: Anatol Pomozov <anatol.pomozov@gmail.com>
+ *
+ * Description: This code tests to make sure that when io_destroy
+ * returns, all outstanding I/Os have been completed. It does this by
+ * issuing one I/O and then calling io_destroy (without calling
+ * io_getevents). After the call to io_destroy, the buffer is checked
+ * to ensure that the data was retrieved. This is done simultaneously
+ * from 100 threads.
+ */
+
+#define _GNU_SOURCE
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <unistd.h>
+#include <string.h>
+#include <libaio.h>
+#include <stdbool.h>
+
+#define FILENAME "tempfile"
+#define FILEPATTERN '1'
+#define DESTROY_PATTERN '2'
+
+#define THREADS_NUM 100
+
+void
+aio_worker(void *ptr)
+{
+ int i, j, fd;
+ char buffer[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE)));
+
+ fd = open(FILENAME, O_DIRECT|O_RDONLY);
+ assert(fd >= 0);
+
+ for (i = 0; i < 1000; i++) {
+ io_context_t ctx;
+ struct iocb cb;
+ struct iocb *cbs[1];
+
+ assert(!io_queue_init(1, &ctx));
+ io_prep_pread(&cb, fd, buffer, PAGE_SIZE, 0);
+ cbs[0] = &cb;
+
+ memset(buffer, '0', PAGE_SIZE);
+ assert(io_submit(ctx, 1, &cbs[0]) == 1);
+ // wait random time (0-500ms) ?
+
+ io_destroy(ctx);
+ memset(buffer, DESTROY_PATTERN, PAGE_SIZE);
+ // wait random for (0-500ms) ?
+
+ // check it is still DESTROY_PATTERN
+ for (j = 0; j < PAGE_SIZE; j++) {
+ if (buffer[j] != DESTROY_PATTERN) {
+ fprintf(stderr,
+ "Buffer has unexpected character: %c\n",
+ buffer[j]);
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ close(fd);
+}
+
+int
+test_main(void)
+{
+ int i, fd, ret;
+ char buffer[PAGE_SIZE];
+ pthread_t threads[THREADS_NUM];
+
+ fd = open(FILENAME, O_CREAT|O_TRUNC|O_APPEND|O_RDWR, S_IRUSR|S_IWUSR);
+ assert(fd != -1);
+
+ memset(buffer, FILEPATTERN, PAGE_SIZE);
+ ret = write(fd, buffer, PAGE_SIZE);
+ assert(ret == PAGE_SIZE);
+ close(fd);
+
+ for (i = 0; i < THREADS_NUM; i++) {
+ ret = pthread_create(&threads[i], NULL,
+ (void *)&aio_worker, NULL);
+ assert(ret == 0);
+ }
+ for (i = 0; i < THREADS_NUM; i++) {
+ ret = pthread_join(threads[i], NULL);
+ assert(ret == 0);
+ }
+
+ return EXIT_SUCCESS;
+}
+/*
+ * Local Variables:
+ * mode: c
+ * c-basic-offset: 8
+ * End:
+ */
--- /dev/null
+/*
+ * Copyright 2015, Red Hat, Inc.
+ *
+ * This test remaps the aio ring buffer and ensures that I/O completions
+ * can still be reaped from userspace.
+ *
+ * Author: Jeff Moyer <jmoyer@redhat.com>
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <sched.h>
+#include <libaio.h>
+
+#define BUFLEN 4096
+#define TEMPLATE "19.XXXXXX"
+
+volatile sig_atomic_t timed_out = 0;
+
+struct aio_ring {
+ unsigned id; /* kernel internal index number */
+ unsigned nr; /* number of io_events */
+ volatile unsigned head;
+ volatile unsigned tail;
+
+ unsigned magic;
+ unsigned compat_features;
+ unsigned incompat_features;
+ unsigned header_length; /* size of aio_ring */
+
+ struct io_event io_events[0];
+};
+
+int
+open_temp_file(void)
+{
+ int fd;
+ char template[sizeof(TEMPLATE)];
+
+ strncpy(template, TEMPLATE, sizeof(TEMPLATE));
+ fd = mkostemp(template, O_DIRECT);
+ if (fd < 0) {
+ perror("mkstemp");
+ exit(1);
+ }
+ unlink(template);
+ return fd;
+}
+
+/*
+ * mmap will do the address space search for us. when remapping the ring,
+ * the use of MREMAP_FIXED will cause this mapping to be unmapped.
+ *
+ * len - length in bytes
+ *
+ * Returns the available virtual address, or MAP_FAILED on error.
+ */
+void *
+find_unused_va(size_t len)
+{
+ return mmap(0, len, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+}
+
+void
+alarm_handler(int __attribute__((unused))signo)
+{
+ timed_out = 1;
+}
+
+int
+user_getevents(io_context_t ctx, int nr_events, struct io_event *event)
+{
+ struct aio_ring *ring = (void *)ctx;
+ int completed = 0;
+
+ timed_out = 0;
+ signal(SIGALRM, alarm_handler);
+ alarm(30);
+
+ while ((completed < nr_events) && !timed_out) {
+ unsigned new_head;
+
+ if (ring->head == ring->tail) {
+ sched_yield();
+ continue;
+ }
+
+ new_head = ring->head;
+ *event = ring->io_events[new_head];
+ new_head += 1;
+ new_head %= ring->nr;
+ ring->head = new_head;
+ completed++;
+ }
+
+ alarm(0);
+ signal(SIGALRM, SIG_DFL);
+
+ return completed;
+}
+
+struct aio_ring *
+remap_ring(struct aio_ring *ring)
+{
+ struct aio_ring *new_ring;
+ size_t ring_size;
+
+ /*
+ * No need to round up to page size as ring->nr was adjusted
+ * already to fill the last page in the ring.
+ */
+ ring_size = sizeof(struct aio_ring) + ring->nr * sizeof(struct io_event);
+
+ /*
+ * Remap the ring.
+ */
+ new_ring = find_unused_va(ring_size);
+ if (new_ring == MAP_FAILED) {
+ fprintf(stderr, "Unable to find suitable va for ring\n");
+ return NULL;
+ }
+
+ new_ring = mremap(ring, ring_size, ring_size,
+ MREMAP_FIXED|MREMAP_MAYMOVE, new_ring);
+ if (new_ring == MAP_FAILED || new_ring == ring) {
+ perror("mremap");
+ return NULL;
+ }
+
+ return new_ring;
+}
+
+io_context_t
+remap_io_context(io_context_t ctx)
+{
+ struct aio_ring *ring, *new_ring;
+
+ ring = (void *)ctx;
+ new_ring = remap_ring(ring);
+ if (!new_ring)
+ return NULL;
+
+ ctx = (io_context_t)new_ring;
+ return ctx;
+}
+
+int
+do_io(io_context_t ctx, struct iocb *iocbp, int fd)
+{
+ int ret;
+ char buf[BUFLEN];
+
+ io_prep_pwrite(iocbp, fd, buf, BUFLEN, 0);
+ ret = io_submit(ctx, 1, &iocbp);
+ if (ret != 1) {
+ fprintf(stderr, "io_submit failed with %d\n", ret);
+ return 1;
+ }
+ return 0;
+}
+
+int
+check_completion(io_context_t ctx, struct iocb *iocbp)
+{
+ int ret;
+ struct io_event event;
+
+ ret = user_getevents(ctx, 1, &event);
+ if (ret != 1) {
+ fprintf(stderr, "user_getevents timed out.\n");
+ return 1;
+ }
+
+ if (event.obj != iocbp) {
+ fprintf(stderr,
+ "Error: event->opj (%p) does not match iocbp (%p)\n",
+ event.obj, iocbp);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+test_main()
+{
+ int fd;
+ int ret;
+ io_context_t ctx;
+ struct iocb iocb;
+
+ memset(&ctx, 0, sizeof(ctx));
+ fd = open_temp_file();
+
+ ret = io_setup(1, &ctx);
+ if (ret != 0) {
+ fprintf(stderr, "io_setup failed with %d\n", ret);
+ return 1;
+ }
+
+ /*
+ * First, try remapping the ring buffer in-between io_setup and
+ * io_submit.
+ */
+ ctx = remap_io_context(ctx);
+ if (ctx == NULL)
+ return 1;
+
+ ret = do_io(ctx, &iocb, fd);
+ if (ret != 0)
+ return 1;
+
+ ret = check_completion(ctx, &iocb);
+ if (ret != 0)
+ return 1;
+
+ /*
+ * Now remap the ring in between io_submit and getevents.
+ */
+ ret = do_io(ctx, &iocb, fd);
+ if (ret != 0)
+ return 1;
+
+ ctx = remap_io_context(ctx);
+ if (ctx == NULL)
+ return 1;
+
+ ret = check_completion(ctx, &iocb);
+ if (ret != 0)
+ return 1;
+
+ /*
+ * Success, clean up.
+ */
+ ret = io_destroy(ctx);
+ if (ret != 0) {
+ fprintf(stderr, "io_destroy failed with %d\n", ret);
+ return 1;
+ }
+ close(fd);
+
+ return 0;
+}
+/*
+ * Local variables:
+ * mode: c
+ * c-basic-offset: 8
+ * End:
+ */
--- /dev/null
+/*
+ * Copyright 2017, Red Hat, Inc.
+ * Author: Jeff Moyer <jmoyer@redhat.com>
+ * Based on test code from Mauricio Faria de Oliveira
+ * <mauricfo@linux.vnet.ibm.com>
+ * License: GPLv2
+ *
+ * Description: Ensure that aio-max-nr requests can be allocated, or,
+ * if not, that the reason is not faulty accounting.
+ */
+#include <libaio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#define FAIL 1
+
+#define AIO_MAX_NR "/proc/sys/fs/aio-max-nr"
+#define AIO_NR "/proc/sys/fs/aio-nr"
+
+static unsigned aio_max_nr;
+
+int
+read_proc_val(const char *path, unsigned *val)
+{
+ FILE *fp;
+ int ret;
+
+ fp = fopen(path, "r");
+ if (!fp) {
+ fprintf(stderr, "Unable to open proc file \"%s\" for reading\n",
+ path);
+ return FAIL;
+ }
+
+ ret = fscanf(fp, "%u\n", val);
+ fclose(fp);
+
+ if (ret == EOF) {
+ fprintf(stderr, "Failed to read from proc file \"%s\"\n",
+ path);
+ return FAIL;
+ }
+
+ return 0;
+}
+
+/*
+ * Create as many ioctx-s with nr_events each as possible (up to aio_max_nr).
+ * Report any failures of -EAGAIN.
+ */
+int
+do_alloc_ioctxs(int nr_events)
+{
+ long ret;
+ unsigned i, avail, aio_nr, nr_ctxs;
+ io_context_t *ioctx;
+
+ ret = read_proc_val(AIO_NR, &aio_nr);
+ if (ret)
+ return FAIL;
+
+ avail = aio_max_nr - aio_nr;
+ nr_ctxs = avail / nr_events;
+ ioctx = calloc(nr_ctxs, sizeof(*ioctx));
+ if (!ioctx) {
+ fprintf(stderr, "allocating %u ioctx-s failed with %d\n",
+ nr_ctxs, errno);
+ return FAIL;
+ }
+
+ fprintf(stderr, "Creating %u ioctx-s with %u events each...\n", nr_ctxs,
+ nr_events);
+ fflush(stderr);
+ for (i = 0; i < nr_ctxs; i++) {
+ ret = io_setup(nr_events, &ioctx[i]);
+ if (ret) {
+ /*
+ * EAGAIN is the only failure case we're interested
+ * in. -ENOMEM, for example, is expected in this
+ * test.
+ */
+ if (ret != -EAGAIN)
+ break;
+
+ fprintf(stderr,"io_setup(%u) failed on iteration %d.\n",
+ nr_events, i);
+ fprintf(stderr, "allocated %u of %u possible events.\n",
+ nr_events * i, aio_max_nr);
+ ret = read_proc_val(AIO_NR, &aio_nr);
+ if (ret == 0)
+ fprintf(stderr, "aio_nr is currently at %u\n",
+ aio_nr);
+
+ free(ioctx);
+ return FAIL;
+ }
+ }
+ fprintf(stderr, "Successfully created %u io_context-s\n", i);
+ if (i < nr_ctxs - 1)
+ fprintf(stderr, "Last io_setup call returned %ld (%s)\n", ret,
+ strerror(-ret));
+ fflush(stderr);
+
+ return 0;
+}
+
+/*
+ * We fork off a child to do the actual work. The reason is that each
+ * io_destroy will incur an rcu grace period to complete. That really
+ * adds up, depending on the number of io_contexts created. We take
+ * advantage of an optimization in the kernel that waits for all
+ * contexts to be torn down in one grace period. In other words, just
+ * exiting the process without tearing down the ioctx-s using
+ * io_destroy is way faster.
+ */
+int
+alloc_ioctxs(int nr_events)
+{
+ pid_t child;
+ int ret, status;
+
+ child = fork();
+ switch (child) {
+ case 0: /* child */
+ ret = do_alloc_ioctxs(nr_events);
+ exit(ret);
+ case -1:
+ fprintf(stderr, "fork() failed with %d\n", errno);
+ return FAIL;
+ default:
+ break;
+ }
+ if (waitpid(child, &status, 0) < 0)
+ return FAIL;
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
+ return 0;
+
+ return FAIL;
+}
+
+int
+test_main()
+{
+ int ret;
+ unsigned nr_events;
+
+ ret = read_proc_val(AIO_MAX_NR, &aio_max_nr);
+ if (ret)
+ return FAIL;
+
+ fprintf(stderr, "aio_max_nr: %u\n", aio_max_nr);
+
+ nr_events = 1;
+ while (1) {
+ ret = alloc_ioctxs(nr_events);
+ if (ret)
+ return FAIL;
+
+ if (nr_events == aio_max_nr)
+ break;
+
+ nr_events *= 2;
+ if (nr_events > aio_max_nr)
+ nr_events = aio_max_nr;
+ }
+
+ return 0;
+}
+/*
+ * Local variables:
+ * mode: c
+ * c-basic-offset: 8
+ * End:
+ */
--- /dev/null
+/*
+ * Copyright 2017, Red Hat, Inc.
+ *
+ * Test RWF_NOWAIT.
+ *
+ * RWF_NOWAIT will cause -EAGAIN to be returned in the io_event for
+ * any I/O that cannot be serviced without blocking the submission
+ * thread. Instances covered by the kernel at the time this test was
+ * written include:
+ * - O_DIRECT I/O to a file offset that has populated page cache pages
+ * - the submission context cannot obtain the inode lock
+ * - space allocation is necessary
+ * - we need to wait for other I/O (e.g. in the misaligned I/O case)
+ * - ...
+ *
+
+ * The easiest of these to test is that a direct I/O is writing to a
+ * file offset with populated page cache. We also test to ensure that
+ * we can perform I/O in the absence of the above conditions.
+ *
+ * Author: Jeff Moyer <jmoyer@redhat.com>
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <signal.h>
+#include <sched.h>
+#include <libaio.h>
+
+#define TEMPLATE "21.XXXXXX"
+#define BUFLEN 4096
+
+#ifndef RWF_NOWAIT
+#define RWF_NOWAIT 0x00000008
+#endif
+
+int
+open_temp_file()
+{
+ int fd;
+ char temp_file[sizeof(TEMPLATE)];
+
+ strncpy(temp_file, TEMPLATE, sizeof(TEMPLATE));
+ fd = mkstemp(temp_file);
+ if (fd < 0) {
+ perror("mkstemp");
+ return -1;
+ }
+ unlink(temp_file);
+ return fd;
+}
+
+int
+test_main()
+{
+ int fd, flags;
+ int ret;
+ io_context_t ctx;
+ struct iocb iocb, *iocbp = &iocb;
+ struct io_event event;
+ char buf[BUFLEN] __attribute__((aligned (4096)));
+ struct iovec iov;
+
+ fd = open_temp_file();
+ if (fd < 0)
+ return 1;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ret = io_setup(1, &ctx);
+ if (ret != 0) {
+ fprintf(stderr, "io_setup failed with %d\n", ret);
+ return 1;
+ }
+
+ /*
+ * Perform a buffered write to a file. This instantiates the
+ * block and adds the page to the page cache.
+ */
+ memset(buf, 0xa, BUFLEN);
+ ret = write(fd, buf, BUFLEN);
+ if (ret != BUFLEN) {
+ perror("write");
+ return 1;
+ }
+
+ /*
+ * Now attempt an aio/dio pwritev2 with the RWF_NONBLOCK flag
+ * set.
+ */
+ flags = fcntl(fd, F_GETFL);
+ ret = fcntl(fd, F_SETFL, flags | O_DIRECT);
+ if (ret != 0) {
+ perror("fcntl");
+ return 1;
+ }
+
+ memset(buf, 0, BUFLEN);
+ iov.iov_base = buf;
+ iov.iov_len = BUFLEN;
+ io_prep_preadv2(&iocb, fd, &iov, 1, 0, RWF_NOWAIT);
+
+ ret = io_submit(ctx, 1, &iocbp);
+
+ /*
+ * io_submit will return -EINVAL if RWF_NOWAIT is not supported.
+ */
+ if (ret != 1) {
+ if (ret == -EINVAL) {
+ fprintf(stderr, "RWF_NOWAIT not supported by kernel.\n");
+ /* just return success */
+ return 0;
+ }
+ errno = -ret;
+ perror("io_submit");
+ return 1;
+ }
+
+ ret = io_getevents(ctx, 1, 1, &event, NULL);
+ if (ret != 1) {
+ errno = -ret;
+ perror("io_getevents");
+ return 1;
+ }
+
+ /*
+ * We expect -EAGAIN due to the existence of a page cache page
+ * for the file system block we are writing.
+ */
+ if (event.res != -EAGAIN) {
+ fprintf(stderr, "Expected -EAGAIN, got %lu\n", event.res);
+ return 1;
+ }
+
+ /*
+ * An O_DIRECT write to the page will force the page out of the
+ * page cache, allowing the subsequent RWF_NOWAIT I/O to complete.
+ */
+ ret = pwrite(fd, buf, BUFLEN, 0);
+ if (ret != BUFLEN) {
+ perror("write");
+ return 1;
+ }
+
+ /*
+ * Now retry the RWF_NOWAIT I/O. This should succeed.
+ */
+ ret = io_submit(ctx, 1, &iocbp);
+ if (ret != 1) {
+ errno = -ret;
+ perror("io_submit");
+ return 1;
+ }
+
+ ret = io_getevents(ctx, 1, 1, &event, NULL);
+ if (ret != 1) {
+ errno = -ret;
+ perror("io_getevents");
+ return 1;
+ }
+
+ if (event.res != BUFLEN) {
+ fprintf(stderr, "Expected %d, got %lu\n", BUFLEN, event.res);
+ return 1;
+ }
+
+ return 0;
+}
+/*
+ * Local variables:
+ * mode: c
+ * c-basic-offset: 8
+ * End:
+ */
{
long long min = 0, max = 9223372036854775807LL;
char c = 0;
+ int ret;
while (max - min > 1) {
if (pwrite64(fd, &c, 1, (min + max) / 2) == -1)
max = (min + max) / 2;
else {
- ftruncate(fd, 0);
+ ret = ftruncate(fd, 0);
+ assert(ret == 0);
min = (min + max) / 2;
}
}
Name: libaio
-Version: 0.3.110
+Version: 0.3.111
Release: 1
Summary: Linux-native asynchronous I/O access library
License: LGPL
%attr(0644,root,root) %{_libdir}/libaio.a
%changelog
+* Tue Mar 6 2018 Jeff Moyer <jmoyer@redhat.com> - 0.3.111-1
+- Add two new tests to the test harness (Jeff Moyer)
+- Generic arch dectection for padding defines (Nathan Rossi)
+- harness: don't hardcode page size (Jeff Moyer)
+- harness: add a test case for mremap (Jeff Moyer)
+- libaio: harness: fix build errors due to attribute warn_unused_result (Mauricio Faria de Oliveira)
+- libaio: harness: fix build error due to linker search order (Mauricio Faria de Oliveira)
+- harness: add test for allocating aio-max-nr ioctxs (Jeff Moyer)
+- Add support for preadv2/pwritev2 (Jeff Moyer)
+- syscall-generic: don't overwrite errno (Jeff Moyer)
+- syscall: get rid of custom syscall implementation (Jeff Moyer)
+- Change syscall-arm64.h to syscall-generic.h (Icenowy Zheng)
+- Use generic syscall number schema for RISC-V (Icenowy Zheng)
+- Add endian detection (LE) and bit width detection (32/64) for RISC-V (Icenowy Zheng)
+- Makefile: convert tag and archive targets to git (Jeff Moyer)
+
* Fri Jul 5 2013 Jeff Moyer <jmoyer@redhat.com> - 0.3.110-1
- Add suport for sparc and arm64 (Mike Frysinger and Jeff Moyer)
- Add generic syscall fallbacks (Mike Frysinger)
/* little endian, 32 bits */
#if defined(__i386__) || (defined(__arm__) && !defined(__ARMEB__)) || \
defined(__sh__) || defined(__bfin__) || defined(__MIPSEL__) || \
- defined(__cris__)
+ defined(__cris__) || (defined(__riscv) && __riscv_xlen == 32) || \
+ (defined(__GNUC__) && defined(__BYTE_ORDER__) && \
+ __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_LONG__ == 4)
#define PADDED(x, y) x; unsigned y
#define PADDEDptr(x, y) x; unsigned y
#define PADDEDul(x, y) unsigned long x; unsigned y
/* little endian, 64 bits */
#elif defined(__ia64__) || defined(__x86_64__) || defined(__alpha__) || \
- (defined(__aarch64__) && defined(__AARCH64EL__))
+ (defined(__aarch64__) && defined(__AARCH64EL__)) || \
+ (defined(__riscv) && __riscv_xlen == 64) || \
+ (defined(__GNUC__) && defined(__BYTE_ORDER__) && \
+ __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ && __SIZEOF_LONG__ == 8)
#define PADDED(x, y) x, y
#define PADDEDptr(x, y) x
#define PADDEDul(x, y) unsigned long x
/* big endian, 64 bits */
#elif defined(__powerpc64__) || defined(__s390x__) || \
(defined(__sparc__) && defined(__arch64__)) || \
- (defined(__aarch64__) && defined(__AARCH64EB__))
+ (defined(__aarch64__) && defined(__AARCH64EB__)) || \
+ (defined(__GNUC__) && defined(__BYTE_ORDER__) && \
+ __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_LONG__ == 8)
#define PADDED(x, y) unsigned y; x
#define PADDEDptr(x,y) x
#define PADDEDul(x, y) unsigned long x
#elif defined(__PPC__) || defined(__s390__) || \
(defined(__arm__) && defined(__ARMEB__)) || \
defined(__sparc__) || defined(__MIPSEB__) || defined(__m68k__) || \
- defined(__hppa__) || defined(__frv__) || defined(__avr32__)
+ defined(__hppa__) || defined(__frv__) || defined(__avr32__) || \
+ (defined(__GNUC__) && defined(__BYTE_ORDER__) && \
+ __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ && __SIZEOF_LONG__ == 4)
#define PADDED(x, y) unsigned y; x
#define PADDEDptr(x, y) unsigned y; x
#define PADDEDul(x, y) unsigned y; unsigned long x
struct iocb {
PADDEDptr(void *data, __pad1); /* Return in the io completion event */
- PADDED(unsigned key, __pad2); /* For use in identifying io requests */
+ /* key: For use in identifying io requests */
+ /* aio_rw_flags: RWF_* flags (such as RWF_NOWAIT) */
+ PADDED(unsigned key, aio_rw_flags);
short aio_lio_opcode;
short aio_reqprio;
iocb->u.c.offset = offset;
}
+static inline void io_prep_preadv2(struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, long long offset, int flags)
+{
+ memset(iocb, 0, sizeof(*iocb));
+ iocb->aio_fildes = fd;
+ iocb->aio_lio_opcode = IO_CMD_PREADV;
+ iocb->aio_reqprio = 0;
+ iocb->aio_rw_flags = flags;
+ iocb->u.c.buf = (void *)iov;
+ iocb->u.c.nbytes = iovcnt;
+ iocb->u.c.offset = offset;
+}
+
+static inline void io_prep_pwritev2(struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, long long offset, int flags)
+{
+ memset(iocb, 0, sizeof(*iocb));
+ iocb->aio_fildes = fd;
+ iocb->aio_lio_opcode = IO_CMD_PWRITEV;
+ iocb->aio_reqprio = 0;
+ iocb->aio_rw_flags = flags;
+ iocb->u.c.buf = (void *)iov;
+ iocb->u.c.nbytes = iovcnt;
+ iocb->u.c.offset = offset;
+}
+
/* Jeff Moyer says this was implemented in Red Hat AS2.1 and RHEL3.
* AFAICT, it was never in mainline, and should not be used. --RR */
static inline void io_prep_poll(struct iocb *iocb, int fd, int events)
#define __NR_io_getevents 400
#define __NR_io_submit 401
#define __NR_io_cancel 402
-
-#define inline_syscall_r0_asm
-#define inline_syscall_r0_out_constraint "=v"
-
-#define inline_syscall_clobbers \
- "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \
- "$22", "$23", "$24", "$25", "$27", "$28", "memory"
-
-#define inline_syscall0(name, args...) \
-{ \
- register long _sc_0 inline_syscall_r0_asm; \
- register long _sc_19 __asm__("$19"); \
- \
- _sc_0 = name; \
- __asm__ __volatile__ \
- ("callsys # %0 %1 <= %2" \
- : inline_syscall_r0_out_constraint (_sc_0), \
- "=r"(_sc_19) \
- : "0"(_sc_0) \
- : inline_syscall_clobbers, \
- "$16", "$17", "$18", "$20", "$21"); \
- _sc_ret = _sc_0, _sc_err = _sc_19; \
-}
-
-#define inline_syscall1(name,arg1) \
-{ \
- register long _sc_0 inline_syscall_r0_asm; \
- register long _sc_16 __asm__("$16"); \
- register long _sc_19 __asm__("$19"); \
- \
- _sc_0 = name; \
- _sc_16 = (long) (arg1); \
- __asm__ __volatile__ \
- ("callsys # %0 %1 <= %2 %3" \
- : inline_syscall_r0_out_constraint (_sc_0), \
- "=r"(_sc_19), "=r"(_sc_16) \
- : "0"(_sc_0), "2"(_sc_16) \
- : inline_syscall_clobbers, \
- "$17", "$18", "$20", "$21"); \
- _sc_ret = _sc_0, _sc_err = _sc_19; \
-}
-
-#define inline_syscall2(name,arg1,arg2) \
-{ \
- register long _sc_0 inline_syscall_r0_asm; \
- register long _sc_16 __asm__("$16"); \
- register long _sc_17 __asm__("$17"); \
- register long _sc_19 __asm__("$19"); \
- \
- _sc_0 = name; \
- _sc_16 = (long) (arg1); \
- _sc_17 = (long) (arg2); \
- __asm__ __volatile__ \
- ("callsys # %0 %1 <= %2 %3 %4" \
- : inline_syscall_r0_out_constraint (_sc_0), \
- "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17) \
- : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17) \
- : inline_syscall_clobbers, \
- "$18", "$20", "$21"); \
- _sc_ret = _sc_0, _sc_err = _sc_19; \
-}
-
-#define inline_syscall3(name,arg1,arg2,arg3) \
-{ \
- register long _sc_0 inline_syscall_r0_asm; \
- register long _sc_16 __asm__("$16"); \
- register long _sc_17 __asm__("$17"); \
- register long _sc_18 __asm__("$18"); \
- register long _sc_19 __asm__("$19"); \
- \
- _sc_0 = name; \
- _sc_16 = (long) (arg1); \
- _sc_17 = (long) (arg2); \
- _sc_18 = (long) (arg3); \
- __asm__ __volatile__ \
- ("callsys # %0 %1 <= %2 %3 %4 %5" \
- : inline_syscall_r0_out_constraint (_sc_0), \
- "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \
- "=r"(_sc_18) \
- : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), \
- "4"(_sc_18) \
- : inline_syscall_clobbers, "$20", "$21"); \
- _sc_ret = _sc_0, _sc_err = _sc_19; \
-}
-
-#define inline_syscall4(name,arg1,arg2,arg3,arg4) \
-{ \
- register long _sc_0 inline_syscall_r0_asm; \
- register long _sc_16 __asm__("$16"); \
- register long _sc_17 __asm__("$17"); \
- register long _sc_18 __asm__("$18"); \
- register long _sc_19 __asm__("$19"); \
- \
- _sc_0 = name; \
- _sc_16 = (long) (arg1); \
- _sc_17 = (long) (arg2); \
- _sc_18 = (long) (arg3); \
- _sc_19 = (long) (arg4); \
- __asm__ __volatile__ \
- ("callsys # %0 %1 <= %2 %3 %4 %5 %6" \
- : inline_syscall_r0_out_constraint (_sc_0), \
- "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \
- "=r"(_sc_18) \
- : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), \
- "4"(_sc_18), "1"(_sc_19) \
- : inline_syscall_clobbers, "$20", "$21"); \
- _sc_ret = _sc_0, _sc_err = _sc_19; \
-}
-
-#define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5) \
-{ \
- register long _sc_0 inline_syscall_r0_asm; \
- register long _sc_16 __asm__("$16"); \
- register long _sc_17 __asm__("$17"); \
- register long _sc_18 __asm__("$18"); \
- register long _sc_19 __asm__("$19"); \
- register long _sc_20 __asm__("$20"); \
- \
- _sc_0 = name; \
- _sc_16 = (long) (arg1); \
- _sc_17 = (long) (arg2); \
- _sc_18 = (long) (arg3); \
- _sc_19 = (long) (arg4); \
- _sc_20 = (long) (arg5); \
- __asm__ __volatile__ \
- ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7" \
- : inline_syscall_r0_out_constraint (_sc_0), \
- "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \
- "=r"(_sc_18), "=r"(_sc_20) \
- : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), \
- "4"(_sc_18), "1"(_sc_19), "5"(_sc_20) \
- : inline_syscall_clobbers, "$21"); \
- _sc_ret = _sc_0, _sc_err = _sc_19; \
-}
-
-#define inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6) \
-{ \
- register long _sc_0 inline_syscall_r0_asm; \
- register long _sc_16 __asm__("$16"); \
- register long _sc_17 __asm__("$17"); \
- register long _sc_18 __asm__("$18"); \
- register long _sc_19 __asm__("$19"); \
- register long _sc_20 __asm__("$20"); \
- register long _sc_21 __asm__("$21"); \
- \
- _sc_0 = name; \
- _sc_16 = (long) (arg1); \
- _sc_17 = (long) (arg2); \
- _sc_18 = (long) (arg3); \
- _sc_19 = (long) (arg4); \
- _sc_20 = (long) (arg5); \
- _sc_21 = (long) (arg6); \
- __asm__ __volatile__ \
- ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7 %8" \
- : inline_syscall_r0_out_constraint (_sc_0), \
- "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17), \
- "=r"(_sc_18), "=r"(_sc_20), "=r"(_sc_21) \
- : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), "4"(_sc_18), \
- "1"(_sc_19), "5"(_sc_20), "6"(_sc_21) \
- : inline_syscall_clobbers); \
- _sc_ret = _sc_0, _sc_err = _sc_19; \
-}
-
-#define INLINE_SYSCALL1(name, nr, args...) \
-({ \
- long _sc_ret, _sc_err; \
- inline_syscall##nr(__NR_##name, args); \
- if (_sc_err != 0) \
- { \
- _sc_ret = -(_sc_ret); \
- } \
- _sc_ret; \
-})
-
-#define io_syscall1(type,fname,sname,type1,arg1) \
-type fname(type1 arg1) \
-{ \
- return (type)INLINE_SYSCALL1(sname, 1, arg1); \
-}
-
-#define io_syscall2(type,fname,sname,type1,arg1,type2,arg2) \
-type fname(type1 arg1,type2 arg2) \
-{ \
- return (type)INLINE_SYSCALL1(sname, 2, arg1, arg2); \
-}
-
-#define io_syscall3(type,fname,sname,type1,arg1,type2,arg2,type3,arg3) \
-type fname(type1 arg1,type2 arg2,type3 arg3) \
-{ \
- return (type)INLINE_SYSCALL1(sname, 3, arg1, arg2, arg3); \
-}
-
-#define io_syscall4(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type fname (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
-{ \
- return (type)INLINE_SYSCALL1(sname, 4, arg1, arg2, arg3, arg4); \
-}
-
-#define io_syscall5(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5) \
-type fname (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
-{ \
- return (type)INLINE_SYSCALL1(sname, 5, arg1, arg2, arg3, arg4, arg5);\
-}
#define __NR_io_getevents (__NR_SYSCALL_BASE+245)
#define __NR_io_submit (__NR_SYSCALL_BASE+246)
#define __NR_io_cancel (__NR_SYSCALL_BASE+247)
-
-#define __sys2(x) #x
-#define __sys1(x) __sys2(x)
-
-#if defined(__thumb__) || defined(__ARM_EABI__)
-#define __SYS_REG(name) register long __sysreg __asm__("r7") = __NR_##name;
-#define __SYS_REG_LIST(regs...) "r" (__sysreg) , ##regs
-#define __syscall(name) "swi\t0"
-#else
-#define __SYS_REG(name)
-#define __SYS_REG_LIST(regs...) regs
-#define __syscall(name) "swi\t" __sys1(__NR_##name) ""
-#endif
-
-#define io_syscall1(type,fname,sname,type1,arg1) \
-type fname(type1 arg1) { \
- __SYS_REG(sname) \
- register long __r0 __asm__("r0") = (long)arg1; \
- register long __res_r0 __asm__("r0"); \
- __asm__ __volatile__ ( \
- __syscall(sname) \
- : "=r" (__res_r0) \
- : __SYS_REG_LIST( "0" (__r0) ) \
- : "memory" ); \
- return (type) __res_r0; \
-}
-
-#define io_syscall2(type,fname,sname,type1,arg1,type2,arg2) \
-type fname(type1 arg1,type2 arg2) { \
- __SYS_REG(sname) \
- register long __r0 __asm__("r0") = (long)arg1; \
- register long __r1 __asm__("r1") = (long)arg2; \
- register long __res_r0 __asm__("r0"); \
- __asm__ __volatile__ ( \
- __syscall(sname) \
- : "=r" (__res_r0) \
- : __SYS_REG_LIST( "0" (__r0), "r" (__r1) ) \
- : "memory" ); \
- return (type) __res_r0; \
-}
-
-#define io_syscall3(type,fname,sname,type1,arg1,type2,arg2,type3,arg3) \
-type fname(type1 arg1,type2 arg2,type3 arg3) { \
- __SYS_REG(sname) \
- register long __r0 __asm__("r0") = (long)arg1; \
- register long __r1 __asm__("r1") = (long)arg2; \
- register long __r2 __asm__("r2") = (long)arg3; \
- register long __res_r0 __asm__("r0"); \
- __asm__ __volatile__ ( \
- __syscall(sname) \
- : "=r" (__res_r0) \
- : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2) ) \
- : "memory" ); \
- return (type) __res_r0; \
-}
-
-#define io_syscall4(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\
-type fname(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
- __SYS_REG(sname) \
- register long __r0 __asm__("r0") = (long)arg1; \
- register long __r1 __asm__("r1") = (long)arg2; \
- register long __r2 __asm__("r2") = (long)arg3; \
- register long __r3 __asm__("r3") = (long)arg4; \
- register long __res_r0 __asm__("r0"); \
- __asm__ __volatile__ ( \
- __syscall(sname) \
- : "=r" (__res_r0) \
- : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), "r" (__r3) ) \
- : "memory" ); \
- return (type) __res_r0; \
-}
-
-#define io_syscall5(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
-type fname(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) {\
- __SYS_REG(sname) \
- register long __r0 __asm__("r0") = (long)arg1; \
- register long __r1 __asm__("r1") = (long)arg2; \
- register long __r2 __asm__("r2") = (long)arg3; \
- register long __r3 __asm__("r3") = (long)arg4; \
- register long __r4 __asm__("r4") = (long)arg5; \
- register long __res_r0 __asm__("r0"); \
- __asm__ __volatile__ ( \
- __syscall(sname) \
- : "=r" (__res_r0) \
- : __SYS_REG_LIST( "0" (__r0), "r" (__r1), "r" (__r2), \
- "r" (__r3), "r" (__r4) ) \
- : "memory" ); \
- return (type) __res_r0; \
-}
-
+++ /dev/null
-/*
- * linux/include/asm-arm/unistd.h
- *
- * Copyright (C) 2001-2005 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Please forward _all_ changes to this file to rmk@arm.linux.org.uk,
- * no matter what the change is. Thanks!
- */
-
-#define __NR_io_setup 0
-#define __NR_io_destroy 1
-#define __NR_io_submit 2
-#define __NR_io_cancel 3
-#define __NR_io_getevents 4
-
-#define __sys2(x) #x
-#define __sys1(x) __sys2(x)
-
-#define __SYS_REG(name) register long __sysreg __asm__("w8") = __NR_##name;
-#define __SYS_REG_LIST(regs...) "r" (__sysreg) , ##regs
-#define __syscall(name) "svc\t#0"
-
-#define io_syscall1(type,fname,sname,type1,arg1) \
-type fname(type1 arg1) { \
- __SYS_REG(sname) \
- register long __x0 __asm__("x0") = (long)arg1; \
- register long __res_x0 __asm__("x0"); \
- __asm__ __volatile__ ( \
- __syscall(sname) \
- : "=r" (__res_x0) \
- : __SYS_REG_LIST( "0" (__x0) ) \
- : "memory" ); \
- return (type) __res_x0; \
-}
-
-#define io_syscall2(type,fname,sname,type1,arg1,type2,arg2) \
-type fname(type1 arg1,type2 arg2) { \
- __SYS_REG(sname) \
- register long __x0 __asm__("x0") = (long)arg1; \
- register long __x1 __asm__("x1") = (long)arg2; \
- register long __res_x0 __asm__("x0"); \
- __asm__ __volatile__ ( \
- __syscall(sname) \
- : "=r" (__res_x0) \
- : __SYS_REG_LIST( "0" (__x0), "r" (__x1) ) \
- : "memory" ); \
- return (type) __res_x0; \
-}
-
-#define io_syscall3(type,fname,sname,type1,arg1,type2,arg2,type3,arg3) \
-type fname(type1 arg1,type2 arg2,type3 arg3) { \
- __SYS_REG(sname) \
- register long __x0 __asm__("x0") = (long)arg1; \
- register long __x1 __asm__("x1") = (long)arg2; \
- register long __x2 __asm__("x2") = (long)arg3; \
- register long __res_x0 __asm__("x0"); \
- __asm__ __volatile__ ( \
- __syscall(sname) \
- : "=r" (__res_x0) \
- : __SYS_REG_LIST( "0" (__x0), "r" (__x1), "r" (__x2) ) \
- : "memory" ); \
- return (type) __res_x0; \
-}
-
-#define io_syscall4(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4)\
-type fname(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
- __SYS_REG(sname) \
- register long __x0 __asm__("x0") = (long)arg1; \
- register long __x1 __asm__("x1") = (long)arg2; \
- register long __x2 __asm__("x2") = (long)arg3; \
- register long __x3 __asm__("x3") = (long)arg4; \
- register long __res_x0 __asm__("x0"); \
- __asm__ __volatile__ ( \
- __syscall(sname) \
- : "=r" (__res_x0) \
- : __SYS_REG_LIST( "0" (__x0), "r" (__x1), "r" (__x2), "r" (__x3) ) \
- : "memory" ); \
- return (type) __res_x0; \
-}
-
-#define io_syscall5(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
-type fname(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) {\
- __SYS_REG(sname) \
- register long __x0 __asm__("x0") = (long)arg1; \
- register long __x1 __asm__("x1") = (long)arg2; \
- register long __x2 __asm__("x2") = (long)arg3; \
- register long __x3 __asm__("x3") = (long)arg4; \
- register long __x4 __asm__("x4") = (long)arg5; \
- register long __res_x0 __asm__("x0"); \
- __asm__ __volatile__ ( \
- __syscall(sname) \
- : "=r" (__res_x0) \
- : __SYS_REG_LIST( "0" (__x0), "r" (__x1), "r" (__x2), \
- "r" (__x3), "r" (__x4) ) \
- : "memory" ); \
- return (type) __res_x0; \
-}
-#include <errno.h>
-#include <unistd.h>
-#include <sys/syscall.h>
-
-#define _body_io_syscall(sname, args...) \
-{ \
- int ret = syscall(__NR_##sname, ## args); \
- return ret < 0 ? -errno : ret; \
-}
-
-#define io_syscall1(type,fname,sname,type1,arg1) \
-type fname(type1 arg1) \
-_body_io_syscall(sname, (long)arg1)
-
-#define io_syscall2(type,fname,sname,type1,arg1,type2,arg2) \
-type fname(type1 arg1,type2 arg2) \
-_body_io_syscall(sname, (long)arg1, (long)arg2)
-
-#define io_syscall3(type,fname,sname,type1,arg1,type2,arg2,type3,arg3) \
-type fname(type1 arg1,type2 arg2,type3 arg3) \
-_body_io_syscall(sname, (long)arg1, (long)arg2, (long)arg3)
-
-#define io_syscall4(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type fname (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
-_body_io_syscall(sname, (long)arg1, (long)arg2, (long)arg3, (long)arg4)
-
-#define io_syscall5(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4, type5,arg5) \
-type fname (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
-_body_io_syscall(sname, (long)arg1, (long)arg2, (long)arg3, (long)arg4, (long)arg5)
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * This is based on the include/uapi/asm-generic/unistd.h header file
+ * in the kernel, which is a generic syscall schema for new architectures.
+ */
+
+#define __NR_io_setup 0
+#define __NR_io_destroy 1
+#define __NR_io_submit 2
+#define __NR_io_cancel 3
+#define __NR_io_getevents 4
#define __NR_io_getevents 247
#define __NR_io_submit 248
#define __NR_io_cancel 249
-
-#define io_syscall1(type,fname,sname,type1,arg1) \
-type fname(type1 arg1) \
-{ \
-long __res; \
-__asm__ volatile ("xchgl %%edi,%%ebx\n" \
- "int $0x80\n" \
- "xchgl %%edi,%%ebx" \
- : "=a" (__res) \
- : "0" (__NR_##sname),"D" ((long)(arg1))); \
-return __res; \
-}
-
-#define io_syscall2(type,fname,sname,type1,arg1,type2,arg2) \
-type fname(type1 arg1,type2 arg2) \
-{ \
-long __res; \
-__asm__ volatile ("xchgl %%edi,%%ebx\n" \
- "int $0x80\n" \
- "xchgl %%edi,%%ebx" \
- : "=a" (__res) \
- : "0" (__NR_##sname),"D" ((long)(arg1)),"c" ((long)(arg2))); \
-return __res; \
-}
-
-#define io_syscall3(type,fname,sname,type1,arg1,type2,arg2,type3,arg3) \
-type fname(type1 arg1,type2 arg2,type3 arg3) \
-{ \
-long __res; \
-__asm__ volatile ("xchgl %%edi,%%ebx\n" \
- "int $0x80\n" \
- "xchgl %%edi,%%ebx" \
- : "=a" (__res) \
- : "0" (__NR_##sname),"D" ((long)(arg1)),"c" ((long)(arg2)), \
- "d" ((long)(arg3))); \
-return __res; \
-}
-
-#define io_syscall4(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type fname (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
-{ \
-long __res; \
-__asm__ volatile ("xchgl %%edi,%%ebx\n" \
- "int $0x80\n" \
- "xchgl %%edi,%%ebx" \
- : "=a" (__res) \
- : "0" (__NR_##sname),"D" ((long)(arg1)),"c" ((long)(arg2)), \
- "d" ((long)(arg3)),"S" ((long)(arg4))); \
-return __res; \
-}
-
-#define io_syscall5(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5) \
-type fname (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
-{ \
-long __res; \
-long tmp; \
-__asm__ volatile ("movl %%ebx,%7\n" \
- "movl %2,%%ebx\n" \
- "int $0x80\n" \
- "movl %7,%%ebx" \
- : "=a" (__res) \
- : "0" (__NR_##sname),"rm" ((long)(arg1)),"c" ((long)(arg2)), \
- "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \
- "m" (tmp)); \
-return __res; \
-}
#define __NR_io_getevents 1240
#define __NR_io_submit 1241
#define __NR_io_cancel 1242
-
-#define __ia64_raw_syscall(fname, sname) \
- __asm__ (".text\n" \
- ".globl " SYMSTR(fname) "\n" \
- ".proc " SYMSTR(fname) "\n" \
- SYMSTR(fname) ":\n" \
- " mov r15=" SYMSTR( __NR_ ## sname ) "\n" \
- " break 0x100000\n" \
- " ;;\n" \
- " cmp.eq p6,p0=-1,r10\n" \
- " ;;\n" \
- " (p6) sub r8=0,r8\n" \
- " br.ret.sptk.few b0\n" \
- ".size " SYMSTR(fname) ", . - " SYMSTR(fname) "\n" \
- ".endp " SYMSTR(fname) "\n" \
- );
-
-#define io_syscall0(type, name) \
- extern type name(void); \
- __ia64_raw_syscall(name);
-
-#define io_syscall1(type, fname, sname, type1, arg1) \
- extern type fname(type1 arg1); \
- __ia64_raw_syscall(fname, sname);
-
-#define io_syscall2(type, fname, sname, type1, arg1, type2, arg2) \
- extern type fname(type1 arg1, type2 arg2); \
- __ia64_raw_syscall(fname, sname);
-
-#define io_syscall3(type, fname, sname, type1, arg1, type2, arg2, type3, arg3) \
- extern type fname(type1 arg1, type2 arg2, type3 arg3); \
- __ia64_raw_syscall(fname, sname);
-
-#define io_syscall4(type, fname, sname, type1, arg1, type2, arg2, type3, arg3, type4, arg4) \
- extern type fname(type1 arg1, type2 arg2, type3 arg3, type4 arg4); \
- __ia64_raw_syscall(fname, sname);
-
-#define io_syscall5(type, fname, sname, type1, arg1, type2, arg2, type3, arg3, type4, arg4, type5, arg5) \
- extern type fname(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5); \
- __ia64_raw_syscall(fname, sname);
#define __NR_io_getevents 229
#define __NR_io_submit 230
#define __NR_io_cancel 231
-
-/* On powerpc a system call basically clobbers the same registers like a
- * function call, with the exception of LR (which is needed for the
- * "sc; bnslr" sequence) and CR (where only CR0.SO is clobbered to signal
- * an error return status).
- */
-
-#define __syscall_nr(nr, type, name, args...) \
- unsigned long __sc_ret, __sc_err; \
- { \
- register unsigned long __sc_0 __asm__ ("r0"); \
- register unsigned long __sc_3 __asm__ ("r3"); \
- register unsigned long __sc_4 __asm__ ("r4"); \
- register unsigned long __sc_5 __asm__ ("r5"); \
- register unsigned long __sc_6 __asm__ ("r6"); \
- register unsigned long __sc_7 __asm__ ("r7"); \
- register unsigned long __sc_8 __asm__ ("r8"); \
- \
- __sc_loadargs_##nr(name, args); \
- __asm__ __volatile__ \
- ("sc \n\t" \
- "mfcr %0 " \
- : "=&r" (__sc_0), \
- "=&r" (__sc_3), "=&r" (__sc_4), \
- "=&r" (__sc_5), "=&r" (__sc_6), \
- "=&r" (__sc_7), "=&r" (__sc_8) \
- : __sc_asm_input_##nr \
- : "cr0", "ctr", "memory", \
- "r9", "r10","r11", "r12"); \
- __sc_ret = __sc_3; \
- __sc_err = __sc_0; \
- } \
- if (__sc_err & 0x10000000) return -((int)__sc_ret); \
- return (type) __sc_ret
-
-#define __sc_loadargs_0(name, dummy...) \
- __sc_0 = __NR_##name
-#define __sc_loadargs_1(name, arg1) \
- __sc_loadargs_0(name); \
- __sc_3 = (unsigned long) (arg1)
-#define __sc_loadargs_2(name, arg1, arg2) \
- __sc_loadargs_1(name, arg1); \
- __sc_4 = (unsigned long) (arg2)
-#define __sc_loadargs_3(name, arg1, arg2, arg3) \
- __sc_loadargs_2(name, arg1, arg2); \
- __sc_5 = (unsigned long) (arg3)
-#define __sc_loadargs_4(name, arg1, arg2, arg3, arg4) \
- __sc_loadargs_3(name, arg1, arg2, arg3); \
- __sc_6 = (unsigned long) (arg4)
-#define __sc_loadargs_5(name, arg1, arg2, arg3, arg4, arg5) \
- __sc_loadargs_4(name, arg1, arg2, arg3, arg4); \
- __sc_7 = (unsigned long) (arg5)
-
-#define __sc_asm_input_0 "0" (__sc_0)
-#define __sc_asm_input_1 __sc_asm_input_0, "1" (__sc_3)
-#define __sc_asm_input_2 __sc_asm_input_1, "2" (__sc_4)
-#define __sc_asm_input_3 __sc_asm_input_2, "3" (__sc_5)
-#define __sc_asm_input_4 __sc_asm_input_3, "4" (__sc_6)
-#define __sc_asm_input_5 __sc_asm_input_4, "5" (__sc_7)
-
-#define io_syscall1(type,fname,sname,type1,arg1) \
-type fname(type1 arg1) \
-{ \
- __syscall_nr(1, type, sname, arg1); \
-}
-
-#define io_syscall2(type,fname,sname,type1,arg1,type2,arg2) \
-type fname(type1 arg1, type2 arg2) \
-{ \
- __syscall_nr(2, type, sname, arg1, arg2); \
-}
-
-#define io_syscall3(type,fname,sname,type1,arg1,type2,arg2,type3,arg3) \
-type fname(type1 arg1, type2 arg2, type3 arg3) \
-{ \
- __syscall_nr(3, type, sname, arg1, arg2, arg3); \
-}
-
-#define io_syscall4(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type fname(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
-{ \
- __syscall_nr(4, type, sname, arg1, arg2, arg3, arg4); \
-}
-
-#define io_syscall5(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
-type fname(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
-{ \
- __syscall_nr(5, type, sname, arg1, arg2, arg3, arg4, arg5); \
-}
#define __NR_io_getevents 245
#define __NR_io_submit 246
#define __NR_io_cancel 247
-
-#define io_svc_clobber "1", "cc", "memory"
-
-#define io_syscall1(type,fname,sname,type1,arg1) \
-type fname(type1 arg1) { \
- register type1 __arg1 asm("2") = arg1; \
- register long __svcres asm("2"); \
- long __res; \
- __asm__ __volatile__ ( \
- " .if %1 < 256\n" \
- " svc %b1\n" \
- " .else\n" \
- " la %%r1,%1\n" \
- " .svc 0\n" \
- " .endif" \
- : "=d" (__svcres) \
- : "i" (__NR_##sname), \
- "0" (__arg1) \
- : io_svc_clobber ); \
- __res = __svcres; \
- return (type) __res; \
-}
-
-#define io_syscall2(type,fname,sname,type1,arg1,type2,arg2) \
-type fname(type1 arg1, type2 arg2) { \
- register type1 __arg1 asm("2") = arg1; \
- register type2 __arg2 asm("3") = arg2; \
- register long __svcres asm("2"); \
- long __res; \
- __asm__ __volatile__ ( \
- " .if %1 < 256\n" \
- " svc %b1\n" \
- " .else\n" \
- " la %%r1,%1\n" \
- " svc 0\n" \
- " .endif" \
- : "=d" (__svcres) \
- : "i" (__NR_##sname), \
- "0" (__arg1), \
- "d" (__arg2) \
- : io_svc_clobber ); \
- __res = __svcres; \
- return (type) __res; \
-}
-
-#define io_syscall3(type,fname,sname,type1,arg1,type2,arg2, \
- type3,arg3) \
-type fname(type1 arg1, type2 arg2, type3 arg3) { \
- register type1 __arg1 asm("2") = arg1; \
- register type2 __arg2 asm("3") = arg2; \
- register type3 __arg3 asm("4") = arg3; \
- register long __svcres asm("2"); \
- long __res; \
- __asm__ __volatile__ ( \
- " .if %1 < 256\n" \
- " svc %b1\n" \
- " .else\n" \
- " la %%r1,%1\n" \
- " svc 0\n" \
- " .endif" \
- : "=d" (__svcres) \
- : "i" (__NR_##sname), \
- "0" (__arg1), \
- "d" (__arg2), \
- "d" (__arg3) \
- : io_svc_clobber ); \
- __res = __svcres; \
- return (type) __res; \
-}
-
-#define io_syscall4(type,fname,sname,type1,arg1,type2,arg2, \
- type3,arg3,type4,arg4) \
-type fname(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
- register type1 __arg1 asm("2") = arg1; \
- register type2 __arg2 asm("3") = arg2; \
- register type3 __arg3 asm("4") = arg3; \
- register type4 __arg4 asm("5") = arg4; \
- register long __svcres asm("2"); \
- long __res; \
- __asm__ __volatile__ ( \
- " .if %1 < 256\n" \
- " svc %b1\n" \
- " .else\n" \
- " la %%r1,%1\n" \
- " svc 0\n" \
- " .endif" \
- : "=d" (__svcres) \
- : "i" (__NR_##sname), \
- "0" (__arg1), \
- "d" (__arg2), \
- "d" (__arg3), \
- "d" (__arg4) \
- : io_svc_clobber ); \
- __res = __svcres; \
- return (type) __res; \
-}
-
-#define io_syscall5(type,fname,sname,type1,arg1,type2,arg2, \
- type3,arg3,type4,arg4,type5,arg5) \
-type fname(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
- type5 arg5) { \
- register type1 __arg1 asm("2") = arg1; \
- register type2 __arg2 asm("3") = arg2; \
- register type3 __arg3 asm("4") = arg3; \
- register type4 __arg4 asm("5") = arg4; \
- register type5 __arg5 asm("6") = arg5; \
- register long __svcres asm("2"); \
- long __res; \
- __asm__ __volatile__ ( \
- " .if %1 < 256\n" \
- " svc %b1\n" \
- " .else\n" \
- " la %%r1,%1\n" \
- " svc 0\n" \
- " .endif" \
- : "=d" (__svcres) \
- : "i" (__NR_##sname), \
- "0" (__arg1), \
- "d" (__arg2), \
- "d" (__arg3), \
- "d" (__arg4), \
- "d" (__arg5) \
- : io_svc_clobber ); \
- __res = __svcres; \
- return (type) __res; \
-}
-#include <errno.h>
-
#define __NR_io_setup 268
#define __NR_io_destroy 269
#define __NR_io_submit 270
#define __NR_io_cancel 271
#define __NR_io_getevents 272
-
-#define io_syscall1(type,fname,sname,type1,arg1) \
-type fname(type1 arg1) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##sname; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-__asm__ __volatile__ ("t 0x10\n\t" \
- "bcc 1f\n\t" \
- "mov %%o0, %0\n\t" \
- "sub %%g0, %%o0, %0\n\t" \
- "1:\n\t" \
- : "=r" (__res), "=&r" (__o0) \
- : "1" (__o0), "r" (__g1) \
- : "cc"); \
-return (type) __res; \
-}
-
-#define io_syscall2(type,fname,sname,type1,arg1,type2,arg2) \
-type fname(type1 arg1,type2 arg2) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##sname; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-register long __o1 __asm__ ("o1") = (long)(arg2); \
-__asm__ __volatile__ ("t 0x10\n\t" \
- "bcc 1f\n\t" \
- "mov %%o0, %0\n\t" \
- "sub %%g0, %%o0, %0\n\t" \
- "1:\n\t" \
- : "=r" (__res), "=&r" (__o0) \
- : "1" (__o0), "r" (__o1), "r" (__g1) \
- : "cc"); \
-return (type) __res; \
-}
-
-#define io_syscall3(type,fname,sname,type1,arg1,type2,arg2,type3,arg3) \
-type fname(type1 arg1,type2 arg2,type3 arg3) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##sname; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-register long __o1 __asm__ ("o1") = (long)(arg2); \
-register long __o2 __asm__ ("o2") = (long)(arg3); \
-__asm__ __volatile__ ("t 0x10\n\t" \
- "bcc 1f\n\t" \
- "mov %%o0, %0\n\t" \
- "sub %%g0, %%o0, %0\n\t" \
- "1:\n\t" \
- : "=r" (__res), "=&r" (__o0) \
- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \
- : "cc"); \
-return (type) __res; \
-}
-
-#define io_syscall4(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type fname (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##sname; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-register long __o1 __asm__ ("o1") = (long)(arg2); \
-register long __o2 __asm__ ("o2") = (long)(arg3); \
-register long __o3 __asm__ ("o3") = (long)(arg4); \
-__asm__ __volatile__ ("t 0x10\n\t" \
- "bcc 1f\n\t" \
- "mov %%o0, %0\n\t" \
- "sub %%g0, %%o0, %0\n\t" \
- "1:\n\t" \
- : "=r" (__res), "=&r" (__o0) \
- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \
- : "cc"); \
-return (type) __res; \
-}
-
-#define io_syscall5(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5) \
-type fname (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
-{ \
-long __res; \
-register long __g1 __asm__ ("g1") = __NR_##sname; \
-register long __o0 __asm__ ("o0") = (long)(arg1); \
-register long __o1 __asm__ ("o1") = (long)(arg2); \
-register long __o2 __asm__ ("o2") = (long)(arg3); \
-register long __o3 __asm__ ("o3") = (long)(arg4); \
-register long __o4 __asm__ ("o4") = (long)(arg5); \
-__asm__ __volatile__ ("t 0x10\n\t" \
- "bcc 1f\n\t" \
- "mov %%o0, %0\n\t" \
- "sub %%g0, %%o0, %0\n\t" \
- "1:\n\t" \
- : "=r" (__res), "=&r" (__o0) \
- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \
- : "cc"); \
-return (type) __res; \
-}
#define __NR_io_getevents 208
#define __NR_io_submit 209
#define __NR_io_cancel 210
-
-#define __syscall_clobber "r11","rcx","memory"
-#define __syscall "syscall"
-
-#define io_syscall1(type,fname,sname,type1,arg1) \
-type fname(type1 arg1) \
-{ \
-long __res; \
-__asm__ volatile (__syscall \
- : "=a" (__res) \
- : "0" (__NR_##sname),"D" ((long)(arg1)) : __syscall_clobber ); \
-return __res; \
-}
-
-#define io_syscall2(type,fname,sname,type1,arg1,type2,arg2) \
-type fname(type1 arg1,type2 arg2) \
-{ \
-long __res; \
-__asm__ volatile (__syscall \
- : "=a" (__res) \
- : "0" (__NR_##sname),"D" ((long)(arg1)),"S" ((long)(arg2)) : __syscall_clobber ); \
-return __res; \
-}
-
-#define io_syscall3(type,fname,sname,type1,arg1,type2,arg2,type3,arg3) \
-type fname(type1 arg1,type2 arg2,type3 arg3) \
-{ \
-long __res; \
-__asm__ volatile (__syscall \
- : "=a" (__res) \
- : "0" (__NR_##sname),"D" ((long)(arg1)),"S" ((long)(arg2)), \
- "d" ((long)(arg3)) : __syscall_clobber); \
-return __res; \
-}
-
-#define io_syscall4(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-type fname (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
-{ \
-long __res; \
-__asm__ volatile ("movq %5,%%r10 ;" __syscall \
- : "=a" (__res) \
- : "0" (__NR_##sname),"D" ((long)(arg1)),"S" ((long)(arg2)), \
- "d" ((long)(arg3)),"g" ((long)(arg4)) : __syscall_clobber,"r10" ); \
-return __res; \
-}
-
-#define io_syscall5(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
- type5,arg5) \
-type fname (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
-{ \
-long __res; \
-__asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " __syscall \
- : "=a" (__res) \
- : "0" (__NR_##sname),"D" ((long)(arg1)),"S" ((long)(arg2)), \
- "d" ((long)(arg3)),"g" ((long)(arg4)),"g" ((long)(arg5)) : \
- __syscall_clobber,"r8","r10" ); \
-return __res; \
-}
#include <sys/syscall.h>
#include <unistd.h>
+#include <errno.h>
#define _SYMSTR(str) #str
#define SYMSTR(str) _SYMSTR(str)
#include "syscall-arm.h"
#elif defined(__sparc__)
#include "syscall-sparc.h"
-#elif defined(__aarch64__)
-#include "syscall-arm64.h"
-#else
-#warning "using generic syscall method"
+#elif defined(__aarch64__) || defined(__riscv)
#include "syscall-generic.h"
+#else
+#warning "using system call numbers from sys/syscall.h"
#endif
+
+#define _body_io_syscall(sname, args...) \
+{ \
+ int ret, saved_errno; \
+ saved_errno = errno; \
+ ret= syscall(__NR_##sname, ## args); \
+ if (ret < 0) { \
+ ret = -errno; \
+ errno = saved_errno; \
+ } \
+ return ret; \
+}
+
+#define io_syscall1(type,fname,sname,type1,arg1) \
+type fname(type1 arg1) \
+_body_io_syscall(sname, (long)arg1)
+
+#define io_syscall2(type,fname,sname,type1,arg1,type2,arg2) \
+type fname(type1 arg1,type2 arg2) \
+_body_io_syscall(sname, (long)arg1, (long)arg2)
+
+#define io_syscall3(type,fname,sname,type1,arg1,type2,arg2,type3,arg3) \
+type fname(type1 arg1,type2 arg2,type3 arg3) \
+_body_io_syscall(sname, (long)arg1, (long)arg2, (long)arg3)
+
+#define io_syscall4(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type fname (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+_body_io_syscall(sname, (long)arg1, (long)arg2, (long)arg3, (long)arg4)
+
+#define io_syscall5(type,fname,sname,type1,arg1,type2,arg2,type3,arg3,type4,arg4, type5,arg5) \
+type fname (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
+_body_io_syscall(sname, (long)arg1, (long)arg2, (long)arg3, (long)arg4, (long)arg5)