diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2012-02-27 03:26:59 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2012-02-27 03:26:59 +0000 |
commit | 6f1d9dd9f40b000f03c209207e98d8a4469594bb (patch) | |
tree | 7f822db4fc92fa66f9ea97a862242b8124f9965b | |
parent | 352462dacc05290102a18fa77964998d68e6380d (diff) |
Add options to use mmap or electric fence to check memory accesses, and fix a few memory access violations.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1294008 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | sca-cpp/trunk/configure.ac | 42 | ||||
-rwxr-xr-x | sca-cpp/trunk/etc/memgrind | 2 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/gc.hpp | 134 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/mem-test.cpp | 4 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/string-test.cpp | 2 | ||||
-rw-r--r-- | sca-cpp/trunk/kernel/xml.hpp | 4 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/java/eval.hpp | 1 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/json/json-test.cpp | 3 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/opencl/eval.hpp | 1 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/eval.hpp | 1 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/server/client-test.hpp | 24 |
11 files changed, 167 insertions, 51 deletions
diff --git a/sca-cpp/trunk/configure.ac b/sca-cpp/trunk/configure.ac index cb85c3930e..6adf807db2 100644 --- a/sca-cpp/trunk/configure.ac +++ b/sca-cpp/trunk/configure.ac @@ -123,7 +123,6 @@ if test "${want_maintainer_mode}" = "true"; then else cxxflags="${cxxflags} -O2 -Wlogical-op -Wconversion" fi - ldflags="${ldflags} -pg" AM_CONDITIONAL([WANT_MAINTAINER_MODE], true) AC_DEFINE([WANT_MAINTAINER_MODE], 1, [compile with debugging and compile-time warnings]) else @@ -158,6 +157,47 @@ else AM_CONDITIONAL([WANT_PROFILING], false) fi +# Enable memory checking with electric fence. +AC_MSG_CHECKING([whether to enable electric fence]) +AC_ARG_ENABLE(efence, [AS_HELP_STRING([--enable-efence], [link with electric fence [default=no]])], +[ case "${enableval}" in + no) + AC_MSG_RESULT(no) + ;; + *) + AC_MSG_RESULT(yes) + want_efence=true + ;; + esac ], +[ AC_MSG_RESULT(no)]) +if test "${want_efence}" = "true"; then + ldflags="${ldflags} -lefence" + AM_CONDITIONAL([WANT_EFENCE], true) + AC_DEFINE([WANT_EFENCE], 1, [link with electric fence]) +else + AM_CONDITIONAL([WANT_EFENCE], false) +fi + +# Enable usage of mmap for memory allocation. +AC_MSG_CHECKING([whether to use mmap for memory allocation]) +AC_ARG_ENABLE(malloc-mmap, [AS_HELP_STRING([--enable-malloc-mmap], [use mmap for memory allocation [default=no]])], +[ case "${enableval}" in + no) + AC_MSG_RESULT(no) + ;; + *) + AC_MSG_RESULT(yes) + want_malloc_mmap=true + ;; + esac ], +[ AC_MSG_RESULT(no)]) +if test "${want_efence}" = "true"; then + AM_CONDITIONAL([WANT_MALLOC_MMAP], true) + AC_DEFINE([WANT_MALLOC_MMAP], 1, [use mmap for memory allocation]) +else + AM_CONDITIONAL([WANT_MALLOC_MMAP], false) +fi + # Enable multi-threading support. AC_MSG_CHECKING([whether to compile for multi-threaded execution]) AC_ARG_ENABLE(threads, [AS_HELP_STRING([--enable-threads], [compile for multi-threaded execution [default=no]])], diff --git a/sca-cpp/trunk/etc/memgrind b/sca-cpp/trunk/etc/memgrind index 6fbb76bc30..079adca595 100755 --- a/sca-cpp/trunk/etc/memgrind +++ b/sca-cpp/trunk/etc/memgrind @@ -19,5 +19,5 @@ # Run valgrind to analyze memory usage and track memory leaks -valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=40 --track-fds=yes $* 2>&1 | tee memgrind.log +valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=40 --track-fds=yes --trace-children=yes $* 2>&1 | tee memgrind.log diff --git a/sca-cpp/trunk/kernel/gc.hpp b/sca-cpp/trunk/kernel/gc.hpp index 28ca80edc9..59947dd853 100644 --- a/sca-cpp/trunk/kernel/gc.hpp +++ b/sca-cpp/trunk/kernel/gc.hpp @@ -26,6 +26,10 @@ * Garbage collected memory management, using APR memory pools. */ +#ifdef WANT_MALLOC_MMAP +#include <sys/mman.h> +#include <malloc.h> +#endif #include <stdlib.h> #include <apr_general.h> #include <apr_pools.h> @@ -112,6 +116,16 @@ public: }; /** + * Initialize APR. + */ +class gc_apr_context_t { +public: + gc_apr_context_t() { + apr_initialize(); + } +} gc_apr_context; + +/** * Garbage collected APR memory pool. */ class gc_pool { @@ -161,21 +175,13 @@ apr_pool_t* pool(const gc_pool& pool) { * Destroy a memory pool. */ const bool destroy(const gc_pool& p) { + if (pool(p) == NULL) + return false; apr_pool_destroy(pool(p)); return true; } /** - * Initialize APR. - */ -class gc_apr_context_t { -public: - gc_apr_context_t() { - apr_initialize(); - } -} gc_apr_context; - -/** * Maintain a stack of memory pools. */ #ifdef WANT_THREADS @@ -273,7 +279,7 @@ private: * register a cleanup callback for it. */ template<typename T> apr_status_t gc_pool_cleanup(void* v) { - T* t = static_cast<T*>(v); + T* t = (T*)v; t->~T(); return APR_SUCCESS; } @@ -282,7 +288,7 @@ template<typename T> T* gc_new(apr_pool_t* p) { void* gc_new_ptr = apr_palloc(p, sizeof(T)); assertOrFail(gc_new_ptr != NULL); apr_pool_cleanup_register(p, gc_new_ptr, gc_pool_cleanup<T>, apr_pool_cleanup_null) ; - return static_cast<T*>(gc_new_ptr); + return (T*)(gc_new_ptr); } template<typename T> T* gc_new(const gc_pool& p) { @@ -334,42 +340,112 @@ char* gc_cnew(size_t n) { /** * Pool based equivalent of the standard malloc function. */ -void* gc_malloc(size_t n) { - size_t* gc_malloc_ptr = static_cast<size_t*>(apr_palloc(gc_current_pool(), sizeof(size_t) + n)); - assertOrFail(gc_malloc_ptr != NULL); - *gc_malloc_ptr = n; - return gc_malloc_ptr + 1; +void* gc_pool_malloc(size_t n) { + size_t* ptr = static_cast<size_t*>(apr_palloc(gc_current_pool(), sizeof(size_t) + n)); + assertOrFail(ptr != NULL); + *ptr = n; + return ptr + 1; } /** * Pool based equivalent of the standard realloc function. */ -void* gc_realloc(void* ptr, size_t n) { +void* gc_pool_realloc(void* ptr, size_t n) { size_t size = *(static_cast<size_t*>(ptr) - 1); - size_t* gc_realloc_ptr = static_cast<size_t*>(apr_palloc(gc_current_pool(), sizeof(size_t) + n)); - assertOrFail(gc_realloc_ptr != NULL); - *gc_realloc_ptr = n; - memcpy(gc_realloc_ptr + 1, ptr, size < n? size : n); - return gc_realloc_ptr + 1; + size_t* rptr = static_cast<size_t*>(apr_palloc(gc_current_pool(), sizeof(size_t) + n)); + assertOrFail(rptr != NULL); + *rptr = n; + memcpy(rptr + 1, ptr, size < n? size : n); + return rptr + 1; } /** * Pool based equivalent of the standard free function. */ -void gc_free(unused void* ptr) { +void gc_pool_free(unused void* ptr) { // Memory allocated from a pool is freed when the pool is freed } /** * Pool based equivalent of the standard strdup function. */ -char* gc_strdup(const char* str) { - char* gc_strdup_ptr = static_cast<char*>(gc_malloc(strlen(str) + 1)); - assertOrFail(gc_strdup_ptr != NULL); - strcpy(gc_strdup_ptr, str); - return gc_strdup_ptr; +char* gc_pool_strdup(const char* str) { + char* dptr = static_cast<char*>(gc_pool_malloc(strlen(str) + 1)); + assertOrFail(dptr != NULL); + strcpy(dptr, str); + return dptr; +} + +#ifdef WANT_MALLOC_MMAP + +/** + * Mmap based memory allocation functions. + */ + +/** + * Mmap based equivalent of the standard malloc function. + */ +void* gc_mmap_malloc(size_t n, unused const void* caller) { + //printf("gc_mmap_malloc %d", n); + size_t* ptr = static_cast<size_t*>(mmap(NULL, sizeof(size_t) + n, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); + assertOrFail(ptr != NULL); + *ptr = n; + //printf(" %p\n", ptr + 1); + return ptr + 1; +} + +/** + * Mmap based equivalent of the standard realloc function. + */ +void* gc_mmap_realloc(void* ptr, size_t n, const void* caller) { + if (ptr == NULL) + return gc_mmap_malloc(n, caller);; + //printf("gc_mmap_realloc %p %d", ptr, n); + size_t size = *(static_cast<size_t*>(ptr) - 1); + size_t* rptr = static_cast<size_t*>(mremap(static_cast<size_t*>(ptr) - 1, sizeof(size_t) + size, sizeof(size_t) + n, MREMAP_MAYMOVE, NULL)); + assertOrFail(rptr != NULL); + *rptr = n; + //printf(" %p\n", rptr + 1); + return rptr + 1; +} + +/** + * Mmap based equivalent of the standard free function. + */ +void gc_mmap_free(void* ptr, unused const void* caller) { + //printf("gc_mmap_free %p\n", ptr); + if (ptr == NULL) + return; + size_t size = *(static_cast<size_t*>(ptr) - 1); + munmap(static_cast<size_t*>(ptr) - 1, sizeof(size_t) + size); } +/** + * Mmap based equivalent of the standard memalign function. + */ +void* gc_mmap_memalign(unused size_t alignment, size_t n, unused const void* caller) { + //printf("gc_mmap_memalign %d %d\n", alignment, n); + return gc_mmap_malloc(n, caller); } +/** + * Install the mmap based memory allocation functions. + */ +void gc_mmap_init_hook(void) { + __malloc_hook = gc_mmap_malloc; + __realloc_hook = gc_mmap_realloc; + __free_hook = gc_mmap_free; + __memalign_hook = gc_mmap_memalign; +} + +#endif + +} + +#ifdef WANT_MALLOC_MMAP + +void (*__malloc_initialize_hook)(void) = tuscany::gc_mmap_init_hook; + +#endif + #endif /* tuscany_gc_hpp */ diff --git a/sca-cpp/trunk/kernel/mem-test.cpp b/sca-cpp/trunk/kernel/mem-test.cpp index b1164a5a36..e9a2f85ec6 100644 --- a/sca-cpp/trunk/kernel/mem-test.cpp +++ b/sca-cpp/trunk/kernel/mem-test.cpp @@ -103,7 +103,7 @@ struct poolAllocPerf { }; bool testPoolAllocPerf() { - const int count = 100000; + const int count = 10000; const lambda<bool()> pl = poolAllocPerf(count); maxElements = 0; cout << "Memory pool alloc test " << (time(pl, 1, 1) / count) << " ms" << endl; @@ -139,7 +139,7 @@ struct stdAllocPerf { }; bool testStdAllocPerf() { - const int count = 100000; + const int count = 10000; const lambda<bool()> sl = stdAllocPerf(count); maxElements = 0; cout << "Memory standard alloc test " << (time(sl, 1, 1) / count) << " ms" << endl; diff --git a/sca-cpp/trunk/kernel/string-test.cpp b/sca-cpp/trunk/kernel/string-test.cpp index f2f21f6ea6..e691d93dfb 100644 --- a/sca-cpp/trunk/kernel/string-test.cpp +++ b/sca-cpp/trunk/kernel/string-test.cpp @@ -153,7 +153,7 @@ bool testStringPerf() { memset(charBuffer, 'A', 16384); charBuffer[16384] = '\0'; - const int count = 100000; + const int count = 10000; { const lambda<bool()> a16 = addStrings(16); cout << "string test " << time(a16, 5, count) << " ms" << endl; diff --git a/sca-cpp/trunk/kernel/xml.hpp b/sca-cpp/trunk/kernel/xml.hpp index 1f1c664c2d..b53093201d 100644 --- a/sca-cpp/trunk/kernel/xml.hpp +++ b/sca-cpp/trunk/kernel/xml.hpp @@ -51,12 +51,11 @@ class XMLParser { public: XMLParser() { debug("xml::XMLParser"); - xmlMemSetup(gc_free, gc_malloc, gc_realloc, gc_strdup); + xmlMemSetup(gc_pool_free, gc_pool_malloc, gc_pool_realloc, gc_pool_strdup); xmlInitParser(); } ~XMLParser() { - debug("xml::~XMLParser"); } } xmlParser; @@ -80,7 +79,6 @@ public: } ~XMLReader() { - debug("xml::~XMLReader"); if (!owner) return; xmlTextReaderClose(xml); diff --git a/sca-cpp/trunk/modules/java/eval.hpp b/sca-cpp/trunk/modules/java/eval.hpp index a73c84c64c..1e119aac80 100644 --- a/sca-cpp/trunk/modules/java/eval.hpp +++ b/sca-cpp/trunk/modules/java/eval.hpp @@ -153,7 +153,6 @@ public: } ~JavaRuntime() { - debug("java::~javaruntime"); } JavaVM* jvm; diff --git a/sca-cpp/trunk/modules/json/json-test.cpp b/sca-cpp/trunk/modules/json/json-test.cpp index ac68d7573d..61aac4ee02 100644 --- a/sca-cpp/trunk/modules/json/json-test.cpp +++ b/sca-cpp/trunk/modules/json/json-test.cpp @@ -123,7 +123,8 @@ bool testJSON() { istringstream is(str(wos)); const list<string> il = streamList(is); const list<value> r = elementsToValues(content(readJSON(il, cx))); - assert(r == l); + const list<value> l2 = mklist<value>(list<value>() + "fruit" + (list<value>() + string("Apple") + string("Orange"))); + assert(r == l2); } return true; } diff --git a/sca-cpp/trunk/modules/opencl/eval.hpp b/sca-cpp/trunk/modules/opencl/eval.hpp index ef0e028e71..35eb6a3b3b 100644 --- a/sca-cpp/trunk/modules/opencl/eval.hpp +++ b/sca-cpp/trunk/modules/opencl/eval.hpp @@ -222,7 +222,6 @@ public: } ~OpenCLContext() { - debug("opencl::~OpenCLContext"); for (cl_uint i = 0; i < ndevs; i++) { if (cq[i] != 0) clReleaseCommandQueue(cq[i]); diff --git a/sca-cpp/trunk/modules/python/eval.hpp b/sca-cpp/trunk/modules/python/eval.hpp index ed22fb2b87..41f45ac5ff 100644 --- a/sca-cpp/trunk/modules/python/eval.hpp +++ b/sca-cpp/trunk/modules/python/eval.hpp @@ -96,7 +96,6 @@ public: } ~PythonRuntime() { - debug("python::~pythonruntime"); } private: diff --git a/sca-cpp/trunk/modules/server/client-test.hpp b/sca-cpp/trunk/modules/server/client-test.hpp index 2dab7b6dfd..2207127e67 100644 --- a/sca-cpp/trunk/modules/server/client-test.hpp +++ b/sca-cpp/trunk/modules/server/client-test.hpp @@ -85,8 +85,9 @@ const bool testGetPerf() { const bool testEval() { gc_scoped_pool pool; http::CURLSession ch("", "", "", ""); - const value val = content(http::evalExpr(mklist<value>(string("echo"), string("Hello")), testURI, ch)); - assert(val == string("Hello")); + const failable<value> r = http::evalExpr(mklist<value>(string("echo"), string("Hello")), testURI, ch); + assert(hasContent(r)); + assert(content(r) == string("Hello")); return true; } @@ -96,8 +97,9 @@ struct evalLoop { evalLoop(const string& uri, http::CURLSession& ch) : uri(uri), ch(ch) { } const bool operator()() const { - const value val = content(http::evalExpr(mklist<value>(string("echo"), string("Hello")), uri, ch)); - assert(val == string("Hello")); + const failable<value> r = http::evalExpr(mklist<value>(string("echo"), string("Hello")), uri, ch); + assert(hasContent(r)); + assert(content(r) == string("Hello")); return true; } }; @@ -111,8 +113,9 @@ struct blobEvalLoop { blobEvalLoop(const string& uri, http::CURLSession& ch) : uri(uri), ch(ch) { } const bool operator()() const { - const value val = content(http::evalExpr(mklist<value>(string("echo"), blobs), uri, ch)); - assert(val == blobs); + const failable<value> r = content(http::evalExpr(mklist<value>(string("echo"), blobs), uri, ch)); + assert(hasContent(r)); + assert(content(r) == blobs); return true; } }; @@ -227,12 +230,12 @@ const bool checkPost(const list<future<bool> >& r) { struct postThreadLoop { const lambda<bool()> l; + worker& w; const int threads; - const gc_ptr<worker> w; - postThreadLoop(const lambda<bool()>& l, const int threads) : l(l), threads(threads), w(new (gc_new<worker>()) worker(threads)) { + postThreadLoop(const lambda<bool()>& l, worker& w, const int threads) : l(l), w(w), threads(threads) { } const bool operator()() const { - list<future<bool> > r = startPost(*w, threads, l); + list<future<bool> > r = startPost(w, threads, l); checkPost(r); return true; } @@ -242,6 +245,7 @@ const bool testPostThreadPerf() { gc_scoped_pool pool; const int count = 50; const int threads = 10; + worker w(threads); const list<value> i = list<value>() + "content" + (list<value>() + "item" + (list<value>() + "name" + string("Apple")) @@ -252,7 +256,7 @@ const bool testPostThreadPerf() { + i); const lambda<bool()> pl= curry(lambda<bool(const string, const int, const value)>(postThread), testURI, count, val); - const lambda<bool()> ptl = postThreadLoop(pl, threads); + const lambda<bool()> ptl = postThreadLoop(pl, w, threads); double t = time(ptl, 0, 1) / (threads * count); cout << "ATOMPub POST thread test " << t << " ms" << endl; |