diff --git a/acinclude.m4 b/acinclude.m4 index 43c1b6f7d2..0969e80af6 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -75,6 +75,7 @@ m4_include(config/ompi_setup_cxx.m4) m4_include(config/ompi_setup_f77.m4) m4_include(config/ompi_setup_f90.m4) m4_include(config/ompi_setup_libevent.m4) +m4_include(config/ompi_setup_memory.m4) m4_include(config/ompi_check_pthread_pids.m4) m4_include(config/ompi_config_pthreads.m4) diff --git a/config/ompi_config_threads.m4 b/config/ompi_config_threads.m4 index a48e6da33a..ac48191c1e 100644 --- a/config/ompi_config_threads.m4 +++ b/config/ompi_config_threads.m4 @@ -172,6 +172,9 @@ EOF AC_MSG_ERROR(["*** Can not continue."]) fi +AM_CONDITIONAL(OMPI_HAVE_POSIX_THREADS, test "$thread_type" = "posix") +AM_CONDITIONAL(OMPI_HAVE_SOLARIS_THREADS, test "$thread_type" = "solaris") + # # Now configure the whole MPI and progress thread gorp # diff --git a/config/ompi_setup_memory.m4 b/config/ompi_setup_memory.m4 new file mode 100644 index 0000000000..61ffa795eb --- /dev/null +++ b/config/ompi_setup_memory.m4 @@ -0,0 +1,92 @@ +dnl +dnl Copyright (c) 2004-2005 The Trustees of Indiana University. +dnl All rights reserved. +dnl Copyright (c) 2004-2005 The Trustees of the University of Tennessee. +dnl All rights reserved. +dnl Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +dnl University of Stuttgart. All rights reserved. +dnl Copyright (c) 2004-2005 The Regents of the University of California. +dnl All rights reserved. +dnl $COPYRIGHT$ +dnl +dnl Additional copyrights may follow +dnl +dnl $HEADER$ +dnl + +AC_DEFUN([OMPI_PTMALLOC_SETUP],[ +# +# Call the top-level OMPI threads setup stuff +# +OLD_CPPFLAGS="$CPPFLAGS" +OLD_LDFLAGS="$LDFLAGS" +OLD_LIBS="$LIBS" + +CPPFLAGS="$CPPFLAGS $THREADCPPFLAGS" +LDFLAGS="$LDFLAGS $THREADLDFLAGS" +LIBS="$LIBS $THREADLIBS" + +if test "`echo $host | grep apple-darwin`" != "" ; then + AC_MSG_WARN([*** Using ptmalloc with OS X will result in failure.]) + AC_MSG_ERROR([*** Aborting to save you the effort]) +fi + +# +# See if we have sbrk prototyped +# +AC_CHECK_DECL([sbrk], [have_decl_sbrk=1], [have_decl_sbrk=0]) +AC_DEFINE_UNQUOTED(OMPI_HAVE_DECL_SBRK, $have_decl_sbrk, + [Whether we have a declaration for sbrk() or not]) + +CPPFLAGS="$OLD_CPPFLAGS" +LDFLAGS="$OLD_LDFLAGS" +LIBS="$OLD_LIBS" +])dnl + + +AC_DEFUN([OMPI_DARWIN_MALLOC_SETUP],[ +case "$host" in + *apple-darwin*) + WRAPPER_EXTRA_LDFLAGS="-Wl,-u -Wl,_ompi_darwin_malloc_linker_hack -Wl,-multiply_defined,suppress -Wl,-force_flat_namespace -Wl,-flat_namespace $WRAPPER_EXTRA_LDFLAGS" + LDFLAGS="-Wl,-multiply_defined,suppress $LDFLAGS" + ;; + *) + AC_MSG_ERROR([Trying to use Darwin malloc while not on a Darwin system.]) + ;; +esac +])dnl + +AC_DEFUN([OMPI_MEMORY_SETUP],[ + +AC_ARG_WITH(memory-manager, + AC_HELP_STRING([--with-memory-manager=TYPE], + [Use TYPE for intercepting memory management calls to control memory pinning (TYPE is one of ptmalloc2,none)]), + [WANT_MEMORY="$withval"], [WANT_MEMORY="none"]) + +AC_MSG_CHECKING([for memory management type]) +if test "$WANT_MEMORY" = "darwin" ; then + AC_MSG_RESULT([Darwin / Mac OS X]) + OMPI_DARWIN_MALLOC_SETUP + OMPI_WANT_DARWIN7MALLOC=1 + OMPI_WANT_PTMALLOC2=0 + AC_MSG_ERROR([Darwin memory manager not currently supported]) +elif test "$WANT_MEMORY" = "ptmalloc2" ; then + AC_MSG_RESULT([ptmalloc2]) + OMPI_PTMALLOC_SETUP + OMPI_WANT_DARWIN7MALLOC=0 + OMPI_WANT_PTMALLOC2=1 +else + AC_MSG_RESULT([none]) + OMPI_WANT_DARWIN7MALLOC=0 + OMPI_WANT_PTMALLOC2=0 +fi + +AC_DEFINE_UNQUOTED([OMPI_WANT_PTMALLOC2], $OMPI_WANT_PTMALLOC2, + [Do we want ptmalloc2 support]) +AM_CONDITIONAL(OMPI_WANT_PTMALLOC2, test "$OMPI_WANT_PTMALLOC2" = "1") + +AC_DEFINE_UNQUOTED([OMPI_WANT_DARWIN7MALLOC], $OMPI_WANT_DARWIN7MALLOC, + [Do we want darwin7malloc support]) +AM_CONDITIONAL(OMPI_WANT_DARWIN7MALLOC, test "$OMPI_WANT_DARWIN7MALLOC" = "1") + +])dnl diff --git a/configure.ac b/configure.ac index 77452c5642..122e12301c 100644 --- a/configure.ac +++ b/configure.ac @@ -1338,6 +1338,11 @@ OMPI_CASE_SENSITIVE_FS_SETUP # AIX: FIONBIO in sys/ioctl.h # glibc: memcpy +# +# memory manager hooks +# +OMPI_MEMORY_SETUP + # checkpoint results AC_CACHE_SAVE @@ -1609,6 +1614,8 @@ AC_CONFIG_FILES([ opal/event/Makefile opal/event/compat/Makefile opal/event/compat/sys/Makefile + opal/memory/Makefile + opal/memory/ptmalloc2/Makefile opal/runtime/Makefile opal/threads/Makefile opal/util/Makefile @@ -1680,6 +1687,7 @@ AC_CONFIG_FILES([ test/mca/rds/Makefile test/mca/rmaps/Makefile test/mca/schema/Makefile + test/memory/Makefile test/runtime/Makefile test/support/Makefile test/threads/Makefile diff --git a/include/ompi_config_bottom.h b/include/ompi_config_bottom.h index 7737e40fac..99f06a8304 100644 --- a/include/ompi_config_bottom.h +++ b/include/ompi_config_bottom.h @@ -243,8 +243,12 @@ typedef long long bool; * include , which includes , but after * setting OMPI_BUILDING to 0 For 3, it's the same as 1 -- just include * first. + * + * Give code that needs to include ompi_config.h but really can't have + * this stuff enabled (like the memory manager code) a way to turn us + * off */ -#if OMPI_ENABLE_MEM_DEBUG +#if OMPI_ENABLE_MEM_DEBUG && !defined(OMPI_DISABLE_ENABLE_MEM_DEBUG) /* It is safe to include opal/util/malloc.h here because a) it will only happen when we are building OMPI and therefore have a full OMPI diff --git a/opal/Makefile.am b/opal/Makefile.am index 16206fe0eb..8a1edf21f2 100644 --- a/opal/Makefile.am +++ b/opal/Makefile.am @@ -37,6 +37,7 @@ libopal_la_LIBADD = \ class/libclass.la \ event/libevent.la \ mca/base/libmca_base.la \ + memory/libopalmemory.la \ runtime/libruntime.la \ threads/libthreads.la \ util/libopalutil.la diff --git a/opal/memory/Makefile.am b/opal/memory/Makefile.am index 5ad66c27c7..2476bc07ae 100644 --- a/opal/memory/Makefile.am +++ b/opal/memory/Makefile.am @@ -18,16 +18,22 @@ include $(top_srcdir)/config/Makefile.options noinst_LTLIBRARIES = libopalmemory.la +SUBDIRS = ptmalloc2 + # Source code files headers = \ memory.h \ memory_internal.h -libopalutil_la_SOURCES = \ +libopalmemory_la_SOURCES = \ $(headers) \ memory.c +if OMPI_WANT_PTMALLOC2 +libopalmemory_la_LIBADD = ptmalloc2/libptmalloc2.la +endif + # Conditionally install the header files if WANT_INSTALL_HEADERS diff --git a/opal/memory/memory.c b/opal/memory/memory.c index 6b77317ce9..1f29990dac 100644 --- a/opal/memory/memory.c +++ b/opal/memory/memory.c @@ -20,6 +20,7 @@ #include "opal/memory/memory.h" #include "opal/memory/memory_internal.h" #include "opal/class/opal_list.h" +#include "opal/class/opal_object.h" /* @@ -27,24 +28,27 @@ */ struct callback_list_item_t { opal_list_item_t super; - opal_mem_free_unpin_fn_t cbfunc; + opal_mem_free_unpin_fn_t *cbfunc; void *cbdata; }; typedef struct callback_list_item_t callback_list_item_t; -static OBJ_CLASS_INSTANCE(callback_list_item_t opal_list_item_t, NULL, NULL); +static OBJ_CLASS_INSTANCE(callback_list_item_t, opal_list_item_t, NULL, NULL); /* * local data */ static opal_list_t callback_list; static opal_atomic_lock_t callback_lock; -static bool have_free_support; +static bool have_free_support = false; + int opal_mem_free_init(void) { - OBJ_DECLARATION(&callback_list, opal_list_t); + OBJ_CONSTRUCT(&callback_list, opal_list_t); opal_atomic_init(&callback_lock, OPAL_ATOMIC_UNLOCKED); + + return OMPI_SUCCESS; } @@ -57,6 +61,17 @@ opal_mem_free_finalize(void) OBJ_RELEASE(item); } OBJ_DESTRUCT(&callback_list); + + return OMPI_SUCCESS; +} + + +/* called from memory manager / memory-manager specific hooks */ +void +opal_mem_free_set_free_support(bool support) +{ + printf("someone set mem_free support to %d\n", (int) support); + have_free_support = support; } @@ -88,7 +103,7 @@ opal_mem_free_is_supported(void) int -opal_mem_free_register_handler(opal_memory_unpin_t *func, void *cbdata) +opal_mem_free_register_handler(opal_mem_free_unpin_fn_t *func, void *cbdata) { opal_list_item_t *item; callback_list_item_t *cbitem; @@ -119,7 +134,7 @@ opal_mem_free_register_handler(opal_memory_unpin_t *func, void *cbdata) cbitem->cbfunc = func; cbitem->cbdata = cbdata; - opal_list_appemd(&callback_list, (opal_list_item_t*) cbitem); + opal_list_append(&callback_list, (opal_list_item_t*) cbitem); done: opal_atomic_unlock(&callback_lock); @@ -129,7 +144,7 @@ opal_mem_free_register_handler(opal_memory_unpin_t *func, void *cbdata) int -opal_mem_free_unregister_handler(opal_memory_unpin_t *func) +opal_mem_free_unregister_handler(opal_mem_free_unpin_fn_t *func) { opal_list_item_t *item; callback_list_item_t *cbitem; diff --git a/opal/memory/memory.h b/opal/memory/memory.h index 56ae63b9f1..1b0c3df4dd 100644 --- a/opal/memory/memory.h +++ b/opal/memory/memory.h @@ -88,7 +88,7 @@ bool opal_mem_free_is_supported(void); * @retval OMPI_ERR_NOT_SUPPORTED There are no hooks available for * receiving callbacks when memory is to be released */ -int opal_mem_free_register_handler(opal_memory_unpin_t *func, void *cbdata); +int opal_mem_free_register_handler(opal_mem_free_unpin_fn_t *func, void *cbdata); /** @@ -101,6 +101,6 @@ int opal_mem_free_register_handler(opal_memory_unpin_t *func, void *cbdata); * @retval OMPI_SUCCESS The function was successfully deregistered * @retval OMPI_ERR_NOT_FOUND The function was not previously registered */ -int opal_mem_free_unregister_handler(opal_memory_unpin_t *func); +int opal_mem_free_unregister_handler(opal_mem_free_unpin_fn_t *func); #endif /* OPAL_MEMORY_MEMORY_H */ diff --git a/opal/memory/memory_internal.h b/opal/memory/memory_internal.h index db4800f942..3738bf83bf 100644 --- a/opal/memory/memory_internal.h +++ b/opal/memory/memory_internal.h @@ -17,6 +17,7 @@ #ifndef OPAL_MEMORY_MEMORY_INTERNAL_H #define OPAL_MEMORY_MEMORY_INTERNAL_H +void opal_mem_free_set_free_support(bool support); void opal_mem_free_release_hook(void *buf, size_t length); #endif /* OPAL_MEMORY_MEMORY_INTERNAL_H */ diff --git a/opal/memory/ptmalloc2/Makefile.am b/opal/memory/ptmalloc2/Makefile.am new file mode 100644 index 0000000000..ec5c561e96 --- /dev/null +++ b/opal/memory/ptmalloc2/Makefile.am @@ -0,0 +1,64 @@ +# +# Copyright (c) 2004-2005 The Trustees of Indiana University. +# All rights reserved. +# Copyright (c) 2004-2005 The Trustees of the University of Tennessee. +# All rights reserved. +# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright (c) 2004-2005 The Regents of the University of California. +# All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +include $(top_srcdir)/config/Makefile.options + +AM_CPPFLAGS = -DMALLOC_DEBUG=0 + +if OMPI_HAVE_POSIX_THREADS +AM_CPPFLAGS += -DUSE_TSD_DATA_HACK \ + -Isysdeps/pthread +endif +if OMPI_HAVE_SOLARIS_THREADS +AM_CPPFLAGS += -Isysdeps/solaris +endif +# this must come *after* the threads -Is +AM_CPPFLAGS += -Isysdeps/generic + +# ptmalloc requires us to include the copyright notice in the +# software. So install it in the same place that we install ROMIO's +# copyright notices. + +docdir = $(datadir)/openmpi/doc +doc_DATA = ptmalloc2-COPYRIGHT + +if OMPI_WANT_PTMALLOC2 +noinst_LTLIBRARIES = libptmalloc2.la +endif + +libptmalloc2_la_SOURCES = \ + malloc.c \ + malloc-stats.c \ + malloc.h \ + thread-m.h \ + thread-st.h + +# these are included directly and shouldn't be built solo +EXTRA_libptmalloc2_la_SOURCES = \ + arena.c \ + hooks.c + +EXTRA_DIST = \ + ChangeLog \ + README \ + ChangeLog \ + lran2.h \ + t-test.h \ + t-test1.c \ + t-test2.c \ + tst-mallocstate.c \ + sysdeps \ + $(doc_DATA) diff --git a/opal/memory/ptmalloc2/arena.c b/opal/memory/ptmalloc2/arena.c index 66aa52c27f..698709a4ec 100644 --- a/opal/memory/ptmalloc2/arena.c +++ b/opal/memory/ptmalloc2/arena.c @@ -464,6 +464,13 @@ ptmalloc_init __MALLOC_P((void)) } if(__malloc_initialize_hook != NULL) (*__malloc_initialize_hook)(); + +/********************** BEGIN OMPI CHANGES *****************************/ + /* don't use __hook for this, as someone might want to use those + features */ + opal_mem_free_set_free_support(true); +/********************* BEGIN OMPI CHANGES ******************************/ + __malloc_initialized = 1; } diff --git a/opal/memory/ptmalloc2/malloc.c b/opal/memory/ptmalloc2/malloc.c index ce91eecf75..b462b1a52c 100644 --- a/opal/memory/ptmalloc2/malloc.c +++ b/opal/memory/ptmalloc2/malloc.c @@ -1,3 +1,61 @@ +/********************** BEGIN OMPI CHANGES *****************************/ +#define OMPI_DISABLE_ENABLE_MEM_DEBUG 1 +#include "ompi_config.h" + +#include +#include +#include +#include + +#include "opal/memory/memory_internal.h" + +/* + * Not all systems have sbrk() declared, since it's technically not a + * POSIX function. + */ +#if !OMPI_HAVE_DECL_SBRK +void *sbrk(); +#endif + +static void* +opal_mem_free_ptmalloc2_sbrk(int inc) +{ + if (inc < 0) { + long oldp = (long) sbrk(0); + opal_mem_free_release_hook((void*) (oldp + inc), -inc); + } + + return sbrk(inc); +} + +static int +opal_mem_free_ptmalloc2_munmap(void *start, size_t length) +{ + opal_mem_free_release_hook(start, length); + return munmap(start, length); +} + +#define MORECORE opal_mem_free_ptmalloc2_sbrk +#define munmap(a,b) opal_mem_free_ptmalloc2_munmap(a,b) +/* easier to just not use mremap - having it makes tracking more + difficult */ +#define HAVE_MREMAP 0 +/* set the threshold for switching from sbrk heap to mmap higher than + normal so that there are more things in the heap. mmap segments + are never reused, so this keeps the number of calls to munmap and + sbrk down significantly */ +#define DEFAULT_MMAP_THRESHOLD (2*1024*1024) + +/* make some non-GCC compilers happy */ +#ifndef __GNUC__ +#define __const const +#endif + +/********************* BEGIN OMPI CHANGES ******************************/ + + + + /* Malloc implementation for multiple threads without lock contention. Copyright (C) 1996-2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -852,7 +910,7 @@ Void_t* public_mALLOc(); #ifdef libc_hidden_proto libc_hidden_proto (public_mALLOc) #endif - + static void here(void); /* free(Void_t* p) Releases the chunk of memory pointed to by p, that had been previously diff --git a/opal/memory/ptmalloc2/malloc.h b/opal/memory/ptmalloc2/malloc.h index 1d486dc7b8..6d714d4bca 100644 --- a/opal/memory/ptmalloc2/malloc.h +++ b/opal/memory/ptmalloc2/malloc.h @@ -69,6 +69,9 @@ # if defined __cplusplus && (__GNUC__ >= 3 || __GNUC_MINOR__ >= 8) # define __THROW throw () # else +#ifdef __THROW +# undef __THROW +#endif # define __THROW # endif # define __MALLOC_P(args) args __THROW diff --git a/opal/memory/ptmalloc2/COPYRIGHT b/opal/memory/ptmalloc2/ptmalloc2-COPYRIGHT similarity index 100% rename from opal/memory/ptmalloc2/COPYRIGHT rename to opal/memory/ptmalloc2/ptmalloc2-COPYRIGHT diff --git a/opal/runtime/opal_finalize.c b/opal/runtime/opal_finalize.c index 55007a52e8..dc1fbf1dfd 100644 --- a/opal/runtime/opal_finalize.c +++ b/opal/runtime/opal_finalize.c @@ -22,6 +22,7 @@ #include "opal/class/opal_object.h" #include "opal/util/output.h" #include "opal/util/malloc.h" +#include "opal/memory/memory.h" #include "mca/base/base.h" #include "runtime/opal.h" @@ -41,6 +42,9 @@ int opal_finalize(void) /* finalize the output system */ opal_output_finalize(); + + /* finalize the memory manager / tracker */ + opal_mem_free_finalize(); /* finalize the class/object system */ opal_class_finalize(); diff --git a/opal/runtime/opal_init.c b/opal/runtime/opal_init.c index 2db01a71c0..11409c50e0 100644 --- a/opal/runtime/opal_init.c +++ b/opal/runtime/opal_init.c @@ -21,6 +21,7 @@ #include "include/orte_constants.h" #include "opal/util/malloc.h" #include "opal/util/output.h" +#include "opal/memory/memory.h" #include "mca/base/base.h" #include "runtime/opal.h" @@ -35,10 +36,12 @@ */ int opal_init(void) { - /* initialize the memory allocator */ opal_malloc_init(); + /* initialize the memory manager / tracker */ + opal_mem_free_init(); + /* initialize the output system */ opal_output_init(); diff --git a/test/Makefile.am b/test/Makefile.am index 338abeba41..922f749a74 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -17,4 +17,4 @@ include $(top_srcdir)/test/support/Makefile.options # support needs to be first for dependencies -SUBDIRS = support asm class dps mca runtime threads util +SUBDIRS = support asm class dps mca memory runtime threads util diff --git a/test/memory/Makefile.am b/test/memory/Makefile.am new file mode 100644 index 0000000000..18960b378b --- /dev/null +++ b/test/memory/Makefile.am @@ -0,0 +1,29 @@ +# +# Copyright (c) 2004-2005 The Trustees of Indiana University. +# All rights reserved. +# Copyright (c) 2004-2005 The Trustees of the University of Tennessee. +# All rights reserved. +# Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, +# University of Stuttgart. All rights reserved. +# Copyright (c) 2004-2005 The Regents of the University of California. +# All rights reserved. +# $COPYRIGHT$ +# +# Additional copyrights may follow +# +# $HEADER$ +# + +include $(top_srcdir)/test/support/Makefile.options + +check_PROGRAMS = \ + opal_memory_basic + +TESTS = \ + $(check_PROGRAMS) + +opal_memory_basic_SOURCES = opal_memory_basic.c +opal_memory_basic_LDADD = \ + $(top_builddir)/opal/libopal.la \ + $(top_builddir)/test/support/libsupport.a +opal_memory_basic_DEPENDENCIES = $(opal_memory_basic_LDADD) diff --git a/test/memory/opal_memory_basic.c b/test/memory/opal_memory_basic.c new file mode 100644 index 0000000000..318fa0ab8f --- /dev/null +++ b/test/memory/opal_memory_basic.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2004-2005 The Trustees of Indiana University. + * All rights reserved. + * Copyright (c) 2004-2005 The Trustees of the University of Tennessee. + * All rights reserved. + * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, + * University of Stuttgart. All rights reserved. + * Copyright (c) 2004-2005 The Regents of the University of California. + * All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "ompi_config.h" + +#include +#include + +#include "ompi/include/constants.h" +#include "opal/runtime/opal.h" +#include "opal/memory/memory.h" + +int ret = 1; +int size = 10 * 1024 * 1024; + +static void +callback(void *buf, size_t length, void *cbdata) +{ + printf("\tcallback with %lx, %d\n", (unsigned long) buf, (int) length); + ret = 0; +} + +int +main(int argc, char *argv[]) +{ + void * foo; + int retval; + + opal_init(); + + if (!opal_mem_free_is_supported()) { + printf("no memory registration supported. skipping\n"); + return 77; + } + + retval = opal_mem_free_register_handler(callback, NULL); + if (retval != OMPI_SUCCESS) return retval; + + /* make some big malloc that should trip an unmap */ + foo = malloc(size); + free(foo); + + retval = opal_mem_free_unregister_handler(callback); + if (retval != OMPI_SUCCESS) return retval; + + opal_finalize(); + + return ret; +}