1
1
forked from 0ad/0ad

test_lockfree: eliminate GCC warning

lockfree: avoid mem leak caused by no longer necessary shutdown hack

This was SVN commit r5097.
This commit is contained in:
janwas 2007-05-26 18:16:13 +00:00
parent 4582c8f276
commit f1e3c44d1b
2 changed files with 14 additions and 50 deletions

View File

@ -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();
}

View File

@ -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).