1
1

- Add configure-time switch (--enable-ptmalloc2-opt-sbrk) to control when

the ptmalloc2 memory hooks component triggers callbacks for memory
  allocation / deallocation.  If enabled (the default) it is only when
  memory is actually obtained from or released to the OS (so little
  malloc calls only trigger callbacks if sbrk is called).  If disabled,
  callbacks are triggered every time malloc/free/etc. is called
* It turns out that syscall and mmap aren't good friends due to the return
  type of mmap and some old legacy issues with syscall functions that
  take more than 5 parameters.  For now, default to either loading
  the symbol from glibc using dlsym or using the __m{un,}map functions.
  Thanks to George for finding this.
* Fix some dumb typos in the mmap / munmap catching code

This commit was SVN r8410.
Этот коммит содержится в:
Brian Barrett 2005-12-08 04:47:03 +00:00
родитель 5232519235
Коммит 364ca3f075
4 изменённых файлов: 160 добавлений и 67 удалений

Просмотреть файл

@ -469,10 +469,15 @@ ptmalloc_init __MALLOC_P((void))
/* don't use __hook for this, as someone might want to use those
features */
opal_mem_hooks_set_support(OPAL_MEMORY_FREE_SUPPORT |
#if defined(HAVE_SYSCALL) || defined(HAVE___MMAP)
#if defined(HAVE___MMAP) || defined(HAVE_DLSYM)
OPAL_MEMORY_MALLOC_SUPPORT |
#endif
OPAL_MEMORY_CHUNK_SUPPORT);
#if OMPI_MEMORY_PTMALLOC2_OPT_SBRK
OPAL_MEMORY_CHUNK_SUPPORT
#else
0
#endif
);
/********************* BEGIN OMPI CHANGES ******************************/
__malloc_initialized = 1;

Просмотреть файл

@ -33,6 +33,21 @@ AC_DEFUN([MCA_memory_ptmalloc2_CONFIG],[
[Use TYPE for intercepting memory management
calls to control memory pinning.])])
AC_ARG_ENABLE([ptmalloc2-opt-sbrk],
[AC_HELP_STRING([--enable-ptmalloc2-opt-sbrk],
[Only trigger callbacks when sbrk is used for small
allocations, rather than every call to malloc/free.
(default: enabled)])])
if test "$enable_ptmalloc2_opt_sbrk" = "no" ; then
memory_ptmalloc2_opt_sbrk=0
else
memory_ptmalloc2_opt_sbrk=1
fi
AC_DEFINE_UNQUOTED([OMPI_MEMORY_PTMALLOC2_OPT_SBRK],
[$memory_ptmalloc2_opt_sbrk],
[Trigger callbacks on sbrk instead of malloc or free])
AS_IF([test "$with_memory_manager" = "ptmalloc2"],
[if test "`echo $host | grep apple-darwin`" != "" ; then
AC_MSG_WARN([*** Using ptmalloc with OS X will result in failure.])
@ -45,11 +60,6 @@ AC_DEFUN([MCA_memory_ptmalloc2_CONFIG],[
[memory_ptmalloc2_happy="yes"],
[memory_ptmalloc2_happy="no"])])
AS_IF([test "$memory_ptmalloc2_happy" = "yes"],
[AS_IF([test "$enable_mpi_threads" = "yes" -o \
"$enable_progress_threads" = "yes"],
[memory_ptmalloc2_happy="no"])])
AS_IF([test "$memory_ptmalloc2_happy" = "yes"],
[# check for malloc.h
AC_CHECK_HEADER([malloc.h],
@ -74,28 +84,35 @@ AC_DEFUN([MCA_memory_ptmalloc2_CONFIG],[
#
AS_IF([test "$memory_ptmalloc2_happy" = "yes"],
[memory_ptmalloc2_mmap=0
AS_IF([test "$memory_ptmalloc2_mmap" = "0"],
[AC_CHECK_HEADER([syscall.h],
[AC_CHECK_FUNCS([syscall], [memory_ptmalloc2_mmap=1])])])
memory_ptmalloc2_munmap=1
AS_IF([test "$memory_ptmalloc2_mmap" = "0"],
[AC_CHECK_FUNCS([__munmap], [memory_ptmalloc2_mmap=1])
AC_CHECK_FUNCS([__mmap])])
# it's nearly impossible to call mmap from syscall(), so
# only go this route if we can't get at munmap any other
# way.
AC_CHECK_HEADER([syscall.h],
[AC_CHECK_FUNCS([syscall], [], [memory_ptmalloc2_munmap=0])])
# Always look for __munmap and __mmap
AC_CHECK_FUNCS([__munmap], [memory_ptmalloc2_mmap=1])
AC_CHECK_FUNCS([__mmap])
# only allow dlsym (and therefore add -ldl) if we
# really need to
AS_IF([test "$memory_ptmalloc2_mmap" = "0"],
[memory_ptmalloc2_LIBS_SAVE="$LIBS"
AC_CHECK_LIB([dl],
[dlsym],
[memory_ptmalloc2_LIBS="-ldl"
[LIBS="$LIBS -ldl"
memory_ptmalloc2_LIBS="-ldl"
memory_ptmalloc2_mmap=1])
AC_CHECK_FUNCS([dlsym])
LIBS="$memory_ptmalloc2_LIBS_SAVE"])
AS_IF([test "$memory_ptmalloc2_mmap" = "0"],
AS_IF([test "$memory_ptmalloc2_mmap" = "0" -a "$memory_ptmalloc2_munmap" = "0"],
[memory_ptmalloc2_happy="no"])])
AS_IF([test "$memory_ptmalloc2_happy" = "yes"],
[memory_ptmalloc2_WRAPPER_EXTRA_LIBS="$memory_ptmalloc2_LIBS"])
AS_IF([test "$memory_ptmalloc2_happy" = "yes"],
[memory_ptmalloc2_WRAPPER_EXTRA_LIBS="$memory_ptmalloc2_LIBS"])
AS_IF([test "$memory_ptmalloc2_happy" = "no" -a \
"$memory_malloc_hoooks_should_use" = "1"],

Просмотреть файл

@ -15,13 +15,16 @@
void *sbrk();
#endif
#if OMPI_MEMORY_PTMALLOC2_OPT_SBRK
static void*
opal_mem_free_ptmalloc2_sbrk(int inc)
{
if (inc < 0) {
long oldp = (long) sbrk(0);
opal_mem_hooks_release_hook((void*) (oldp + inc), -inc);
#if defined(HAVE_SYSCALL) || defined(HAVE___MMAP)
#if defined(HAVE___MMAP) || defined(HAVE_DLSYM)
} else if (inc > 0) {
long oldp = (long) sbrk(0);
opal_mem_hooks_alloc_hook((void*) oldp, inc);
@ -32,13 +35,24 @@ opal_mem_free_ptmalloc2_sbrk(int inc)
}
extern int opal_mem_free_ptmalloc2_munmap(void *start, size_t length);
#if defined(HAVE___MMAP) || defined(HAVE_DLSYM)
extern void* opal_mem_free_ptmalloc2_mmap(void *start, size_t length,
int prot, int flags,
int fd, off_t offset);
#endif
/* if we are trying to catch only allocations from and releases to the
operating system, intercept sbrk, mmap, and munmap. If we want to
intercept every call to malloc/realloc/free/etc., don't do this, as
we need to add something into each of those calls anyway. */
#define MORECORE opal_mem_free_ptmalloc2_sbrk
#define munmap(a,b) opal_mem_free_ptmalloc2_munmap(a,b)
#define mmap(a, b, c, d, e, f) opal_mem_free_ptmalloc2_mmap(a, b, c, d, e, f)
#if defined(HAVE___MMAP) || defined(HAVE_DLSYM)
#define mmap(a,b,c,d,e,f) opal_mem_free_ptmalloc2_mmap(a,b,c,d,e,f)
#endif
#endif /* OMPI_MEMORY_PTMALLOC2_OPT_SBRK */
/* easier to just not use mremap - having it makes tracking more
difficult */
#define HAVE_MREMAP 0
@ -3430,6 +3444,12 @@ public_mALLOc(size_t bytes)
(void)mutex_unlock(&ar_ptr->mutex);
assert(!victim || chunk_is_mmapped(mem2chunk(victim)) ||
ar_ptr == arena_for_chunk(mem2chunk(victim)));
/* OMPI Change */
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_alloc_hook(victim, mUSABLe(victim));
#endif
return victim;
}
#ifdef libc_hidden_def
@ -3448,6 +3468,10 @@ public_fREe(Void_t* mem)
(*hook)(mem, RETURN_ADDRESS (0));
return;
}
/* OMPI change */
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_release_hook(mem, mUSABLe(mem));
#endif
if (mem == 0) /* free(0) has no effect */
return;
@ -3496,6 +3520,10 @@ public_rEALLOc(Void_t* oldmem, size_t bytes)
__realloc_hook;
if (hook != NULL)
return (*hook)(oldmem, bytes, RETURN_ADDRESS (0));
/* OMPI change */
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_release_hook(mem, mUSABLe(mem));
#endif
#if REALLOC_ZERO_BYTES_FREES
if (bytes == 0 && oldmem != NULL) { public_fREe(oldmem); return 0; }
@ -3516,15 +3544,29 @@ public_rEALLOc(Void_t* oldmem, size_t bytes)
#if HAVE_MREMAP
newp = mremap_chunk(oldp, nb);
if(newp) return chunk2mem(newp);
if(newp) {
/* OMPI Change */
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_alloc_hook(newp, mUSABLe(newp));
#endif
return chunk2mem(newp);
}
#endif
/* Note the extra SIZE_SZ overhead. */
if(oldsize - SIZE_SZ >= nb) return oldmem; /* do nothing */
if(oldsize - SIZE_SZ >= nb) {
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_alloc_hook(oldmem, mUSABLe(oldmem));
#endif
return oldmem; /* do nothing */
}
/* Must alloc, copy, free. */
newmem = public_mALLOc(bytes);
if (newmem == 0) return 0; /* propagate failure */
MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ);
munmap_chunk(oldp);
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_alloc_hook(newmem, mUSABLe(newmem));
#endif
return newmem;
}
#endif
@ -3551,6 +3593,9 @@ public_rEALLOc(Void_t* oldmem, size_t bytes)
(void)mutex_unlock(&ar_ptr->mutex);
assert(!newp || chunk_is_mmapped(mem2chunk(newp)) ||
ar_ptr == arena_for_chunk(mem2chunk(newp)));
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_alloc_hook(newp, mUSABLe(newp));
#endif
return newp;
}
#ifdef libc_hidden_def
@ -3599,6 +3644,9 @@ public_mEMALIGn(size_t alignment, size_t bytes)
}
assert(!p || chunk_is_mmapped(mem2chunk(p)) ||
ar_ptr == arena_for_chunk(mem2chunk(p)));
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_alloc_hook(p, mUSABLe(p));
#endif
return p;
}
#ifdef libc_hidden_def
@ -3618,6 +3666,9 @@ public_vALLOc(size_t bytes)
return 0;
p = _int_valloc(ar_ptr, bytes);
(void)mutex_unlock(&ar_ptr->mutex);
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_alloc_hook(p, mUSABLe(p));
#endif
return p;
}
@ -3632,6 +3683,9 @@ public_pVALLOc(size_t bytes)
arena_get(ar_ptr, bytes + 2*mp_.pagesize + MINSIZE);
p = _int_pvalloc(ar_ptr, bytes);
(void)mutex_unlock(&ar_ptr->mutex);
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_alloc_hook(p, mUSABLe(p));
#endif
return p;
}
@ -3668,6 +3722,9 @@ public_cALLOc(size_t n, size_t elem_size)
return memset(mem, 0, sz);
#else
while(sz > 0) ((char*)mem)[--sz] = 0; /* rather inefficient */
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_alloc_hook(mem, mUSABLe(mem));
#endif
return mem;
#endif
}
@ -3722,8 +3779,12 @@ public_cALLOc(size_t n, size_t elem_size)
/* Two optional cases in which clearing not necessary */
#if HAVE_MMAP
if (chunk_is_mmapped(p))
if (chunk_is_mmapped(p)) {
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_alloc_hook(mem, mUSABLe(mem));
#endif
return mem;
}
#endif
csz = chunksize(p);
@ -3764,6 +3825,9 @@ public_cALLOc(size_t n, size_t elem_size)
}
}
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_alloc_hook(mem, mUSABLe(mem));
#endif
return mem;
}
@ -3779,6 +3843,9 @@ public_iCALLOc(size_t n, size_t elem_size, Void_t** chunks)
m = _int_icalloc(ar_ptr, n, elem_size, chunks);
(void)mutex_unlock(&ar_ptr->mutex);
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_alloc_hook(m, mUSABLe(m));
#endif
return m;
}
@ -3794,6 +3861,9 @@ public_iCOMALLOc(size_t n, size_t sizes[], Void_t** chunks)
m = _int_icomalloc(ar_ptr, n, sizes, chunks);
(void)mutex_unlock(&ar_ptr->mutex);
#if !OMPI_MEMORY_PTMALLOC2_OPT_SBRK
opal_mem_hooks_alloc_hook(m, mUSABLe(m));
#endif
return m;
}

Просмотреть файл

@ -21,14 +21,16 @@
#include <sys/types.h>
#include <stdlib.h>
#include <sys/mman.h>
#if defined(HAVE_SYSCALL)
#if defined(HAVE___MUNMAP)
/* here so we only include dlfcn if we absolutely have to */
#elif defined(HAVE_DLSYM)
#ifndef __USE_GNU
#define __USE_GNU
#endif
#include <dlfcn.h>
#elif defined(HAVE_SYSCALL)
#include <syscall.h>
#include <unistd.h>
#elif defined(HAVE___MUNMAP)
/* here only so that we only include dlfcn.h if needed */
#elif defined(HAVE_DLSYM)
#define __USE_GNU
#include <dlfcn.h>
#endif
#include "opal/memoryhooks/memory_internal.h"
@ -37,7 +39,7 @@
* munmap is always intercepted
*/
int opal_mem_free_ptmalloc2_munmap(void *start, size_t length);
#if defined(HAVE_SYSCALL) || defined(HAVE___MUNMAP)
#if defined(HAVE___MUNMAP)
int __munmap(void* addr, size_t len);
#endif
@ -50,16 +52,6 @@ munmap(void* addr, size_t len)
}
/* with syscall, we can safely intercept this as well */
#if defined(HAVE_SYSCALL)
int
__munmap(void* addr, size_t len)
{
return opal_mem_free_ptmalloc2_munmap(addr, len);
}
#endif
/* three ways to call munmap. Prefered is to just call syscall, so
that we can intercept both munmap and __munmap. If that isn't
possible, try calling __munmap from munmap and let __munmap go. If
@ -67,29 +59,35 @@ __munmap(void* addr, size_t len)
int
opal_mem_free_ptmalloc2_munmap(void *start, size_t length)
{
#ifdef HAVE_DLSYM
#if !defined(HAVE___MUNMAP) && defined(HAVE_DLSYM)
static int (*realmunmap)(void*, size_t);
#endif
opal_mem_hooks_release_hook(start, length);
#if defined(HAVE_SYSCALL)
return syscall(__NR_munmap, start, length);
#elif defined(HAVE___MUNMAP)
#if defined(HAVE___MUNMAP)
return __munmap(start, length);
#elif defined(HAVE_DLSYM)
if (NULL == realmunmap) {
realmunmap = (int (*)(void*, size_t)) dlsym(RTLD_NEXT, "munmap");
union {
int (*munmap_fp)(void*, size_t);
void *munmap_p;
} tmp;
tmp.munmap_p = dlsym(RTLD_NEXT, "munmap");
realmunmap = tmp.munmap_fp;
}
return realmunmap(start, length);
#elif defined(HAVE_SYSCALL)
return syscall(__NR_munmap, start, length);
#else
#error "Can not determine how to call munmap"
#endif
}
#if defined(HAVE_SYSCALL) || defined(HAVE___MMAP)
#if defined(HAVE___MMAP) || defined(HAVE_DLSYM)
/*
* mmap is only intercepted if we have a chance of finding it (ie, a
* syscall or weak symbol)
@ -98,8 +96,10 @@ void* opal_mem_free_ptmalloc2_mmap(void *start, size_t length,
int prot, int flags,
int fd, off_t offset);
#if defined(HAVE___MMAP)
void* __mmap(void *start, size_t length, int prot, int flags,
int fd, off_t offset);
#endif
void*
@ -109,37 +109,38 @@ mmap(void *start, size_t length, int prot, int flags,
return opal_mem_free_ptmalloc2_mmap(start, length, prot, flags,
fd, offset);
}
#if defined(HAVE_SYSCALL)
/* with syscall, we can safely intercept this as well */
void*
__mmap(void *start, size_t length, int prot, int flags,
int fd, off_t offset)
{
return opal_mem_free_ptmalloc2_mmap(start, length, prot, flags,
fd, offset);
}
#endif
/* three ways to call mmap. Prefered is to just call syscall, so that
we can intercept both munmap and __munmap. If that isn't possible,
try calling __mmap from mmap and let __mmap go. Do not try to
dlsym, as that generally requires calling mmap.
*/
void* opal_mem_free_ptmalloc2_mmap(void *start, size_t length,
int prot, int flags,
int fd, off_t offset)
{
opal_mem_hooks_alloc_hook(start, length);
#if !defined(HAVE___MMAP) && defined(HAVE_DLSYM)
static void* (*realmmap)(void *, size_t, int, int, int, off_t);
#endif
void *tmp;
#if defined(HAVE___MUNMAP)
tmp = __mmap(start, length, prot, flags, fd, offset);
#elif defined(HAVE_DLSYM)
if (NULL == realmmap) {
union {
void* (*mmap_fp)(void *, size_t, int, int, int, off_t);
void *mmap_p;
} tmp;
tmp.mmap_p = dlsym(RTLD_NEXT, "mmap");
realmmap = tmp.mmap_fp;
}
tmp = realmmap(start, length, prot, flags, fd, offset);
#if defined(HAVE_SYSCALL)
return (void*) syscall(__NR_mmap, start, length, prot, flags, fd, offset);
#elif defined(HAVE___MUNMAP)
return __mmap(start, length, prot, flags, fd, offset);
#else
#error "Can not determine how to call mmap"
#endif
opal_mem_hooks_alloc_hook(tmp, length);
return tmp;
}
#endif /* #if defined(HAVE_SYSCALL) || defined(HAVE___MMAP) */
#endif /* defined(HAVE___MMAP) || defined(HAVE_DLSYM) */