summaryrefslogtreecommitdiff
path: root/eio.c
diff options
context:
space:
mode:
authorroot <root>2010-09-12 03:36:28 +0000
committerroot <root>2010-09-12 03:36:28 +0000
commit4a8a84bcfe982d119e9079d6e6cadce9d4ad93f8 (patch)
tree3e9d828c135bea75f2607b9fe6996617dbd23a91 /eio.c
parentaf54198660d122a386f9ad8a6e4a3bbffb6810e5 (diff)
*** empty log message ***
Diffstat (limited to 'eio.c')
-rw-r--r--eio.c110
1 files changed, 92 insertions, 18 deletions
diff --git a/eio.c b/eio.c
index 1c1806e..fc64b68 100644
--- a/eio.c
+++ b/eio.c
@@ -76,12 +76,15 @@
# 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 */
@@ -1394,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);
+
+ 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);
+ }
+
+ mlockall (flags);
+}
+#endif
+
#if !(_POSIX_MAPPED_FILES && _POSIX_SYNCHRONIZED_IO)
# define eio__msync(a,b,c) ((errno = ENOSYS), -1)
#else
@@ -1401,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)
@@ -1419,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;
}
@@ -1623,6 +1685,8 @@ 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;
@@ -1718,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;