X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=compat%2Fcompat_mman.c;h=bef80d481ecb952ca794b991e1f15669588bf215;hb=68b66a256a54d32992dfefeaad11eea88b7df234;hp=58be70ae304a0332f5d11b889e3bf48ff5c857f4;hpb=1f0f70c02e4026c8a81649c5e0702644b34c1556;p=babeltrace.git diff --git a/compat/compat_mman.c b/compat/compat_mman.c index 58be70ae..bef80d48 100644 --- a/compat/compat_mman.c +++ b/compat/compat_mman.c @@ -29,38 +29,85 @@ #define BT_LOG_TAG "COMPAT-MMAN" #include "logging.h" +#ifdef __APPLE__ +/* + * On macOS, we need a dummy symbol so that the linker won't + * complain of an empty table of contents. + */ +BT_HIDDEN +int bt_mman_dummy_symbol; +#endif /* __APPLE__ */ + #ifdef __MINGW32__ -#include #include #include #include #include #include -#include +#include -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; + } + + 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; + } +} -#define NEW_MMAP_STRUCT_CNT 10 +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 +116,7 @@ static void mmap_unlock(void) { if (pthread_mutex_unlock(&mmap_mutex)) { + BT_LOGF_STR("Failed to release mmap_mutex."); abort(); } } @@ -104,179 +152,134 @@ 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; + } + + /* 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 */ + /* 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 array */ - memcpy(&mmap_infos[mmap_infos_cur], &mapping, - sizeof(struct mmap_info)); - mmap_infos_cur++; + /* Add the new mapping to the hashtable. */ + g_hash_table_insert(mmap_mappings, mapping_addr, mapping); 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)) { - abort(); - } - if (!CloseHandle(mmap_infos[i].file_handle)) { + /* Remove it. */ + if (!g_hash_table_remove(mmap_mappings, addr)) { + BT_LOGF_STR("Failed to remove mapping from hashtable."); 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