Example #1
0
File: install.c Project: LenaO/ucx
/* Called with lock held */
static ucs_status_t ucm_mmap_test(int events)
{
    static int installed_events = 0;
    ucm_event_handler_t handler;
    int out_events;
    void *p;

    if (ucs_test_all_flags(installed_events, events)) {
        /* All requested events are already installed */
        return UCS_OK;
    }

    /* Install a temporary event handler which will add the supported event
     * type to out_events bitmap.
     */
    handler.events   = events;
    handler.priority = -1;
    handler.cb       = ucm_mmap_event_test_callback;
    handler.arg      = &out_events;
    out_events       = 0;

    ucm_event_handler_add(&handler);

    if (events & (UCM_EVENT_MMAP|UCM_EVENT_MUNMAP|UCM_EVENT_MREMAP)) {
        p = mmap(NULL, 0, 0, 0, -1 ,0);
        p = mremap(p, 0, 0, 0);
        munmap(p, 0);
    }

    if (events & (UCM_EVENT_SHMAT|UCM_EVENT_SHMDT)) {
        p = shmat(0, NULL, 0);
        shmdt(p);
    }

    if (events & UCM_EVENT_SBRK) {
        (void)sbrk(0);
    }

    ucm_event_handler_remove(&handler);

    /* TODO check address / stop all threads */
    installed_events |= out_events;
    ucm_debug("mmap test: got 0x%x out of 0x%x, total: 0x%x", out_events, events,
              installed_events);

    /* Return success iff we caught all wanted events */
    if (!ucs_test_all_flags(out_events, events)) {
        return UCS_ERR_UNSUPPORTED;
    }

    return UCS_OK;
}
Example #2
0
/* Has to be called with install_mutex held */
static void ucm_malloc_test(int events)
{
    static const size_t small_alloc_count = 128;
    static const size_t small_alloc_size  = 4096;
    static const size_t large_alloc_size  = 4 * UCS_MBYTE;
    ucm_event_handler_t handler;
    void *p[small_alloc_count];
    int out_events;
    int i;

    ucm_debug("testing malloc...");

    /* Install a temporary event handler which will add the supported event
     * type to out_events bitmap.
     */
    handler.events   = events;
    handler.priority = -1;
    handler.cb       = ucm_mmap_event_test_callback;
    handler.arg      = &out_events;
    out_events       = 0;

    ucm_event_handler_add(&handler);

    /* Trigger both small and large allocations
     * TODO check address / stop all threads */
    for (i = 0; i < small_alloc_count; ++i) {
        p[i] = malloc(small_alloc_size);
    }
    for (i = 0; i < small_alloc_count; ++i) {
        free(p[i]);
    }
    p[0] = malloc(large_alloc_size);
    p[0] = realloc(p[0], large_alloc_size * 2);
    free(p[0]);

    if (ucm_malloc_hook_state.hook_called) {
        ucm_dlmalloc_trim(0);
    }

    ucm_event_handler_remove(&handler);

    ucm_malloc_hook_state.installed_events |= out_events;

    ucm_debug("malloc test: have 0x%x out of 0x%x, hooks were%s called",
              ucm_malloc_hook_state.installed_events, events,
              ucm_malloc_hook_state.hook_called ? "" : " not");
}
Example #3
0
ucs_status_t ucm_malloc_install(int events)
{
    ucs_status_t status;

    pthread_mutex_lock(&ucm_malloc_hook_state.install_mutex);

    events &= UCM_EVENT_MMAP | UCM_EVENT_MUNMAP | UCM_EVENT_MREMAP | UCM_EVENT_SBRK;

    if (ucs_malloc_is_ready(events)) {
        goto out_succ;
    }

    ucm_malloc_test(events);
    if (ucs_malloc_is_ready(events)) {
        goto out_succ;
    }

    if (!ucm_malloc_hook_state.hook_called) {
        /* Try to leak less memory from original malloc */
        malloc_trim(0);
    }

    if (!(ucm_malloc_hook_state.install_state & UCM_MALLOC_INSTALLED_SBRK_EVH)) {
        ucm_debug("installing malloc-sbrk event handler");
        ucm_event_handler_add(&ucm_malloc_sbrk_handler);
        ucm_malloc_hook_state.install_state |= UCM_MALLOC_INSTALLED_SBRK_EVH;
    }

    /* When running on valgrind, don't even try malloc hooks.
     * We want to release original blocks to silence the leak check, so we must
     * have a way to call the original free(), also these hooks don't work with
     * valgrind anyway.
     */
#if HAVE_MALLOC_HOOK
    if (ucm_global_config.enable_malloc_hooks) {
        /* Install using malloc hooks.
         * TODO detect glibc support in configure-time.
         */
        if (!(ucm_malloc_hook_state.install_state & UCM_MALLOC_INSTALLED_HOOKS)) {
            ucm_debug("installing malloc hooks");
            __free_hook     = ucm_free;
            __realloc_hook  = ucm_realloc;
            __malloc_hook   = ucm_malloc;
            __memalign_hook = ucm_memalign;
            ucm_malloc_hook_state.install_state |= UCM_MALLOC_INSTALLED_HOOKS;
        }

        /* Just installed the hooks, test again. */
        ucm_malloc_test(events);
        if (ucm_malloc_hook_state.hook_called) {
            goto out_install_opt_syms;
        }
    } else
#endif
    {
        ucm_debug("using malloc hooks is disabled by configuration");
    }

    /* Install using malloc symbols */
    if (ucm_global_config.enable_malloc_reloc) {
        if (!(ucm_malloc_hook_state.install_state & UCM_MALLOC_INSTALLED_MALL_SYMS)) {
            ucm_debug("installing malloc relocations");
            ucm_malloc_populate_glibc_cache();
            ucm_malloc_install_symbols(ucm_malloc_symbol_patches);
            ucs_assert(ucm_malloc_symbol_patches[0].value == ucm_free);
            ucm_malloc_hook_state.free           = ucm_malloc_symbol_patches[0].prev_value;
            ucm_malloc_hook_state.install_state |= UCM_MALLOC_INSTALLED_MALL_SYMS;
        }
    } else {
        ucm_debug("installing malloc relocations is disabled by configuration");
    }

    /* Just installed the symbols, test again */
    ucm_malloc_test(events);
    if (ucm_malloc_hook_state.hook_called) {
        goto out_install_opt_syms;
    }

    status = UCS_ERR_UNSUPPORTED;
    goto out_unlock;

out_install_opt_syms:
    ucm_malloc_install_optional_symbols();
    ucm_malloc_install_mallopt();
out_succ:
    status = UCS_OK;
out_unlock:
    pthread_mutex_unlock(&ucm_malloc_hook_state.install_mutex);
    return status;
}