Port: use ghashtable in mman compat
[babeltrace.git] / compat / compat_mman.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
This page took 0.030519 seconds and 4 git commands to generate.