Port: use ghashtable in mman compat
authorMichael Jeanson <mjeanson@efficios.com>
Fri, 2 Jun 2017 20:38:05 +0000 (16:38 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Wed, 5 Jul 2017 19:46:16 +0000 (15:46 -0400)
Signed-off-by: Michael Jeanson <mjeanson@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
compat/compat_mman.c
include/babeltrace/compat/mman-internal.h
include/babeltrace/mmap-align-internal.h
plugins/ctf/fs-src/data-stream-file.c

index 58be70ae304a0332f5d11b889e3bf48ff5c857f4..1c95d8eff66d59d1a2f3b6758e8f4c0994bcdbf5 100644 (file)
@@ -31,7 +31,6 @@
 
 #ifdef __MINGW32__
 
-#include <assert.h>
 #include <errno.h>
 #include <io.h>
 #include <pthread.h>
 #include <windows.h>
 #include <babeltrace/compat/mman-internal.h>
 
-struct mmap_info {
-       HANDLE file_handle; /* the duplicated handle */
-       HANDLE map_handle;  /* handle returned by CreateFileMapping */
-       void *start;        /* ptr returned by MapViewOfFile */
+struct mmap_mapping {
+       /* The duplicated handle. */
+       HANDLE file_handle;
+       /* Handle returned by CreateFileMapping. */
+       HANDLE map_handle;
 };
 
+static
+GHashTable *mmap_mappings = NULL;
+
 /*
- * This mutex protects the array of memory mappings and its associated
- * counters. (mmap_infos, mmap_infos_cur mmap_infos_max)
+ * This mutex protects the hashtable of memory mappings.
  */
 static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
 
-static int mmap_infos_cur = 0;
-static int mmap_infos_max = 0;
-static struct mmap_info *mmap_infos = NULL;
+static
+struct mmap_mapping *mapping_create(void)
+{
+       struct mmap_mapping *mapping;
+
+       mapping = malloc(sizeof(struct mmap_mapping));
+       if (mapping != NULL) {
+               mapping->file_handle = NULL;
+               mapping->map_handle = NULL;
+       }
 
-#define NEW_MMAP_STRUCT_CNT 10
+       return mapping;
+}
+
+static
+void mapping_clean(struct mmap_mapping *mapping)
+{
+       if (mapping) {
+               if (!CloseHandle(mapping->map_handle)) {
+                       BT_LOGF_STR("Failed to close mmap map_handle.");
+                       abort();
+               }
+               if (!CloseHandle(mapping->file_handle)) {
+                       BT_LOGF_STR("Failed to close mmap file_handle.");
+                       abort();
+               }
+               free(mapping);
+               mapping = NULL;
+       }
+}
+
+static
+void addr_clean(void *addr)
+{
+       /* Cleanup of handles should never fail. */
+       if (!UnmapViewOfFile(addr)) {
+               BT_LOGF_STR("Failed to unmap mmap mapping.");
+               abort();
+       }
+}
 
 static
 void mmap_lock(void)
 {
        if (pthread_mutex_lock(&mmap_mutex)) {
+               BT_LOGF_STR("Failed to acquire mmap_mutex.");
                abort();
        }
 }
@@ -69,6 +107,7 @@ static
 void mmap_unlock(void)
 {
        if (pthread_mutex_unlock(&mmap_mutex)) {
+               BT_LOGF_STR("Failed to release mmap_mutex.");
                abort();
        }
 }
@@ -104,179 +143,137 @@ DWORD map_prot_flags(int prot, DWORD *dwDesiredAccess)
                return PAGE_EXECUTE_READ;
        }
 
-       /* Mapping failed */
+       /* Mapping failed. */
        *dwDesiredAccess = 0;
        return 0;
 }
 
-void *mmap(void *start, size_t length, int prot, int flags, int fd,
+BT_HIDDEN
+void *bt_mmap(void *addr, size_t length, int prot, int flags, int fd,
                off_t offset)
 {
-       struct mmap_info mapping;
+       struct mmap_mapping *mapping = NULL;
+       void *mapping_addr;
        DWORD dwDesiredAccess;
        DWORD flProtect;
        HANDLE handle;
 
-       /* Check for a valid fd */
+       /* Check for a valid fd. */
        if (fd == -1) {
                _set_errno(EBADF);
-               return MAP_FAILED;
+               goto error;
        }
 
-       /* we don't support this atm */
+       /* We don't support this at the moment. */
        if (flags == MAP_FIXED) {
                _set_errno(ENOTSUP);
-               return MAP_FAILED;
+               goto error;
        }
 
-       /* Map mmap flags to windows API */
+       /* Map mmap flags to those of the Windows API. */
        flProtect = map_prot_flags(prot, &dwDesiredAccess);
        if (flProtect == 0) {
                _set_errno(EINVAL);
-               return MAP_FAILED;
+               goto error;
        }
 
-       /* Get a handle from the fd */
+       /* Allocate the mapping struct. */
+       mapping = mapping_create();
+       if (!mapping) {
+               BT_LOGE_STR("Failed to allocate mmap mapping.");
+               _set_errno(ENOMEM);
+               goto error;
+       }
+
+       /* Get a handle from the fd. */
        handle = (HANDLE) _get_osfhandle(fd);
 
-       /* Duplicate the handle and store it in 'mapping.file_handle' */
+       /* Duplicate the handle and store it in 'mapping.file_handle'. */
        if (!DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
-                       &mapping.file_handle, 0, FALSE,
+                       &mapping->file_handle, 0, FALSE,
                        DUPLICATE_SAME_ACCESS)) {
-               return MAP_FAILED;
+               _set_errno(ENOMEM);
+               goto error;
        }
 
        /*
         * Create a file mapping object with a maximum size
-        * of 'offset' + 'length'
+        * of 'offset' + 'length'.
         */
-       mapping.map_handle = CreateFileMapping(mapping.file_handle, NULL,
+       mapping->map_handle = CreateFileMapping(mapping->file_handle, NULL,
                        flProtect, 0, offset + length, NULL);
-       if (mapping.map_handle == 0) {
-               if (!CloseHandle(mapping.file_handle)) {
-                       abort();
-               }
+       if (mapping->map_handle == 0) {
                _set_errno(EACCES);
-               return MAP_FAILED;
+               goto error;
        }
 
-       /* Map the requested block starting at 'offset' for 'length' bytes */
-       mapping.start = MapViewOfFile(mapping.map_handle, dwDesiredAccess, 0,
+       /* Map the requested block starting at 'offset' for 'length' bytes. */
+       mapping_addr = MapViewOfFile(mapping->map_handle, dwDesiredAccess, 0,
                        offset, length);
-       if (mapping.start == 0) {
+       if (mapping_addr == 0) {
                DWORD dwLastErr = GetLastError();
-               if (!CloseHandle(mapping.map_handle)) {
-                       abort();
-               }
-               if (!CloseHandle(mapping.file_handle)) {
-                       abort();
-               }
-
                if (dwLastErr == ERROR_MAPPED_ALIGNMENT) {
                        _set_errno(EINVAL);
                } else {
                        _set_errno(EACCES);
                }
-
-               return MAP_FAILED;
+               goto error;
        }
 
        mmap_lock();
 
-       /* If we have never done any mappings, allocate the array */
-       if (mmap_infos == NULL) {
-               mmap_infos_max = NEW_MMAP_STRUCT_CNT;
-               mmap_infos = (struct mmap_info *) calloc(mmap_infos_max,
-                               sizeof(struct mmap_info));
-               if (mmap_infos == NULL) {
-                       mmap_infos_max = 0;
+       /* If we have never done any mappings, allocate the hashtable. */
+       if (!mmap_mappings) {
+               mmap_mappings = g_hash_table_new_full(g_direct_hash,
+                       g_direct_equal, (GDestroyNotify) addr_clean,
+                       (GDestroyNotify) mapping_clean);
+               if (!mmap_mappings) {
+                       BT_LOGE_STR("Failed to allocate mmap hashtable.");
+                       _set_errno(ENOMEM);
                        goto error_mutex_unlock;
                }
        }
 
-       /* if we have reached our current mapping limit, expand it */
-       if (mmap_infos_cur == mmap_infos_max) {
-               struct mmap_info *realloc_mmap_infos = NULL;
-
-               mmap_infos_max += NEW_MMAP_STRUCT_CNT;
-               realloc_mmap_infos = (struct mmap_info *) realloc(mmap_infos,
-                               mmap_infos_max * sizeof(struct mmap_info));
-               if (realloc_mmap_infos == NULL) {
-                       mmap_infos_max -= NEW_MMAP_STRUCT_CNT;
-                       goto error_mutex_unlock;
-               }
-               mmap_infos = realloc_mmap_infos;
+       /* Add the new mapping to the hashtable. */
+       if (!g_hash_table_insert(mmap_mappings, mapping_addr, mapping)) {
+               BT_LOGF_STR("Failed to insert mapping in the hashtable.");
+               abort();
        }
 
-       /* Add the new mapping to the array */
-       memcpy(&mmap_infos[mmap_infos_cur], &mapping,
-                       sizeof(struct mmap_info));
-       mmap_infos_cur++;
-
        mmap_unlock();
 
-       return mapping.start;
+       return mapping_addr;
 
 error_mutex_unlock:
        mmap_unlock();
-
-       if (!CloseHandle(mapping.map_handle)) {
-               abort();
-       }
-       if (!CloseHandle(mapping.file_handle)) {
-               abort();
-       }
-
-       _set_errno(ENOMEM);
+error:
+       mapping_clean(mapping);
        return MAP_FAILED;
 }
 
-int munmap(void *start, size_t length)
+BT_HIDDEN
+int bt_munmap(void *addr, size_t length)
 {
-       int i, j;
+       int ret = 0;
 
-       /* Find the mapping to unmap */
-       for (i = 0; i < mmap_infos_cur; i++) {
-               if (mmap_infos[i].start == start)
-                       break;
-       }
+       mmap_lock();
 
-       /* Mapping was not found */
-       if (i == mmap_infos_cur) {
+       /* Check if the mapping exists in the hashtable. */
+       if (g_hash_table_lookup(mmap_mappings, addr) == NULL) {
                _set_errno(EINVAL);
-               return -1;
+               ret = -1;
+               goto end;
        }
 
-       /* Cleanup of handles should never fail */
-       if (!UnmapViewOfFile(mmap_infos[i].start)) {
-               abort();
-       }
-       if (!CloseHandle(mmap_infos[i].map_handle)) {
+       /* Remove it. */
+       if (!g_hash_table_remove(mmap_mappings, addr)) {
+               BT_LOGF_STR("Failed to remove mapping from hashtable.");
                abort();
        }
-       if (!CloseHandle(mmap_infos[i].file_handle)) {
-               abort();
-       }
-
-       mmap_lock();
-
-       /* Clean the mapping list */
-       for (j = i + 1; j < mmap_infos_cur; j++) {
-               memcpy(&mmap_infos[j - 1], &mmap_infos[j],
-                               sizeof(struct mmap_info));
-       }
-       mmap_infos_cur--;
-
-       /* If the mapping list is now empty, free it */
-       if (mmap_infos_cur == 0) {
-               free(mmap_infos);
-               mmap_infos = NULL;
-               mmap_infos_max = 0;
-       }
 
+end:
        mmap_unlock();
-
-       return 0;
+       return ret;
 }
 
 #endif
index 6d9fa9260f3ada1bdf0bd33fb3c75bb3e0e40946..5e4ac9231cb7f5ae7c7e5adbfa55edc6bcd7f6ab 100644 (file)
  * SOFTWARE.
  */
 
-#ifndef __MINGW32__
-
-#include <sys/mman.h>
-
-#else /* __MINGW32__ */
+#ifdef __MINGW32__
 
 #include <sys/types.h>
 
 #define MAP_ANON       MAP_ANONYMOUS
 #define MAP_FAILED     ((void *) -1)
 
-void *mmap(void *addr, size_t length, int prot, int flags, int fd,
+void *bt_mmap(void *addr, size_t length, int prot, int flags, int fd,
        off_t offset);
-int munmap(void *addr, size_t length);
 
+int bt_munmap(void *addr, size_t length);
+
+#else /* __MINGW32__ */
+
+#include <sys/mman.h>
+
+static inline
+void *bt_mmap(void *addr, size_t length, int prot, int flags, int fd,
+       off_t offset)
+{
+       return (void *) mmap(addr, length, prot, flags, fd, offset);
+}
+
+static inline
+int bt_munmap(void *addr, size_t length)
+{
+       return munmap(addr, length);
+}
 #endif /* __MINGW32__ */
 
 #ifndef MAP_ANONYMOUS
index e87f4a98efc297110700314914654aa3568d128f..0b64ab925f5e120f7d66653a2bfb767fcd885c40 100644 (file)
@@ -94,7 +94,7 @@ struct mmap_align *mmap_align(size_t length, int prot,
         * boundary.
         */
        mma->page_aligned_length = ALIGN(length + offset - page_aligned_offset, page_size);
-       mma->page_aligned_addr = mmap(NULL, mma->page_aligned_length,
+       mma->page_aligned_addr = bt_mmap(NULL, mma->page_aligned_length,
                prot, flags, fd, page_aligned_offset);
        if (mma->page_aligned_addr == MAP_FAILED) {
                free(mma);
@@ -113,7 +113,7 @@ int munmap_align(struct mmap_align *mma)
        page_aligned_addr = mma->page_aligned_addr;
        page_aligned_length = mma->page_aligned_length;
        free(mma);
-       return munmap(page_aligned_addr, page_aligned_length);
+       return bt_munmap(page_aligned_addr, page_aligned_length);
 }
 
 static inline
index 0fb3a6bd1ce54a4306daa10159d5d2b0ab948865..5d255ab78441ecf08bc882fc9ac4dbb3547c3672 100644 (file)
@@ -62,7 +62,7 @@ int ds_file_munmap(struct ctf_fs_ds_file *ds_file)
                goto end;
        }
 
-       if (munmap(ds_file->mmap_addr, ds_file->mmap_len)) {
+       if (bt_munmap(ds_file->mmap_addr, ds_file->mmap_len)) {
                BT_LOGE("Cannot memory-unmap address %p (size %zu) of file \"%s\" (%p): %s",
                        ds_file->mmap_addr, ds_file->mmap_len,
                        ds_file->file->path->str, ds_file->file->fp,
@@ -106,7 +106,7 @@ enum bt_ctf_notif_iter_medium_status ds_file_mmap_next(
                        & ~(page_size - 1);
        /* Map new region */
        assert(ds_file->mmap_len);
-       ds_file->mmap_addr = mmap((void *) 0, ds_file->mmap_len,
+       ds_file->mmap_addr = bt_mmap((void *) 0, ds_file->mmap_len,
                        PROT_READ, MAP_PRIVATE, fileno(ds_file->file->fp),
                        ds_file->mmap_offset);
        if (ds_file->mmap_addr == MAP_FAILED) {
This page took 0.029914 seconds and 4 git commands to generate.