Upgrade libeio
authorRyan Dahl <ry@tinyclouds.org>
Mon, 13 Sep 2010 22:40:20 +0000 (15:40 -0700)
committerRyan Dahl <ry@tinyclouds.org>
Mon, 13 Sep 2010 22:40:20 +0000 (15:40 -0700)
deps/libeio/Changes
deps/libeio/eio.c
deps/libeio/eio.h

index 7cba947..656f945 100644 (file)
@@ -1,6 +1,7 @@
 Revision history for libeio
 
 TODO: maybe add mincore support? available on at least darwin, solaris, linux, freebsd
+TODO: openbsd requites stdint.h for intptr_t - why posix?
 
 1.0
         - readdir: correctly handle malloc failures.
@@ -23,4 +24,5 @@ TODO: maybe add mincore support? available on at least darwin, solaris, linux, f
           error codes.
         - add OS-independent EIO_MT_* and EIO_MS_* flag enums.
         - add eio_statvfs/eio_fstatvfs.
+        - add eio_mlock/eio_mlockall and OS-independent MCL_* flag enums.
 
index 6f61f5d..0d30ce7 100644 (file)
@@ -55,7 +55,6 @@
 #include <limits.h>
 #include <fcntl.h>
 #include <assert.h>
-#include <stdint.h>
 
 #ifndef EIO_FINISH
 # define EIO_FINISH(req)  ((req)->finish) && !EIO_CANCELLED (req) ? (req)->finish (req) : 0
 # include "config.h"
 # include <sys/time.h>
 # include <sys/select.h>
-# include <sys/mman.h>
 # include <unistd.h>
 # include <utime.h>
 # include <signal.h>
 # include <dirent.h>
 
+#if _POSIX_MEMLOCK || _POSIX_MAPPED_FILES
+# include <sys/mman.h>
+#endif
+
 /* POSIX_SOURCE is useless on bsd's, and XOPEN_SOURCE is unreliable there, too */
 # if __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__
 #  define _DIRENT_HAVE_D_TYPE /* sigh */
@@ -1395,6 +1397,69 @@ eio__scandir (eio_req *req, etp_worker *self)
       }
 }
 
+#ifdef PAGESIZE
+# define eio_pagesize() PAGESIZE
+#else
+static intptr_t
+eio_pagesize (void)
+{
+  static intptr_t page;
+
+  if (!page)
+    page = sysconf (_SC_PAGESIZE);
+
+  return page;
+}
+#endif
+
+static void
+eio_page_align (void **addr, size_t *length)
+{
+  intptr_t mask = eio_pagesize () - 1;
+
+  /* round down addr */
+  intptr_t adj = mask & (intptr_t)*addr;
+
+  *addr   = (void *)((intptr_t)*addr - adj);
+  *length += adj;
+
+  /* round up length */
+  *length = (*length + mask) & ~mask;
+}
+
+#if !_POSIX_MEMLOCK
+# define eio__mlock(a,b) ((errno = ENOSYS), -1)
+# define eio__mlockall(a) ((errno = ENOSYS), -1)
+#else
+
+static int
+eio__mlock (void *addr, size_t length)
+{
+  eio_page_align (&addr, &length);
+
+  return mlock (addr, length);
+}
+
+static int
+eio__mlockall (int flags)
+{
+  #if __GLIBC__ == 2 && __GLIBC_MINOR__ <= 7
+    extern int mallopt (int, int);
+    mallopt (-6, 238); /* http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=473812 */
+  #endif
+
+  if (EIO_MCL_CURRENT   != MCL_CURRENT
+      || EIO_MCL_FUTURE != MCL_FUTURE)
+    {
+      flags = 0
+         | (flags & EIO_MCL_CURRENT ? MCL_CURRENT : 0)
+         | (flags & EIO_MCL_FUTURE  ? MCL_FUTURE : 0);
+    }
+
+  return mlockall (flags);
+}
+#endif
+
 #if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO)
 # define eio__msync(a,b,c) ((errno = ENOSYS), -1)
 #else
@@ -1402,6 +1467,8 @@ eio__scandir (eio_req *req, etp_worker *self)
 int
 eio__msync (void *mem, size_t len, int flags)
 {
+  eio_page_align (&mem, &len);
+
   if (EIO_MS_ASYNC         != MS_SYNC
       || EIO_MS_INVALIDATE != MS_INVALIDATE
       || EIO_MS_SYNC       != MS_SYNC)
@@ -1420,25 +1487,19 @@ eio__msync (void *mem, size_t len, int flags)
 int
 eio__mtouch (void *mem, size_t len, int flags)
 {
-  intptr_t addr = (intptr_t)mem;
-  intptr_t end = addr + len;
-#ifdef PAGESIZE
-  const intptr_t page = PAGESIZE;
-#else
-  static intptr_t page;
+  eio_page_align (&mem, &len);
 
-  if (!page)
-    page = sysconf (_SC_PAGESIZE);
-#endif
-
-  /* round down to start of page, although this is probably useless */
-  addr &= ~(page - 1); /* assume page size is always a power of two */
+  {
+    intptr_t addr = (intptr_t)mem;
+    intptr_t end = addr + len;
+    intptr_t page = eio_pagesize ();
 
-  if (addr < end)
-    if (flags & EIO_MT_MODIFY) /* modify */
-      do { *((volatile sig_atomic_t *)addr) |= 0; } while ((addr += page) < len);
-    else
-      do { *((volatile sig_atomic_t *)addr)     ; } while ((addr += page) < len);
+    if (addr < end)
+      if (flags & EIO_MT_MODIFY) /* modify */
+        do { *((volatile sig_atomic_t *)addr) |= 0; } while ((addr += page) < len);
+      else
+        do { *((volatile sig_atomic_t *)addr)     ; } while ((addr += page) < len);
+  }
 
   return 0;
 }
@@ -1624,19 +1685,21 @@ static void eio_execute (etp_worker *self, eio_req *req)
       case EIO_FDATASYNC: req->result = fdatasync (req->int1); break;
       case EIO_MSYNC:     req->result = eio__msync (req->ptr2, req->size, req->int1); break;
       case EIO_MTOUCH:    req->result = eio__mtouch (req->ptr2, req->size, req->int1); break;
+      case EIO_MLOCK:     req->result = eio__mlock (req->ptr2, req->size); break;
+      case EIO_MLOCKALL:  req->result = eio__mlockall (req->int1); break;
       case EIO_SYNC_FILE_RANGE: req->result = eio__sync_file_range (req->int1, req->offs, req->size, req->int2); break;
 
       case EIO_READDIR:   eio__scandir (req, self); break;
 
       case EIO_BUSY:
 #ifdef _WIN32
-       Sleep (req->nv1 * 1000.);
+       Sleep (req->nv1 * 1e3);
 #else
         {
           struct timeval tv;
 
           tv.tv_sec  = req->nv1;
-          tv.tv_usec = (req->nv1 - tv.tv_sec) * 1000000.;
+          tv.tv_usec = (req->nv1 - tv.tv_sec) * 1e6;
 
           req->result = select (0, 0, 0, 0, &tv);
         }
@@ -1719,6 +1782,16 @@ eio_req *eio_mtouch (void *addr, size_t length, int flags, int pri, eio_cb cb, v
   REQ (EIO_MTOUCH); req->ptr2 = addr; req->size = length; req->int1 = flags; SEND;
 }
 
+eio_req *eio_mlock (void *addr, size_t length, int pri, eio_cb cb, void *data)
+{
+  REQ (EIO_MLOCK); req->ptr2 = addr; req->size = length; SEND;
+}
+
+eio_req *eio_mlockall (int flags, int pri, eio_cb cb, void *data)
+{
+  REQ (EIO_MLOCKALL); req->int1 = flags; SEND;
+}
+
 eio_req *eio_sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags, int pri, eio_cb cb, void *data)
 {
   REQ (EIO_SYNC_FILE_RANGE); req->int1 = fd; req->offs = offset; req->size = nbytes; req->int2 = flags; SEND;
index 1a5dc3d..ad253a6 100644 (file)
@@ -67,7 +67,8 @@ typedef int (*eio_cb)(eio_req *req);
 /* for readdir */
 
 /* eio_readdir flags */
-enum {
+enum
+{
   EIO_READDIR_DENTS         = 0x01, /* ptr2 contains eio_dirents, not just the (unsorted) names */
   EIO_READDIR_DIRS_FIRST    = 0x02, /* dirents gets sorted into a good stat() ing order to find directories first */
   EIO_READDIR_STAT_ORDER    = 0x04, /* dirents gets sorted into a good stat() ing order to quickly stat all files */
@@ -78,7 +79,8 @@ enum {
 };
 
 /* using "typical" values in the hope that the compiler will do something sensible */
-enum eio_dtype {
+enum eio_dtype
+{
   EIO_DT_UNKNOWN =  0,
   EIO_DT_FIFO    =  1,
   EIO_DT_CHR     =  2,
@@ -98,7 +100,8 @@ enum eio_dtype {
   EIO_DT_MAX     = 15  /* highest DT_VALUE ever, hopefully */
 };
 
-struct eio_dirent {
+struct eio_dirent
+{
   int nameofs; /* offset of null-terminated name string in (char *)req->ptr2 */
   unsigned short namelen; /* size of filename without trailing 0 */
   unsigned char type; /* one of EIO_DT_* */
@@ -107,7 +110,8 @@ struct eio_dirent {
 };
 
 /* eio_msync flags */
-enum {
+enum
+{
   EIO_MS_ASYNC      = 1,
   EIO_MS_INVALIDATE = 2,
   EIO_MS_SYNC       = 4
@@ -115,13 +119,15 @@ enum {
 
 /* eio_mtouch flags */
 
-enum {
+enum
+{
   EIO_MT_MODIFY     = 1
 };
 
 /* eio_sync_file_range flags */
 
-enum {
+enum
+{
   EIO_SYNC_FILE_RANGE_WAIT_BEFORE = 1,
   EIO_SYNC_FILE_RANGE_WRITE       = 2,
   EIO_SYNC_FILE_RANGE_WAIT_AFTER  = 4
@@ -131,7 +137,8 @@ typedef double eio_tstamp; /* feel free to use double in your code directly */
 
 /* the eio request structure */
 
-enum {
+enum
+{
   EIO_CUSTOM,
   EIO_OPEN, EIO_CLOSE, EIO_DUP2,
   EIO_READ, EIO_WRITE,
@@ -144,6 +151,7 @@ enum {
   EIO_CHOWN, EIO_FCHOWN,
   EIO_SYNC, EIO_FSYNC, EIO_FDATASYNC,
   EIO_MSYNC, EIO_MTOUCH, EIO_SYNC_FILE_RANGE,
+  EIO_MLOCK, EIO_MLOCKALL,
   EIO_UNLINK, EIO_RMDIR, EIO_MKDIR, EIO_RENAME,
   EIO_MKNOD, EIO_READDIR,
   EIO_LINK, EIO_SYMLINK, EIO_READLINK,
@@ -151,6 +159,21 @@ enum {
   EIO_BUSY
 };
 
+/* mlockall constants */
+enum
+{
+  EIO_MCL_CURRENT = 1,
+  EIO_MCL_FUTURE  = 2,
+};
+
+/* request priorities */
+
+enum {
+  EIO_PRI_MIN     = -4,
+  EIO_PRI_MAX     =  4,
+  EIO_PRI_DEFAULT =  0
+};
+
 /* eio request structure */
 /* this structure is mostly read-only */
 /* when initialising it, all members must be zero-initialised */
@@ -160,14 +183,14 @@ struct eio_req
 
   ssize_t result;  /* result of syscall, e.g. result = read (... */
   off_t offs;      /* read, write, truncate, readahead, sync_file_range: file offset */
-  size_t size;     /* read, write, readahead, sendfile, msync, sync_file_range: length */
+  size_t size;     /* read, write, readahead, sendfile, msync, mlock, sync_file_range: length */
   void *ptr1;      /* all applicable requests: pathname, old name; readdir: optional eio_dirents */
   void *ptr2;      /* all applicable requests: new name or memory buffer; readdir: name strings */
   eio_tstamp nv1;  /* utime, futime: atime; busy: sleep time */
   eio_tstamp nv2;  /* utime, futime: mtime */
 
   int type;        /* EIO_xxx constant ETP */
-  int int1;        /* all applicable requests: file descriptor; sendfile: output fd; open, msync, readdir: flags */
+  int int1;        /* all applicable requests: file descriptor; sendfile: output fd; open, msync, mlockall, readdir: flags */
   long int2;       /* chown, fchown: uid; sendfile: input fd; open, chmod, mkdir, mknod: file mode, sync_file_range: flags */
   long int3;       /* chown, fchown: gid; mknod: dev_t */
   int errorno;     /* errno value on syscall return */
@@ -185,7 +208,7 @@ struct eio_req
   eio_req *grp, *grp_prev, *grp_next, *grp_first; /* private */
 };
 
-/* _private_ flags */
+/* _private_ request flags */
 enum {
   EIO_FLAG_CANCELLED = 0x01, /* request was cancelled */
   EIO_FLAG_PTR1_FREE = 0x02, /* need to free(ptr1) */
@@ -193,11 +216,8 @@ enum {
   EIO_FLAG_GROUPADD  = 0x08  /* some request was added to the group */
 };
 
-enum {
-  EIO_PRI_MIN     = -4,
-  EIO_PRI_MAX     =  4,
-  EIO_PRI_DEFAULT =  0,
-};
+/* undocumented/unsupported/private helper */
+/*void eio_page_align (void **addr, size_t *length);*/
 
 /* returns < 0 on error, errno set
  * need_poll, if non-zero, will be called when results are available
@@ -238,6 +258,8 @@ eio_req *eio_fsync     (int fd, int pri, eio_cb cb, void *data);
 eio_req *eio_fdatasync (int fd, int pri, eio_cb cb, void *data);
 eio_req *eio_msync     (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data);
 eio_req *eio_mtouch    (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data);
+eio_req *eio_mlock     (void *addr, size_t length, int pri, eio_cb cb, void *data);
+eio_req *eio_mlockall  (int flags, int pri, eio_cb cb, void *data);
 eio_req *eio_sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags, int pri, eio_cb cb, void *data);
 eio_req *eio_close     (int fd, int pri, eio_cb cb, void *data);
 eio_req *eio_readahead (int fd, off_t offset, size_t length, int pri, eio_cb cb, void *data);