3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 18:31:49 +00:00

Use glibc's malloc_usable_size when available (#6321)

This commit is contained in:
Nuno Lopes 2022-09-05 21:40:02 +01:00 committed by GitHub
parent 6a61efbf99
commit 9717dadd9f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -13,6 +13,11 @@ Copyright (c) 2015 Microsoft Corporation
#include "util/error_codes.h"
#include "util/debug.h"
#include "util/scoped_timer.h"
#ifdef __GLIBC__
# include <malloc.h>
# define HAS_MALLOC_USABLE_SIZE
#endif
// The following two function are automatically generated by the mk_make.py script.
// The script collects ADD_INITIALIZER and ADD_FINALIZER commands in the .h files.
// For example, rational.h contains
@ -215,7 +220,7 @@ void * memory::allocate(char const* file, int line, char const* obj, size_t s) {
}
#endif
#if !defined(SINGLE_THREAD)
#ifndef SINGLE_THREAD
// ==================================
// ==================================
// THREAD LOCAL VERSION
@ -258,9 +263,14 @@ static void synchronize_counters(bool allocating) {
}
void memory::deallocate(void * p) {
#ifdef HAS_MALLOC_USABLE_SIZE
size_t sz = malloc_usable_size(p);
void * real_p = p;
#else
size_t * sz_p = reinterpret_cast<size_t*>(p) - 1;
size_t sz = *sz_p;
void * real_p = reinterpret_cast<void*>(sz_p);
#endif
g_memory_thread_alloc_size -= sz;
free(real_p);
if (g_memory_thread_alloc_size < -SYNCH_THRESHOLD) {
@ -269,28 +279,41 @@ void memory::deallocate(void * p) {
}
void * memory::allocate(size_t s) {
#ifndef HAS_MALLOC_USABLE_SIZE
s = s + sizeof(size_t); // we allocate an extra field!
void * r = malloc(s);
if (r == nullptr) {
throw_out_of_memory();
return nullptr;
}
*(static_cast<size_t*>(r)) = s;
#endif
g_memory_thread_alloc_size += s;
g_memory_thread_alloc_count += 1;
if (g_memory_thread_alloc_size > SYNCH_THRESHOLD) {
synchronize_counters(true);
}
void * r = malloc(s);
if (r == nullptr) {
throw_out_of_memory();
return nullptr;
}
#ifdef HAS_MALLOC_USABLE_SIZE
g_memory_thread_alloc_size += malloc_usable_size(r) - s;
return r;
#else
*(static_cast<size_t*>(r)) = s;
return static_cast<size_t*>(r) + 1; // we return a pointer to the location after the extra field
#endif
}
void* memory::reallocate(void *p, size_t s) {
#ifdef HAS_MALLOC_USABLE_SIZE
size_t sz = malloc_usable_size(p);
void * real_p = p;
// We may be lucky and malloc gave us enough space
if (sz >= s)
return p;
#else
size_t *sz_p = reinterpret_cast<size_t*>(p)-1;
size_t sz = *sz_p;
void *real_p = reinterpret_cast<void*>(sz_p);
s = s + sizeof(size_t); // we allocate an extra field!
#endif
g_memory_thread_alloc_size += s - sz;
g_memory_thread_alloc_count += 1;
if (g_memory_thread_alloc_size > SYNCH_THRESHOLD) {
@ -302,74 +325,97 @@ void* memory::reallocate(void *p, size_t s) {
throw_out_of_memory();
return nullptr;
}
#ifdef HAS_MALLOC_USABLE_SIZE
g_memory_thread_alloc_size += malloc_usable_size(r) - s;
return r;
#else
*(static_cast<size_t*>(r)) = s;
return static_cast<size_t*>(r) + 1; // we return a pointer to the location after the extra field
#endif
}
#else
// ==================================
// ==================================
// NO THREAD LOCAL VERSION
// SINGLE-THREAD MODE
// ==================================
// ==================================
// allocate & deallocate without using thread local storage
// allocate & deallocate without locking
void memory::deallocate(void * p) {
#ifdef HAS_MALLOC_USABLE_SIZE
size_t sz = malloc_usable_size(p);
void * real_p = p;
#else
size_t * sz_p = reinterpret_cast<size_t*>(p) - 1;
size_t sz = *sz_p;
void * real_p = reinterpret_cast<void*>(sz_p);
{
lock_guard lock(*g_memory_mux);
g_memory_alloc_size -= sz;
}
#endif
g_memory_alloc_size -= sz;
free(real_p);
}
void * memory::allocate(size_t s) {
#ifndef HAS_MALLOC_USABLE_SIZE
s = s + sizeof(size_t); // we allocate an extra field!
{
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)
g_memory_max_used_size = g_memory_alloc_size;
if (g_memory_max_size != 0 && g_memory_alloc_size > g_memory_max_size)
throw_out_of_memory();
if (g_memory_max_alloc_count != 0 && g_memory_alloc_count > g_memory_max_alloc_count)
throw_alloc_counts_exceeded();
}
#endif
g_memory_alloc_size += s;
g_memory_alloc_count += 1;
if (g_memory_alloc_size > g_memory_max_used_size)
g_memory_max_used_size = g_memory_alloc_size;
if (g_memory_max_size != 0 && g_memory_alloc_size > g_memory_max_size)
throw_out_of_memory();
if (g_memory_max_alloc_count != 0 && g_memory_alloc_count > g_memory_max_alloc_count)
throw_alloc_counts_exceeded();
void * r = malloc(s);
if (r == nullptr) {
throw_out_of_memory();
return nullptr;
}
#ifdef HAS_MALLOC_USABLE_SIZE
g_memory_alloc_size += malloc_usable_size(r) - s;
return r;
#else
*(static_cast<size_t*>(r)) = s;
return static_cast<size_t*>(r) + 1; // we return a pointer to the location after the extra field
#endif
}
void* memory::reallocate(void *p, size_t s) {
#ifdef HAS_MALLOC_USABLE_SIZE
size_t sz = malloc_usable_size(p);
void * real_p = p;
// We may be lucky and malloc gave us enough space
if (sz >= s)
return p;
#else
size_t * sz_p = reinterpret_cast<size_t*>(p) - 1;
size_t sz = *sz_p;
void * real_p = reinterpret_cast<void*>(sz_p);
s = s + sizeof(size_t); // we allocate an extra field!
{
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)
g_memory_max_used_size = g_memory_alloc_size;
if (g_memory_max_size != 0 && g_memory_alloc_size > g_memory_max_size)
throw_out_of_memory();
if (g_memory_max_alloc_count != 0 && g_memory_alloc_count > g_memory_max_alloc_count)
throw_alloc_counts_exceeded();
}
#endif
g_memory_alloc_size += s - sz;
g_memory_alloc_count += 1;
if (g_memory_alloc_size > g_memory_max_used_size)
g_memory_max_used_size = g_memory_alloc_size;
if (g_memory_max_size != 0 && g_memory_alloc_size > g_memory_max_size)
throw_out_of_memory();
if (g_memory_max_alloc_count != 0 && g_memory_alloc_count > g_memory_max_alloc_count)
throw_alloc_counts_exceeded();
void *r = realloc(real_p, s);
if (r == nullptr) {
throw_out_of_memory();
return nullptr;
}
#ifdef HAS_MALLOC_USABLE_SIZE
g_memory_alloc_size += malloc_usable_size(r) - s;
return r;
#else
*(static_cast<size_t*>(r)) = s;
return static_cast<size_t*>(r) + 1; // we return a pointer to the location after the extra field
#endif
}
#endif