From f1e3c44d1b0784423a5575445c700ffcf20c2bab Mon Sep 17 00:00:00 2001 From: janwas Date: Sat, 26 May 2007 18:16:13 +0000 Subject: [PATCH] test_lockfree: eliminate GCC warning lockfree: avoid mem leak caused by no longer necessary shutdown hack This was SVN commit r5097. --- source/lib/lockfree.cpp | 61 +++++++------------------------- source/lib/tests/test_lockfree.h | 3 +- 2 files changed, 14 insertions(+), 50 deletions(-) diff --git a/source/lib/lockfree.cpp b/source/lib/lockfree.cpp index 96239769d4..76238acccf 100644 --- a/source/lib/lockfree.cpp +++ b/source/lib/lockfree.cpp @@ -117,7 +117,7 @@ static TLS* tls_list = 0; // mark a participating thread's slot as unused; clear its hazard pointers. -// called during smr_try_shutdown and when a thread exits +// called during smr_shutdown and when a thread exits // (by pthread dtor, which is registered in tls_init). static void tls_retire(void* tls_) { @@ -142,7 +142,7 @@ static void tls_init() } -// free all TLS info. called by smr_try_shutdown. +// free all TLS info. called by smr_shutdown. static void tls_shutdown() { WARN_ERR(pthread_key_delete(tls_key)); @@ -240,7 +240,6 @@ static bool is_node_referenced(Node* node, void** hps, size_t num_hps) static void smr_release_unreferenced_nodes(TLS* tls) { // nothing to do, and taking address of array[-1] isn't portable. - // we're called from smr_try_shutdown, if(tls->num_retired_nodes == 0) return; @@ -320,60 +319,25 @@ static void smr_retire_node(Node* node) } -// -// shutdown -// - // although not strictly necessary (the OS will free resources at exit), -// we want to free all nodes and TLS to avoid spamming leak detectors. -// that can only happen after our users indicate all data structures are -// no longer in use (i.e. active_data_structures == 0). -// -// problem: if the first user of a data structure is finished before -// program termination, we'd shut down and not be able to reinitialize -// (see tls_alloc). therefore, we don't shut down before -// static destructors are called, i.e. end of program is at hand. - -static bool is_static_dtor_time = false; - -// call when a data structure is freed (i.e. no longer in use); -// we shut down if it is time to do so. -static void smr_try_shutdown() +// we free all nodes and TLS to avoid spurious leak reports. +static void smr_shutdown() { - // shouldn't or can't shut down yet. - if(!is_static_dtor_time || active_data_structures != 0) - return; + // there better not be any data structures still in use, else we're + // going to pull the rug out from under them. + debug_assert(active_data_structures == 0); for(TLS* t = tls_list; t; t = t->next) { + // wipe out hazard pointers so that everything can be freed. tls_retire(t); - // wipe out hazard pointers so that everything can be freed. + smr_release_unreferenced_nodes(t); } tls_shutdown(); } -// non-local static object - its destructor being called indicates -// program end is at hand. could use atexit for this, but registering -// that would be a bit more work. -static struct NLSO -{ - NLSO() - { - } - - ~NLSO() - { - is_static_dtor_time = true; - - // trigger shutdown in case all data structures have - // already been freed. - smr_try_shutdown(); - } -} -nlso; - ////////////////////////////////////////////////////////////////////////////// // @@ -452,7 +416,6 @@ void lfl_free(LFList* list) cpu_AtomicAdd(&active_data_structures, -1); debug_assert(active_data_structures >= 0); - smr_try_shutdown(); } @@ -634,8 +597,8 @@ retry: // ////////////////////////////////////////////////////////////////////////////// -// note: implemented via lfl, so we don't need to track -// active_data_structures or call smr_try_shutdown here. +// note: implemented via lfl, so we don't need to update +// active_data_structures. static void validate(LFHash* hash) { @@ -742,5 +705,5 @@ void lockfree_Shutdown() if(!ModuleShouldShutdown(&initState)) return; - tls_shutdown(); + smr_shutdown(); } diff --git a/source/lib/tests/test_lockfree.h b/source/lib/tests/test_lockfree.h index 7611eeb66d..b35b1b4274 100644 --- a/source/lib/tests/test_lockfree.h +++ b/source/lib/tests/test_lockfree.h @@ -229,7 +229,8 @@ public: for(uintptr_t i = 0; i < NUM_THREADS; i++) { ThreadFuncParam* param = new ThreadFuncParam(this, i); - pthread_create(0, 0, thread_func, param); + pthread_t thread; // unused, but GCC raises warning if 0 is passed + pthread_create(&thread, 0, thread_func, param); } // wait until time interval elapsed (if we get that far, all is well).