From 04394229f0daeeb36a09ea64f3208fe051fd9ca0 Mon Sep 17 00:00:00 2001 From: Michael Jeanson Date: Fri, 2 Jun 2017 16:38:05 -0400 Subject: [PATCH] Port: use ghashtable in mman compat MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Michael Jeanson Signed-off-by: Jérémie Galarneau --- compat/compat_mman.c | 223 +++++++++++----------- include/babeltrace/compat/mman-internal.h | 27 ++- include/babeltrace/mmap-align-internal.h | 4 +- plugins/ctf/fs-src/data-stream-file.c | 4 +- 4 files changed, 134 insertions(+), 124 deletions(-) diff --git a/compat/compat_mman.c b/compat/compat_mman.c index 58be70ae..1c95d8ef 100644 --- a/compat/compat_mman.c +++ b/compat/compat_mman.c @@ -31,7 +31,6 @@ #ifdef __MINGW32__ -#include #include #include #include @@ -39,28 +38,67 @@ #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; + } -#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 diff --git a/include/babeltrace/compat/mman-internal.h b/include/babeltrace/compat/mman-internal.h index 6d9fa926..5e4ac923 100644 --- a/include/babeltrace/compat/mman-internal.h +++ b/include/babeltrace/compat/mman-internal.h @@ -25,11 +25,7 @@ * SOFTWARE. */ -#ifndef __MINGW32__ - -#include - -#else /* __MINGW32__ */ +#ifdef __MINGW32__ #include @@ -47,10 +43,27 @@ #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 + +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 diff --git a/include/babeltrace/mmap-align-internal.h b/include/babeltrace/mmap-align-internal.h index e87f4a98..0b64ab92 100644 --- a/include/babeltrace/mmap-align-internal.h +++ b/include/babeltrace/mmap-align-internal.h @@ -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 diff --git a/plugins/ctf/fs-src/data-stream-file.c b/plugins/ctf/fs-src/data-stream-file.c index 0fb3a6bd..5d255ab7 100644 --- a/plugins/ctf/fs-src/data-stream-file.c +++ b/plugins/ctf/fs-src/data-stream-file.c @@ -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) { -- 2.34.1