Changeset: 3b5247b0b3d8 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=3b5247b0b3d8
Modified Files:
NT/monetdb_config.h.in
configure.ag
gdk/gdk_heap.c
gdk/gdk_posix.c
gdk/gdk_private.h
Branch: default
Log Message:
Merge with Feb2013 branch.
diffs (truncated from 339 to 300 lines):
diff --git a/NT/monetdb_config.h.in b/NT/monetdb_config.h.in
--- a/NT/monetdb_config.h.in
+++ b/NT/monetdb_config.h.in
@@ -301,6 +301,9 @@
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
+/* Define to 1 if you have the `mremap' function. */
+/* #undef HAVE_MREMAP */
+
/* Define if you have the mseed library */
/* #undef HAVE_MSEED */
diff --git a/configure.ag b/configure.ag
--- a/configure.ag
+++ b/configure.ag
@@ -2564,6 +2564,7 @@ AC_CHECK_FUNCS([\
localtime_r \
lockf \
madvise \
+ mremap \
nl_langinfo \
_NSGetExecutablePath \
pipe \
diff --git a/gdk/gdk_heap.c b/gdk/gdk_heap.c
--- a/gdk/gdk_heap.c
+++ b/gdk/gdk_heap.c
@@ -368,16 +368,24 @@ HEAPextend(Heap *h, size_t size)
if (size <= h->size)
return 0;
- if (h->storage != STORE_MEM) {
- HEAPDEBUG fprintf(stderr, "#HEAPextend: extending %s mmapped
heap\n", h->storage == STORE_MMAP ? "shared" : "privately");
- /* memory mapped files extend: save and remap */
- if (HEAPsave_intern(h, nme, ext, ".tmp") < 0)
- return -1;
- HEAPfree(h);
- h->maxsize = h->size = size;
- if (HEAPload_intern(h, nme, ext, ".tmp", FALSE) >= 0) {
- return 0;
- }
+ if (h->storage != STORE_MEM) {
+ char *p;
+ long_str path;
+
+ HEAPDEBUG fprintf(stderr, "#HEAPextend: extending %s mmapped
heap (%s)\n", h->storage == STORE_MMAP ? "shared" : "privately", h->filename);
+ /* extend memory mapped file */
+ GDKfilepath(path, BATDIR, nme, ext);
+ size = (1 + ((size - 1) >> REMAP_PAGE_MAXBITS)) <<
REMAP_PAGE_MAXBITS;
+ p = MT_mremap(path,
+ h->storage == STORE_PRIV ?
+ MMAP_COPY | MMAP_READ | MMAP_WRITE :
+ MMAP_READ | MMAP_WRITE,
+ h->base, h->size, size);
+ if (p) {
+ h->maxsize = h->size = size;
+ h->base = p;
+ return 0;
+ }
} else {
/* extend a malloced heap, possibly switching over to
* file-mapped storage */
diff --git a/gdk/gdk_posix.c b/gdk/gdk_posix.c
--- a/gdk/gdk_posix.c
+++ b/gdk/gdk_posix.c
@@ -57,10 +57,6 @@ extern char *sbrk(int);
# include <sys/user.h>
#endif
-#if defined(DEBUG_ALLOC) && SIZEOF_VOID_P > 4
-#undef DEBUG_ALLOC
-#endif
-
#ifdef WIN32
int GDK_mem_pagebits = 16; /* on windows, the mmap addresses can be set by
the 64KB */
#else
@@ -70,6 +66,9 @@ int GDK_mem_pagebits = 14; /* on linux,
#ifndef MAP_NORESERVE
# define MAP_NORESERVE MAP_PRIVATE
#endif
+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
#define MMAP_ADVISE 7
#define MMAP_WRITABLE (MMAP_WRITE|MMAP_COPY)
@@ -390,11 +389,188 @@ MT_munmap(void *p, size_t len)
int ret = munmap(p, len);
#ifdef MMAP_DEBUG
- mnstr_printf(GDKstdout, "#munmap(" LLFMT "," LLFMT ",%d) = %d\n", (long
long) p, (long long) len, ret);
+ fprintf(stderr, "#munmap(" PTRFMT "," SZFMT ",%d) = %d\n", PTRFMTCAST
p, len, ret);
#endif
return ret;
}
+/* expand or shrink a memory map (ala realloc).
+ * the address returned may be different from the address going in.
+ * in case of failure, the old address is still mapped and NULL is returned.
+ */
+void *
+MT_mremap(const char *path, int mode, void *old_address, size_t old_size,
size_t new_size)
+{
+ void *p;
+ int fd = -1;
+ int flags = mode & MMAP_COPY ? MAP_PRIVATE : MAP_SHARED;
+ int prot = PROT_WRITE | PROT_READ;
+
+ /* doesn't make sense for us to extend read-only memory map */
+ assert(mode & MMAP_WRITABLE);
+
+ if (new_size < old_size) {
+ /* shrink */
+ munmap((char *) old_address + new_size, old_size - new_size);
+#ifdef MMAP_DEBUG
+ fprintf(stderr, "MT_mremap(%s,"PTRFMT","SZFMT","SZFMT") ->
shrinking\n", path?path:"NULL", PTRFMTCAST old_address, old_size, new_size);
+#endif
+ return old_address;
+ }
+ if (new_size == old_size) {
+ /* do nothing */
+#ifdef MMAP_DEBUG
+ fprintf(stderr, "MT_mremap(%s,"PTRFMT","SZFMT","SZFMT") ->
unchanged\n", path?path:"NULL", PTRFMTCAST old_address, old_size, new_size);
+#endif
+ return old_address;
+ }
+
+ if (!(mode & MMAP_COPY) && path != NULL) {
+ /* "normal" memory map */
+ struct stat stb;
+
+ if ((fd = open(path, O_RDWR)) < 0)
+ return NULL;
+ if (fstat(fd, &stb) < 0) {
+ /* shouldn't happen */
+ close(fd);
+ return NULL;
+ }
+ /* if necessary, extend the underlying file */
+ if (stb.st_size < (off_t) new_size &&
+ (lseek(fd, new_size - 1, SEEK_SET) < 0 ||
+ write(fd, "\0", 1) < 0)) {
+ close(fd);
+ return NULL;
+ }
+#ifdef HAVE_MREMAP
+ /* on Linux it's easy */
+ p = mremap(old_address, old_size, new_size, MREMAP_MAYMOVE);
+#else
+ /* try to map extension at end of current map */
+ p = mmap((char *) old_address + old_size, new_size - old_size,
+ prot, flags, fd, old_size);
+ /* if it failed, there is no point trying a full mmap:
+ * that too won't fit */
+ if (p != MAP_FAILED) {
+ if (p == (char *) old_address + old_size) {
+ /* we got the requested address, make
+ * sure we return the correct (old)
+ * address */
+ p = old_address;
+ } else {
+ /* we got some other address: discard
+ * it and make full mmap */
+ munmap(p, new_size - old_size);
+#ifdef NO_MMAP_ALIASING
+ msync(old_address, old_size, MS_SYNC);
+#endif
+ /* first create full mmap, then, if
+ * successful, remove old mmap */
+ p = mmap(NULL, new_size, prot, flags, fd, 0);
+ if (p != MAP_FAILED)
+ munmap(old_address, old_size);
+ }
+ }
+#endif /* HAVE_MREMAP */
+ close(fd);
+ } else {
+ /* "copy-on-write" or "anonymous" memory map */
+#ifdef MAP_ANONYMOUS
+ flags |= MAP_ANONYMOUS;
+#else
+ if ((fd = open("/dev/zero", O_RDWR)) < 0)
+ return NULL;
+#endif
+ /* try to map an anonymous area as extent to the
+ * current map */
+ p = mmap((char *) old_address + old_size, new_size - old_size,
+ prot, flags, fd, 0);
+ /* no point trying a full map if this didn't work:
+ * there isn't enough space */
+ if (p != MAP_FAILED) {
+ if (p == (char *) old_address + old_size) {
+ /* we got the requested address, make
+ * sure we return the correct (old)
+ * address */
+ p = old_address;
+ } else {
+ /* we got some other address: discard
+ * it and make full mmap */
+ munmap(p, new_size - old_size);
+#ifdef HAVE_MREMAP
+ /* first get an area large enough for
+ * new_size */
+ p = mmap(NULL, new_size, prot, flags, fd, 0);
+ if (p != MAP_FAILED) {
+ /* then overlay old mmap over new */
+ void *q;
+
+ q = mremap(old_address, old_size,
+ old_size,
+ MREMAP_FIXED |
MREMAP_MAYMOVE,
+ p);
+ assert(q == p || q == MAP_FAILED);
+ if (q == MAP_FAILED) {
+ /* we didn't expect this... */
+ munmap(p, new_size);
+ p = MAP_FAILED;
+ }
+ }
+#else
+ p = MAP_FAILED;
+ if (path == NULL ||
+ new_size <= GDK_mmap_minsize) {
+ /* size not too big yet or
+ * anonymous, try to make new
+ * anonymous mmap and copy
+ * data over */
+ p = mmap(NULL, new_size, prot, flags,
+ fd, 0);
+ if (p != MAP_FAILED) {
+ memcpy(p, old_address,
+ old_size);
+ munmap(old_address, old_size);
+ }
+ /* if it failed, try alternative */
+ }
+ if (p == MAP_FAILED && path != NULL) {
+ /* write data to disk, then
+ * mmap it to new address */
+ if (fd >= 0)
+ close(fd);
+ p = malloc(strlen(path) + 5);
+ strcat(strcpy(p, path), ".tmp");
+ fd = open(p, O_RDWR | O_CREAT,
+ MONETDB_MODE);
+ free(p);
+ if (fd < 0)
+ return NULL;
+ if (write(fd, old_address,
+ old_size) < 0 ||
+ lseek(fd, new_size - 1,
+ SEEK_SET) < 0 ||
+ write(fd, "\0", 1) < 0) {
+ close(fd);
+ return NULL;
+ }
+ p = mmap(NULL, new_size, prot, flags,
+ fd, 0);
+ if (p != MAP_FAILED)
+ munmap(old_address, old_size);
+ }
+#endif /* HAVE_MREMAP */
+ }
+ }
+ if (fd >= 0)
+ close(fd);
+ }
+#ifdef MMAP_DEBUG
+ fprintf(stderr, "MT_mremap(%s,"PTRFMT","SZFMT","SZFMT") ->
"PTRFMT"%s\n", path?path:"NULL", PTRFMTCAST old_address, old_size, new_size,
PTRFMTCAST p, path && mode & MMAP_COPY ? " private" : "");
+#endif
+ return p == MAP_FAILED ? NULL : p;
+}
+
int
MT_msync(void *p, size_t off, size_t len, int mode)
{
@@ -403,9 +579,9 @@ MT_msync(void *p, size_t off, size_t len
((mode & MMAP_ASYNC) ? MS_ASYNC : MS_INVALIDATE));
#ifdef MMAP_DEBUG
- mnstr_printf(GDKstdout,
- "#msync(" LLFMT "," LLFMT ",%s) = %d\n",
- (long long) p, (long long) len,
+ fprintf(stderr,
+ "#msync(" PTRFMT "," SZFMT ",%s) = %d\n",
+ PTRFMTCAST p, len,
(mode & MMAP_SYNC) ? "MS_SYNC" :
((mode & MMAP_ASYNC) ? "MS_ASYNC" : "MS_INVALIDATE"),
ret);
@@ -588,6 +764,29 @@ MT_munmap(void *p, size_t dummy)
return -(UnmapViewOfFile(p) == 0);
}
+void *
+MT_mremap(const char *path, int mode, void *old_address, size_t old_size,
size_t new_size)
+{
+ void *p;
+
+ /* doesn't make sense for us to extend read-only memory map */
+ assert(mode & MMAP_WRITABLE);
_______________________________________________
checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list