mirror of
https://github.com/Z3Prover/z3
synced 2025-08-26 13:06:05 +00:00
fix crash on Mac due to different destruction order of globals
the mutex in memory_manager has to be destroyed after all mem deallocations happen
This commit is contained in:
parent
2bee9a062f
commit
cf3e649462
12 changed files with 80 additions and 120 deletions
|
@ -35,7 +35,7 @@ out_of_memory_error::out_of_memory_error():z3_error(ERR_MEMOUT) {
|
|||
}
|
||||
|
||||
|
||||
static mutex g_memory_mux;
|
||||
static mutex *g_memory_mux;
|
||||
static atomic<bool> g_memory_out_of_memory(false);
|
||||
static bool g_memory_initialized = false;
|
||||
static long long g_memory_alloc_size = 0;
|
||||
|
@ -46,7 +46,6 @@ static long long g_memory_alloc_count = 0;
|
|||
static long long g_memory_max_alloc_count = 0;
|
||||
static bool g_exit_when_out_of_memory = false;
|
||||
static char const * g_out_of_memory_msg = "ERROR: out of memory";
|
||||
static volatile bool g_memory_fully_initialized = false;
|
||||
|
||||
void memory::exit_when_out_of_memory(bool flag, char const * msg) {
|
||||
g_exit_when_out_of_memory = flag;
|
||||
|
@ -87,29 +86,22 @@ mem_usage_report g_info;
|
|||
#endif
|
||||
|
||||
void memory::initialize(size_t max_size) {
|
||||
bool initialize = false;
|
||||
{
|
||||
lock_guard lock(g_memory_mux);
|
||||
// only update the maximum size if max_size != UINT_MAX
|
||||
if (max_size != UINT_MAX)
|
||||
g_memory_max_size = max_size;
|
||||
if (!g_memory_initialized) {
|
||||
g_memory_initialized = true;
|
||||
initialize = true;
|
||||
}
|
||||
}
|
||||
if (initialize) {
|
||||
g_memory_out_of_memory = false;
|
||||
mem_initialize();
|
||||
g_memory_fully_initialized = true;
|
||||
}
|
||||
else {
|
||||
// Delay the current thread until the DLL is fully initialized
|
||||
// Without this, multiple threads can start to call API functions
|
||||
// before memory::initialize(...) finishes.
|
||||
while (!g_memory_fully_initialized)
|
||||
/* wait */ ;
|
||||
}
|
||||
static mutex init_mux;
|
||||
lock_guard lock(init_mux);
|
||||
|
||||
// only update the maximum size if max_size != UINT_MAX
|
||||
if (max_size != UINT_MAX)
|
||||
g_memory_max_size = max_size;
|
||||
|
||||
if (g_memory_initialized)
|
||||
return;
|
||||
|
||||
#ifndef SINGLE_THREAD
|
||||
g_memory_mux = new mutex;
|
||||
#endif
|
||||
g_memory_out_of_memory = false;
|
||||
mem_initialize();
|
||||
g_memory_initialized = true;
|
||||
}
|
||||
|
||||
bool memory::is_out_of_memory() {
|
||||
|
@ -124,7 +116,7 @@ void memory::set_high_watermark(size_t watermark) {
|
|||
bool memory::above_high_watermark() {
|
||||
if (g_memory_watermark == 0)
|
||||
return false;
|
||||
lock_guard lock(g_memory_mux);
|
||||
lock_guard lock(*g_memory_mux);
|
||||
return g_memory_watermark < g_memory_alloc_size;
|
||||
}
|
||||
|
||||
|
@ -145,6 +137,9 @@ void memory::finalize() {
|
|||
if (g_memory_initialized) {
|
||||
g_finalizing = true;
|
||||
mem_finalize();
|
||||
#ifndef SINGLE_THREAD
|
||||
delete g_memory_mux;
|
||||
#endif
|
||||
g_memory_initialized = false;
|
||||
g_finalizing = false;
|
||||
}
|
||||
|
@ -153,7 +148,7 @@ void memory::finalize() {
|
|||
unsigned long long memory::get_allocation_size() {
|
||||
long long r;
|
||||
{
|
||||
lock_guard lock(g_memory_mux);
|
||||
lock_guard lock(*g_memory_mux);
|
||||
r = g_memory_alloc_size;
|
||||
}
|
||||
if (r < 0)
|
||||
|
@ -164,7 +159,7 @@ unsigned long long memory::get_allocation_size() {
|
|||
unsigned long long memory::get_max_used_memory() {
|
||||
unsigned long long r;
|
||||
{
|
||||
lock_guard lock(g_memory_mux);
|
||||
lock_guard lock(*g_memory_mux);
|
||||
r = g_memory_max_used_size;
|
||||
}
|
||||
return r;
|
||||
|
@ -248,7 +243,7 @@ static void synchronize_counters(bool allocating) {
|
|||
bool out_of_mem = false;
|
||||
bool counts_exceeded = false;
|
||||
{
|
||||
lock_guard lock(g_memory_mux);
|
||||
lock_guard lock(*g_memory_mux);
|
||||
g_memory_alloc_size += g_memory_thread_alloc_size;
|
||||
g_memory_alloc_count += g_memory_thread_alloc_count;
|
||||
if (g_memory_alloc_size > g_memory_max_used_size)
|
||||
|
@ -329,7 +324,7 @@ void memory::deallocate(void * p) {
|
|||
size_t sz = *sz_p;
|
||||
void * real_p = reinterpret_cast<void*>(sz_p);
|
||||
{
|
||||
lock_guard lock(g_memory_mux);
|
||||
lock_guard lock(*g_memory_mux);
|
||||
g_memory_alloc_size -= sz;
|
||||
}
|
||||
free(real_p);
|
||||
|
@ -339,7 +334,7 @@ void * memory::allocate(size_t s) {
|
|||
s = s + sizeof(size_t); // we allocate an extra field!
|
||||
bool out_of_mem = false, counts_exceeded = false;
|
||||
{
|
||||
lock_guard lock(g_memory_mux);
|
||||
lock_guard lock(*g_memory_mux);
|
||||
g_memory_alloc_size += s;
|
||||
g_memory_alloc_count += 1;
|
||||
if (g_memory_alloc_size > g_memory_max_used_size)
|
||||
|
@ -369,7 +364,7 @@ void* memory::reallocate(void *p, size_t s) {
|
|||
s = s + sizeof(size_t); // we allocate an extra field!
|
||||
bool out_of_mem = false, counts_exceeded = false;
|
||||
{
|
||||
lock_guard lock(g_memory_mux);
|
||||
lock_guard lock(*g_memory_mux);
|
||||
g_memory_alloc_size += s - sz;
|
||||
g_memory_alloc_count += 1;
|
||||
if (g_memory_alloc_size > g_memory_max_used_size)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue