librt: Initial userland implementation of POSIX AIO functionality.
authorVenkatesh Srinivas <me@endeavour.zapto.org>
Thu, 17 Feb 2011 18:03:42 +0000 (10:03 -0800)
committerVenkatesh Srinivas <me@endeavour.zapto.org>
Thu, 17 Feb 2011 18:03:42 +0000 (10:03 -0800)
Issues synchronous IO requests in response to AIO calls; does not
support SIGEV_THREAD or SIGEV_SIGNAL; the former because our
infrastructure doesn't have SIGEV_THREAD already; the latter
because we do not support sigqueue() or sending signals w/ a
sigval payload.

lib/librt/Makefile
lib/librt/aio.c [new file with mode: 0644]
sys/kern/kern_exec.c
sys/kern/kern_exit.c
sys/sys/aio.h

index 163ba02..defdab9 100644 (file)
@@ -2,7 +2,7 @@ LIB=rt
 SHLIB_MAJOR=0
 WARNS?=2
 
-SRCS+= mq.c
+SRCS+= mq.c aio.c
 
 MAN+=  mq_close.2 mq_getattr.2 mq_notify.2 mq_open.2 mq_receive.2 \
        mq_send.2 mq_setattr.2 mq_unlink.2
diff --git a/lib/librt/aio.c b/lib/librt/aio.c
new file mode 100644 (file)
index 0000000..487aa66
--- /dev/null
@@ -0,0 +1,212 @@
+/*-
+ * Copyright (c) 2011 Venkatesh Srinivas <vsrinivas@dragonflybsd.org>  
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ */
+
+/*
+ * This file contains support for the POSIX 1003.1B AIO/LIO facility.
+ *
+ * This version of AIO is aimed at standards compliance; it is not aimed
+ * at either reasonability or performance. It merely wraps synchronous I/O
+ * routines.
+ *
+ * This version cannot perform asynchronous notification of I/O completion
+ * on DragonFly via SIGEV_THREAD or SIGEV_SIGNAL.
+ *
+ *    1) SIGEV_THREAD is not supported by DFly's sigevent structure or any
+ *      other machinery in libthread or librt.
+ *
+ *    2) SIGEV_SIGNAL code is present, but if-ed out under 'notyet'; Dfly
+ *      does not support sigqueue(), so we cannot control the payload to
+ *      a SIGINFO-signal from userspace. Programs using AIO signals use
+ *      the payload field to carry pointers to the completed AIO structure,
+ *      which is not yet possible here.
+ *
+ * It would be possible for this version to support SIGEV_KEVENT.
+ */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/signal.h>
+#include <sys/queue.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/aio.h>
+
+static void
+_aio_signal(struct aiocb *ap)
+{
+#ifdef notyet
+       int sig;
+       union sigval sv;
+       pid_t pid;
+
+       if (ap->aio_sigevent.sigev_notify == SIGEV_NONE)
+               return;
+
+       sig = ap->aio_sigevent.sigev_signo;
+       sv = ap->aio_sigevent.sigev_value;
+       
+       sigqueue(pid, sig, sv);
+#endif
+}
+
+static void
+_lio_signal(struct sigevent *sigevp)
+{
+#ifdef notyet
+       int sig;
+       union sigval sv;
+       pid_t pid;
+
+       pid = getpid();
+       sig = sigevp->sigev_signo;
+       sv = sigevp->sigev_value;
+
+       sigqueue(pid, sig, sv);
+#endif
+}
+
+/*
+ * aio_read()
+ *
+ *     Asynchronously read from a file
+ */
+int 
+aio_read(struct aiocb *ap)
+{
+#ifndef notyet
+       if (ap->aio_sigevent.sigev_notify != SIGEV_NONE)
+               return (ENOSYS);
+#endif
+
+       ap->_aio_val = pread(ap->aio_fildes, 
+                            (void *) ap->aio_buf, 
+                            ap->aio_nbytes,
+                            ap->aio_offset);
+       ap->_aio_err = errno;
+
+       _aio_signal(ap);
+
+       return (0);
+}
+
+int 
+aio_write(struct aiocb *ap)
+{
+#ifndef notyet
+       if (ap->aio_sigevent.sigev_notify != SIGEV_NONE)
+               return (ENOSYS);
+#endif
+
+       ap->_aio_val = pwrite(ap->aio_fildes,
+                             (void *) ap->aio_buf, 
+                             ap->aio_nbytes,
+                             ap->aio_offset);
+       ap->_aio_err = errno;
+
+       _aio_signal(ap);
+
+       return (0);
+}
+
+int
+aio_fsync(int op, struct aiocb *ap)
+{
+#ifndef notyet
+       if (ap->aio_sigevent.sigev_notify != SIGEV_NONE)
+               return (ENOSYS);
+#endif
+
+       ap->_aio_val = fsync(ap->aio_fildes);
+       ap->_aio_err = errno;
+
+       _aio_signal(ap);
+
+       return(0);
+}
+
+int 
+lio_listio(int mode, struct aiocb *const apv[], int nent, 
+          struct sigevent *sigevp)
+{
+       int i;
+
+#ifndef notyet
+       if (sigevp && sigevp->sigev_notify != SIGEV_NONE)
+               return (ENOSYS);
+#endif
+
+       for (i = 0; i < nent; i++)
+               switch (apv[i]->aio_lio_opcode) {
+               case LIO_READ:
+                       aio_read(apv[i]);
+                       break;
+               case LIO_WRITE:
+                       aio_write(apv[i]);
+                       break;
+               case LIO_NOP:
+                       break;
+               }
+
+       if (sigevp && 
+           (mode == LIO_NOWAIT) &&
+           (sigevp->sigev_notify == SIGEV_SIGNAL)
+          ) {
+               _lio_signal(sigevp);
+       }
+
+       return (0);
+}
+
+/*
+ * aio_error()
+ *
+ *     Get I/O completion status
+ *
+ *      Returns EINPROGRESS until I/O is complete. Returns ECANCELED if
+ *     I/O is canceled. Returns I/O status if operation completed.
+ *
+ *      This routine does not block.
+ */
+int 
+aio_error(const struct aiocb *ap)
+{
+       return (ap->_aio_err);
+}
+
+/*
+ * aio_return()
+ *
+ *     Finish up I/O, releasing I/O resources and returns the value
+ *     that would have been associated with a synchronous request.
+ */
+ssize_t
+aio_return(struct aiocb *ap)
+{
+       return (ap->_aio_val);
+}
+
+int
+aio_cancel(int fildes, struct aiocb *aiocbp)
+{
+       return (AIO_ALLDONE);
+}
+
+int
+aio_suspend(const struct aiocb *const list[], int nent, const struct timespec *timo)
+{
+       return (0);
+}
+
index 50ee398..6b5816f 100644 (file)
@@ -52,7 +52,6 @@
 #include <sys/sysctl.h>
 #include <sys/vnode.h>
 #include <sys/vmmeter.h>
-#include <sys/aio.h>
 #include <sys/libkern.h>
 
 #include <cpu/lwbuf.h>
index 2de4674..1e5a110 100644 (file)
@@ -62,7 +62,6 @@
 #include <sys/filedesc.h>
 #include <sys/shm.h>
 #include <sys/sem.h>
-#include <sys/aio.h>
 #include <sys/jail.h>
 #include <sys/kern_syscall.h>
 #include <sys/upcall.h>
index 2bb6988..f63902e 100644 (file)
  */
 #define        AIO_LISTIO_MAX          16
 
-/*
- * Private members for aiocb -- don't access
- * directly.
- */
-struct __aiocb_private {
-       int     status;
-       int     error;
-       void    *kernelinfo;
-};
-
 /*
  * I/O control block
  */
@@ -85,7 +75,9 @@ typedef struct aiocb {
        struct  sigevent aio_sigevent;  /* Signal to deliver */
        int     aio_lio_opcode;         /* LIO opcode */
        int     aio_reqprio;            /* Request priority -- ignored */
-       struct  __aiocb_private _aiocb_private;
+
+       int     _aio_val;
+       int     _aio_err;
 } aiocb_t;
 
 #ifndef _KERNEL
@@ -138,34 +130,6 @@ int        aio_waitcomplete(struct aiocb **, struct timespec *);
 
 __END_DECLS
 
-#else
-/*
- * Job queue item
- */
-
-#define AIOCBLIST_RUNDOWN       0x4
-#define AIOCBLIST_DONE          0x10
-
-struct aiocblist {
-        TAILQ_ENTRY    (aiocblist) list;       /* List of jobs */
-        TAILQ_ENTRY    (aiocblist) plist;      /* List of jobs for proc */
-        int    jobflags;
-        int    jobstate;
-        int    inputcharge, outputcharge;
-       struct  callout timeout;
-        struct buf *bp;                /* Buffer pointer */
-        struct proc *userproc;         /* User process */
-        struct file *fd_file;          /* Pointer to file structure */ 
-        struct aio_liojob *lio;        /* Optional lio job */
-        struct aiocb *uuaiocb;         /* Pointer in userspace of aiocb */
-       struct  klist klist;            /* list of knotes */
-        struct aiocb uaiocb;           /* Kernel I/O control block */
-};
-
-/* Forward declarations for prototypes below. */
-struct socket;
-struct signalsockbuf;
-
 #endif
 
 #endif