-Changed memory functions, Memory::alloc_static*, simplified them, made them aligned to 16

-Changed Vector<> template to fit this.
This commit is contained in:
Juan Linietsky 2017-01-06 10:15:44 -03:00
parent 99ceddd11e
commit 53ce643e52
18 changed files with 340 additions and 1125 deletions

View File

@ -30,9 +30,68 @@
#include "error_macros.h"
#include "copymem.h"
#include <stdio.h>
#include <stdlib.h>
MID::MID(MemoryPoolDynamic::ID p_id) {
data = (Data*)memalloc(sizeof(Data));
data->refcount.init();
data->id=p_id;
}
void MID::unref() {
if (!data)
return;
if (data->refcount.unref()) {
if (data->id!=MemoryPoolDynamic::INVALID_ID)
MemoryPoolDynamic::get_singleton()->free(data->id);
memfree(data);
}
data=NULL;
}
Error MID::_resize(size_t p_size) {
if (p_size==0 && (!data || data->id==MemoryPoolDynamic::INVALID_ID))
return OK;
if (p_size && !data) {
// create data because we'll need it
data = (Data*)memalloc(sizeof(Data));
ERR_FAIL_COND_V( !data,ERR_OUT_OF_MEMORY );
data->refcount.init();
data->id=MemoryPoolDynamic::INVALID_ID;
}
if (p_size==0 && data && data->id==MemoryPoolDynamic::INVALID_ID) {
MemoryPoolDynamic::get_singleton()->free(data->id);
data->id=MemoryPoolDynamic::INVALID_ID;
}
if (p_size>0) {
if (data->id==MemoryPoolDynamic::INVALID_ID) {
data->id=MemoryPoolDynamic::get_singleton()->alloc(p_size,"Unnamed MID");
ERR_FAIL_COND_V( data->id==MemoryPoolDynamic::INVALID_ID, ERR_OUT_OF_MEMORY );
} else {
MemoryPoolDynamic::get_singleton()->realloc(data->id,p_size);
ERR_FAIL_COND_V( data->id==MemoryPoolDynamic::INVALID_ID, ERR_OUT_OF_MEMORY );
}
}
return OK;
}
void * operator new(size_t p_size,const char *p_description) {
return Memory::alloc_static( p_size, p_description );
return Memory::alloc_static( p_size, false );
}
void * operator new(size_t p_size,void* (*p_allocfunc)(size_t p_size)) {
@ -42,48 +101,146 @@ void * operator new(size_t p_size,void* (*p_allocfunc)(size_t p_size)) {
#include <stdio.h>
void * Memory::alloc_static(size_t p_bytes,const char *p_alloc_from) {
#ifdef DEBUG_ENABLED
size_t Memory::mem_usage=0;
size_t Memory::max_usage=0;
#endif
ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), NULL );
return MemoryPoolStatic::get_singleton()->alloc(p_bytes,p_alloc_from);
}
void * Memory::realloc_static(void *p_memory,size_t p_bytes) {
size_t Memory::alloc_count=0;
ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), NULL );
return MemoryPoolStatic::get_singleton()->realloc(p_memory,p_bytes);
void * Memory::alloc_static(size_t p_bytes,bool p_pad_align) {
#ifdef DEBUG_ENABLED
bool prepad=true;
#else
bool prepad=p_pad_align;
#endif
void * mem = malloc( p_bytes + (prepad?PAD_ALIGN:0));
alloc_count++;
ERR_FAIL_COND_V(!mem,NULL);
if (prepad) {
uint64_t *s = (uint64_t*)mem;
*s=p_bytes;
uint8_t *s8 = (uint8_t*)mem;
#ifdef DEBUG_ENABLED
mem_usage+=p_bytes;
if (mem_usage>max_usage) {
max_usage=mem_usage;
}
#endif
return s8 + PAD_ALIGN;
} else {
return mem;
}
}
void Memory::free_static(void *p_ptr) {
void * Memory::realloc_static(void *p_memory,size_t p_bytes,bool p_pad_align) {
ERR_FAIL_COND( !MemoryPoolStatic::get_singleton());
MemoryPoolStatic::get_singleton()->free(p_ptr);
if (p_memory==NULL) {
return alloc_static(p_bytes,p_pad_align);
}
uint8_t *mem = (uint8_t*)p_memory;
#ifdef DEBUG_ENABLED
bool prepad=true;
#else
bool prepad=p_pad_align;
#endif
if (prepad) {
mem-=PAD_ALIGN;
uint64_t *s = (uint64_t*)mem;
#ifdef DEBUG_ENABLED
mem_usage-=*s;
mem_usage+=p_bytes;
#endif
if (p_bytes==0) {
free(mem);
return NULL;
} else {
*s=p_bytes;
mem = (uint8_t*)realloc(mem,p_bytes+PAD_ALIGN);
ERR_FAIL_COND_V(!mem,NULL);
s = (uint64_t*)mem;
*s=p_bytes;
return mem+PAD_ALIGN;
}
} else {
mem = (uint8_t*)realloc(mem,p_bytes);
ERR_FAIL_COND_V(mem==NULL && p_bytes>0,NULL);
return mem;
}
}
void Memory::free_static(void *p_ptr,bool p_pad_align) {
size_t Memory::get_static_mem_available() {
ERR_FAIL_COND(p_ptr==NULL);
ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), 0);
return MemoryPoolStatic::get_singleton()->get_available_mem();
uint8_t *mem = (uint8_t*)p_ptr;
#ifdef DEBUG_ENABLED
bool prepad=true;
#else
bool prepad=p_pad_align;
#endif
alloc_count--;
if (prepad) {
mem-=PAD_ALIGN;
uint64_t *s = (uint64_t*)mem;
#ifdef DEBUG_ENABLED
mem_usage-=*s;
#endif
free(mem);
} else {
free(mem);
}
}
size_t Memory::get_static_mem_max_usage() {
size_t Memory::get_mem_available() {
ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), 0);
return MemoryPoolStatic::get_singleton()->get_max_usage();
}
size_t Memory::get_static_mem_usage() {
ERR_FAIL_COND_V( !MemoryPoolStatic::get_singleton(), 0);
return MemoryPoolStatic::get_singleton()->get_total_usage();
return 0xFFFFFFFFFFFFF;
}
void Memory::dump_static_mem_to_file(const char* p_file) {
MemoryPoolStatic::get_singleton()->dump_mem_to_file(p_file);
size_t Memory::get_mem_usage(){
#ifdef DEBUG_ENABLED
return mem_usage;
#else
return 0;
#endif
}
size_t Memory::get_mem_max_usage(){
#ifdef DEBUG_ENABLED
return max_usage;
#else
return 0;
#endif
}
MID Memory::alloc_dynamic(size_t p_bytes, const char *p_descr) {

View File

@ -32,13 +32,18 @@
#include <stddef.h>
#include "safe_refcount.h"
#include "os/memory_pool_dynamic.h"
#include "os/memory_pool_static.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
#ifndef PAD_ALIGN
#define PAD_ALIGN 16 //must always be greater than this at much
#endif
class MID {
struct Data {
@ -49,19 +54,7 @@ class MID {
mutable Data *data;
void unref() {
if (!data)
return;
if (data->refcount.unref()) {
if (data->id!=MemoryPoolDynamic::INVALID_ID)
MemoryPoolDynamic::get_singleton()->free(data->id);
MemoryPoolStatic::get_singleton()->free(data);
}
data=NULL;
}
void ref(Data *p_data) {
@ -95,49 +88,13 @@ friend class MID_Lock;
return NULL;
}
Error _resize(size_t p_size) {
if (p_size==0 && (!data || data->id==MemoryPoolDynamic::INVALID_ID))
return OK;
if (p_size && !data) {
// create data because we'll need it
data = (Data*)MemoryPoolStatic::get_singleton()->alloc(sizeof(Data),"MID::Data");
ERR_FAIL_COND_V( !data,ERR_OUT_OF_MEMORY );
data->refcount.init();
data->id=MemoryPoolDynamic::INVALID_ID;
}
void unref();
Error _resize(size_t p_size);
if (p_size==0 && data && data->id==MemoryPoolDynamic::INVALID_ID) {
MemoryPoolDynamic::get_singleton()->free(data->id);
data->id=MemoryPoolDynamic::INVALID_ID;
}
if (p_size>0) {
if (data->id==MemoryPoolDynamic::INVALID_ID) {
data->id=MemoryPoolDynamic::get_singleton()->alloc(p_size,"Unnamed MID");
ERR_FAIL_COND_V( data->id==MemoryPoolDynamic::INVALID_ID, ERR_OUT_OF_MEMORY );
} else {
MemoryPoolDynamic::get_singleton()->realloc(data->id,p_size);
ERR_FAIL_COND_V( data->id==MemoryPoolDynamic::INVALID_ID, ERR_OUT_OF_MEMORY );
}
}
return OK;
}
friend class Memory;
MID(MemoryPoolDynamic::ID p_id) {
data = (Data*)MemoryPoolStatic::get_singleton()->alloc(sizeof(Data),"MID::Data");
data->refcount.init();
data->id=p_id;
}
MID(MemoryPoolDynamic::ID p_id);
public:
bool is_valid() const { return data; }
@ -173,15 +130,23 @@ public:
class Memory{
Memory();
#ifdef DEBUG_ENABLED
static size_t mem_usage;
static size_t max_usage;
#endif
static size_t alloc_count;
public:
static void * alloc_static(size_t p_bytes,const char *p_descr="");
static void * realloc_static(void *p_memory,size_t p_bytes);
static void free_static(void *p_ptr);
static size_t get_static_mem_available();
static size_t get_static_mem_usage();
static size_t get_static_mem_max_usage();
static void dump_static_mem_to_file(const char* p_file);
static void * alloc_static(size_t p_bytes,bool p_pad_align=false);
static void * realloc_static(void *p_memory,size_t p_bytes,bool p_pad_align=false);
static void free_static(void *p_ptr,bool p_pad_align=false);
static size_t get_mem_available();
static size_t get_mem_usage();
static size_t get_mem_max_usage();
static MID alloc_dynamic(size_t p_bytes, const char *p_descr="");
static Error realloc_dynamic(MID p_mid,size_t p_bytes);
@ -191,15 +156,10 @@ public:
};
template<class T>
struct MemAalign {
static _FORCE_INLINE_ int get_align() { return DEFAULT_ALIGNMENT; }
};
class DefaultAllocator {
public:
_FORCE_INLINE_ static void *alloc(size_t p_memory) { return Memory::alloc_static(p_memory, ""); }
_FORCE_INLINE_ static void free(void *p_ptr) { return Memory::free_static(p_ptr); }
_FORCE_INLINE_ static void *alloc(size_t p_memory) { return Memory::alloc_static(p_memory, false); }
_FORCE_INLINE_ static void free(void *p_ptr) { return Memory::free_static(p_ptr,false); }
};
@ -209,19 +169,10 @@ void * operator new(size_t p_size,void* (*p_allocfunc)(size_t p_size)); ///< ope
void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_description); ///< operator new that takes a description and uses a pointer to the preallocated memory
#ifdef DEBUG_MEMORY_ENABLED
#define memalloc(m_size) Memory::alloc_static(m_size, __FILE__ ":" __STR(__LINE__) ", memalloc.")
#define memrealloc(m_mem,m_size) Memory::realloc_static(m_mem,m_size)
#define memfree(m_size) Memory::free_static(m_size)
#else
#define memalloc(m_size) Memory::alloc_static(m_size)
#define memrealloc(m_mem,m_size) Memory::realloc_static(m_mem,m_size)
#define memfree(m_size) Memory::free_static(m_size)
#endif
#ifdef DEBUG_MEMORY_ENABLED
#define dynalloc(m_size) Memory::alloc_dynamic(m_size, __FILE__ ":" __STR(__LINE__) ", type: DYNAMIC")
@ -245,16 +196,8 @@ _ALWAYS_INLINE_ T *_post_initialize(T *p_obj) {
return p_obj;
}
#ifdef DEBUG_MEMORY_ENABLED
#define memnew(m_class) _post_initialize(new(__FILE__ ":" __STR(__LINE__) ", memnew type: " __STR(m_class)) m_class)
#else
#define memnew(m_class) _post_initialize(new("") m_class)
#endif
_ALWAYS_INLINE_ void * operator new(size_t p_size,void *p_pointer,size_t check, const char *p_description) {
// void *failptr=0;
// ERR_FAIL_COND_V( check < p_size , failptr); /** bug, or strange compiler, most likely */
@ -275,7 +218,7 @@ void memdelete(T *p_class) {
if (!predelete_handler(p_class))
return; // doesn't want to be deleted
p_class->~T();
Memory::free_static(p_class);
Memory::free_static(p_class,false);
}
template<class T,class A>
@ -288,15 +231,9 @@ void memdelete_allocator(T *p_class) {
}
#define memdelete_notnull(m_v) { if (m_v) memdelete(m_v); }
#ifdef DEBUG_MEMORY_ENABLED
#define memnew_arr( m_class, m_count ) memnew_arr_template<m_class>(m_count,__FILE__ ":" __STR(__LINE__) ", memnew_arr type: " _STR(m_class))
#else
#define memnew_arr( m_class, m_count ) memnew_arr_template<m_class>(m_count)
#endif
template<typename T>
T* memnew_arr_template(size_t p_elements,const char *p_descr="") {
@ -307,11 +244,11 @@ T* memnew_arr_template(size_t p_elements,const char *p_descr="") {
same strategy used by std::vector, and the DVector class, so it should be safe.*/
size_t len = sizeof(T) * p_elements;
unsigned int *mem = (unsigned int*)Memory::alloc_static( len + MAX(sizeof(size_t), DEFAULT_ALIGNMENT), p_descr );
uint64_t *mem = (uint64_t*)Memory::alloc_static( len , true );
T *failptr=0; //get rid of a warning
ERR_FAIL_COND_V( !mem, failptr );
*mem=p_elements;
mem = (unsigned int *)( ((uint8_t*)mem) + MAX(sizeof(size_t), DEFAULT_ALIGNMENT));
*(mem-1)=p_elements;
T* elems = (T*)mem;
/* call operator new */
@ -330,20 +267,22 @@ T* memnew_arr_template(size_t p_elements,const char *p_descr="") {
template<typename T>
size_t memarr_len(const T *p_class) {
uint8_t* ptr = ((uint8_t*)p_class) - MAX(sizeof(size_t), DEFAULT_ALIGNMENT);
return *(size_t*)ptr;
uint64_t* ptr = (uint64_t*)p_class;
return *(ptr-1);
}
template<typename T>
void memdelete_arr(T *p_class) {
unsigned int * elems = (unsigned int*)(((uint8_t*)p_class) - MAX(sizeof(size_t), DEFAULT_ALIGNMENT));
uint64_t* ptr = (uint64_t*)p_class;
for (unsigned int i=0;i<*elems;i++) {
uint64_t elem_count = *(ptr-1);
for (uint64_t i=0;i<elem_count;i++) {
p_class[i].~T();
};
Memory::free_static(elems);
Memory::free_static(ptr,true);
}

View File

@ -221,7 +221,7 @@ Error MemoryPoolDynamicStatic::unlock(ID p_id) {
size_t MemoryPoolDynamicStatic::get_available_mem() const {
return Memory::get_static_mem_available();
return Memory::get_mem_available();
}
size_t MemoryPoolDynamicStatic::get_total_usage() const {

View File

@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */

View File

@ -1,49 +0,0 @@
/*************************************************************************/
/* memory_pool_static.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "memory_pool_static.h"
MemoryPoolStatic *MemoryPoolStatic::singleton=0;
MemoryPoolStatic *MemoryPoolStatic::get_singleton() {
return singleton;
}
MemoryPoolStatic::MemoryPoolStatic() {
singleton=this;
}
MemoryPoolStatic::~MemoryPoolStatic() {
singleton=NULL;
}

View File

@ -1,69 +0,0 @@
/*************************************************************************/
/* memory_pool_static.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef MEMORY_POOL_STATIC_H
#define MEMORY_POOL_STATIC_H
#include <stddef.h>
#include "core/typedefs.h"
/**
@author Juan Linietsky <red@lunatea>
*/
class MemoryPoolStatic {
private:
static MemoryPoolStatic *singleton;
public:
static MemoryPoolStatic *get_singleton();
virtual void* alloc(size_t p_bytes,const char *p_description)=0; ///< Pointer in p_description shold be to a const char const like "hello"
virtual void* realloc(void * p_memory,size_t p_bytes)=0; ///< Pointer in p_description shold be to a const char const like "hello"
virtual void free(void *p_ptr)=0; ///< Pointer in p_description shold be to a const char const
virtual size_t get_available_mem() const=0;
virtual size_t get_total_usage()=0;
virtual size_t get_max_usage()=0;
/* Most likely available only if memory debugger was compiled in */
virtual int get_alloc_count()=0;
virtual void * get_alloc_ptr(int p_alloc_idx)=0;
virtual const char* get_alloc_description(int p_alloc_idx)=0;
virtual size_t get_alloc_size(int p_alloc_idx)=0;
virtual void dump_mem_to_file(const char* p_file)=0;
MemoryPoolStatic();
virtual ~MemoryPoolStatic();
};
#endif

View File

@ -187,7 +187,7 @@ const char *OS::get_last_error() const {
void OS::dump_memory_to_file(const char* p_file) {
Memory::dump_static_mem_to_file(p_file);
// Memory::dump_static_mem_to_file(p_file);
}
static FileAccess *_OSPRF=NULL;
@ -367,7 +367,7 @@ Error OS::dialog_input_text(String p_title, String p_description, String p_parti
int OS::get_static_memory_usage() const {
return Memory::get_static_mem_usage();
return Memory::get_mem_usage();
}
int OS::get_dynamic_memory_usage() const{
@ -376,7 +376,7 @@ int OS::get_dynamic_memory_usage() const{
int OS::get_static_memory_peak_usage() const {
return Memory::get_static_mem_max_usage();
return Memory::get_mem_max_usage();
}
Error OS::set_cwd(const String& p_cwd) {
@ -392,7 +392,7 @@ bool OS::has_touchscreen_ui_hint() const {
int OS::get_free_static_memory() const {
return Memory::get_static_mem_available();
return Memory::get_mem_available();
}
void OS::yield() {

View File

@ -604,7 +604,7 @@ void PoolAllocator::create_pool(void * p_mem,int p_size,int p_max_entries) {
PoolAllocator::PoolAllocator(int p_size,bool p_needs_locking,int p_max_entries) {
mem_ptr=Memory::alloc_static( p_size,"PoolAllocator()");
mem_ptr=memalloc( p_size);
ERR_FAIL_COND(!mem_ptr);
align=1;
create_pool(mem_ptr,p_size,p_max_entries);
@ -648,7 +648,7 @@ PoolAllocator::PoolAllocator(int p_align,int p_size,bool p_needs_locking,int p_m
PoolAllocator::~PoolAllocator() {
if (mem_ptr)
Memory::free_static( mem_ptr );
memfree( mem_ptr );
memdelete_arr( entry_array );
memdelete_arr( entry_indices );

View File

@ -29,27 +29,76 @@
#include "safe_refcount.h"
// Atomic functions, these are used for multithread safe reference counters!
#ifdef NO_THREADS
uint32_t atomic_conditional_increment( register uint32_t * pw ) {
if (*pw==0)
return 0;
(*pw)++;
return *pw;
}
uint32_t atomic_decrement( register uint32_t * pw ) {
(*pw)--;
return *pw;
}
#else
#ifdef _MSC_VER
// don't pollute my namespace!
#include <windows.h>
long atomic_conditional_increment( register long * pw ) {
uint32_t atomic_conditional_increment( register uint32_t * pw ) {
/* try to increment until it actually works */
// taken from boost
while (true) {
long tmp = static_cast< long const volatile& >( *pw );
uint32_t tmp = static_cast< uint32_t const volatile& >( *pw );
if( tmp == 0 )
return 0; // if zero, can't add to it anymore
if( InterlockedCompareExchange( pw, tmp + 1, tmp ) == tmp )
return 0; // if zero, can't add to it anymore
if( InterlockedCompareExchange( (LONG volatile*)pw, tmp + 1, tmp ) == tmp )
return tmp+1;
}
}
uint32_t atomic_decrement( register uint32_t * pw ) {
return InterlockedDecrement( (LONG volatile*)pw );
}
#elif defined(__GNUC__)
uint32_t atomic_conditional_increment( register uint32_t * pw ) {
while (true) {
uint32_t tmp = static_cast< uint32_t const volatile& >( *pw );
if( tmp == 0 )
return 0; // if zero, can't add to it anymore
if( __sync_val_compare_and_swap( pw, tmp, tmp + 1 ) == tmp )
return tmp+1;
}
}
uint32_t atomic_decrement( register uint32_t * pw ) {
return __sync_sub_and_fetch(pw,1);
}
long atomic_decrement( register long * pw ) {
return InterlockedDecrement( pw );
}
#else
//no threads supported?
#error Must provide atomic functions for this platform or compiler!
#endif
#endif

View File

@ -33,309 +33,17 @@
/* x86/x86_64 GCC */
#include "platform_config.h"
#include "typedefs.h"
#ifdef NO_THREADS
struct SafeRefCount {
int count;
public:
// destroy() is called when weak_count_ drops to zero.
bool ref() { //true on success
if (count==0)
return false;
count++;
return true;
}
int refval() { //true on success
if (count==0)
return 0;
count++;
return count;
}
bool unref() { // true if must be disposed of
if (count>0)
count--;
return count==0;
}
long get() const { // nothrow
return static_cast<int const volatile &>( count );
}
void init(int p_value=1) {
count=p_value;
};
};
#else
#if defined( PLATFORM_REFCOUNT )
#include "platform_refcount.h"
#elif defined( __GNUC__ ) && ( defined( __i386__ ) || defined( __x86_64__ ) )
#define REFCOUNT_T volatile int
#define REFCOUNT_GET_T int const volatile&
static inline int atomic_conditional_increment( volatile int * pw ) {
// int rv = *pw;
// if( rv != 0 ) ++*pw;
// return rv;
int rv, tmp;
__asm__
(
"movl %0, %%eax\n\t"
"0:\n\t"
"test %%eax, %%eax\n\t"
"je 1f\n\t"
"movl %%eax, %2\n\t"
"incl %2\n\t"
"lock\n\t"
"cmpxchgl %2, %0\n\t"
"jne 0b\n\t"
"1:":
"=m"( *pw ), "=&a"( rv ), "=&r"( tmp ): // outputs (%0, %1, %2)
"m"( *pw ): // input (%3)
"cc" // clobbers
);
return rv;
}
static inline int atomic_decrement( volatile int *pw) {
// return --(*pw);
unsigned char rv;
__asm__
(
"lock\n\t"
"decl %0\n\t"
"setne %1":
"=m" (*pw), "=qm" (rv):
"m" (*pw):
"memory"
);
return static_cast<int>(rv);
}
/* PowerPC32/64 GCC */
#elif ( defined( __GNUC__ ) ) && ( defined( __powerpc__ ) || defined( __ppc__ ) )
#define REFCOUNT_T int
#define REFCOUNT_GET_T int const volatile&
inline int atomic_conditional_increment( int * pw )
{
// if( *pw != 0 ) ++*pw;
// return *pw;
int rv;
__asm__
(
"0:\n\t"
"lwarx %1, 0, %2\n\t"
"cmpwi %1, 0\n\t"
"beq 1f\n\t"
"addi %1, %1, 1\n\t"
"1:\n\t"
"stwcx. %1, 0, %2\n\t"
"bne- 0b":
"=m"( *pw ), "=&b"( rv ):
"r"( pw ), "m"( *pw ):
"cc"
);
return rv;
}
inline int atomic_decrement( int * pw )
{
// return --*pw;
int rv;
__asm__ __volatile__
(
"sync\n\t"
"0:\n\t"
"lwarx %1, 0, %2\n\t"
"addi %1, %1, -1\n\t"
"stwcx. %1, 0, %2\n\t"
"bne- 0b\n\t"
"isync":
"=m"( *pw ), "=&b"( rv ):
"r"( pw ), "m"( *pw ):
"memory", "cc"
);
return rv;
}
/* CW ARM */
#elif defined( __GNUC__ ) && ( defined( __arm__ ) )
#define REFCOUNT_T int
#define REFCOUNT_GET_T int const volatile&
inline int atomic_conditional_increment(volatile int* v)
{
int t;
int tmp;
__asm__ __volatile__(
"1: ldrex %0, [%2] \n"
" cmp %0, #0 \n"
" beq 2f \n"
" add %0, %0, #1 \n"
"2: \n"
" strex %1, %0, [%2] \n"
" cmp %1, #0 \n"
" bne 1b \n"
: "=&r" (t), "=&r" (tmp)
: "r" (v)
: "cc", "memory");
return t;
}
inline int atomic_decrement(volatile int* v)
{
int t;
int tmp;
__asm__ __volatile__(
"1: ldrex %0, [%2] \n"
" add %0, %0, #-1 \n"
" strex %1, %0, [%2] \n"
" cmp %1, #0 \n"
" bne 1b \n"
: "=&r" (t), "=&r" (tmp)
: "r" (v)
: "cc", "memory");
return t;
}
/* CW PPC */
#elif ( defined( __MWERKS__ ) ) && defined( __POWERPC__ )
inline long atomic_conditional_increment( register long * pw )
{
register int a;
asm
{
loop:
lwarx a, 0, pw
cmpwi a, 0
beq store
addi a, a, 1
store:
stwcx. a, 0, pw
bne- loop
}
return a;
}
inline long atomic_decrement( register long * pw )
{
register int a;
asm {
sync
loop:
lwarx a, 0, pw
addi a, a, -1
stwcx. a, 0, pw
bne- loop
isync
}
return a;
}
/* Any Windows (MSVC) */
#elif defined( _MSC_VER )
// made functions to not pollute namespace..
#define REFCOUNT_T long
#define REFCOUNT_GET_T long const volatile&
long atomic_conditional_increment( register long * pw );
long atomic_decrement( register long * pw );
#if 0
#elif defined( __GNUC__ ) && defined( ARMV6_ENABLED)
#endif
#else
#error This platform cannot use safe refcount, compile with NO_THREADS or implement it.
#endif
uint32_t atomic_conditional_increment( register uint32_t * counter );
uint32_t atomic_decrement( register uint32_t * pw );
struct SafeRefCount {
REFCOUNT_T count;
uint32_t count;
public:
@ -346,7 +54,7 @@ public:
return atomic_conditional_increment( &count ) != 0;
}
int refval() { //true on success
uint32_t refval() { //true on success
return atomic_conditional_increment( &count );
}
@ -360,20 +68,18 @@ public:
return false;
}
long get() const { // nothrow
uint32_t get() const { // nothrow
return static_cast<REFCOUNT_GET_T>( count );
return count;
}
void init(int p_value=1) {
void init(uint32_t p_value=1) {
count=p_value;
};
}
};
#endif // no thread safe
#endif

View File

@ -77,10 +77,6 @@
#endif
#ifndef DEFAULT_ALIGNMENT
#define DEFAULT_ALIGNMENT 1
#endif
//custom, gcc-safe offsetof, because gcc complains a lot.
template<class T>

View File

@ -46,19 +46,20 @@ class Vector {
// internal helpers
_FORCE_INLINE_ SafeRefCount* _get_refcount() const {
_FORCE_INLINE_ uint32_t* _get_refcount() const {
if (!_ptr)
return NULL;
return reinterpret_cast<SafeRefCount*>((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount));
return reinterpret_cast<uint32_t*>(_ptr)-2;
}
_FORCE_INLINE_ int* _get_size() const {
_FORCE_INLINE_ uint32_t* _get_size() const {
if (!_ptr)
return NULL;
return reinterpret_cast<int*>((uint8_t*)_ptr-sizeof(int));
return NULL;
return reinterpret_cast<uint32_t*>(_ptr)-1;
}
_FORCE_INLINE_ T* _get_data() const {
@ -71,7 +72,7 @@ class Vector {
_FORCE_INLINE_ size_t _get_alloc_size(size_t p_elements) const {
//return nearest_power_of_2_templated(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int));
return nearest_power_of_2(p_elements*sizeof(T)+sizeof(SafeRefCount)+sizeof(int));
return nearest_power_of_2(p_elements*sizeof(T));
}
_FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const {
@ -79,8 +80,8 @@ class Vector {
size_t o;
size_t p;
if (_mul_overflow(p_elements, sizeof(T), &o)) return false;
if (_add_overflow(o, sizeof(SafeRefCount)+sizeof(int), &p)) return false;
*out = nearest_power_of_2(p);
*out = nearest_power_of_2(o);
if (_add_overflow(o, 32, &p)) return false; //no longer allocated here
return true;
#else
// Speed is more important than correctness here, do the operations unchecked
@ -104,7 +105,7 @@ public:
_FORCE_INLINE_ void clear() { resize(0); }
_FORCE_INLINE_ int size() const {
int* size = _get_size();
uint32_t* size = (uint32_t*)_get_size();
if (size)
return *size;
else
@ -190,22 +191,22 @@ void Vector<T>::_unref(void *p_data) {
if (!p_data)
return;
SafeRefCount *src = reinterpret_cast<SafeRefCount*>((uint8_t*)p_data-sizeof(int)-sizeof(SafeRefCount));
uint32_t *refc = _get_refcount();
if (!src->unref())
if (atomic_decrement(refc)>0)
return; // still in use
// clean up
int *count = (int*)(src+1);
uint32_t *count = _get_size();
T *data = (T*)(count+1);
for (int i=0;i<*count;i++) {
for (uint32_t i=0;i<*count;i++) {
// call destructors
data[i].~T();
}
// free mem
memfree((uint8_t*)p_data-sizeof(int)-sizeof(SafeRefCount));
Memory::free_static((uint8_t*)p_data,true);
}
@ -215,18 +216,22 @@ void Vector<T>::_copy_on_write() {
if (!_ptr)
return;
if (_get_refcount()->get() > 1 ) {
/* in use by more than me */
void* mem_new = memalloc(_get_alloc_size(*_get_size()));
SafeRefCount *src_new=(SafeRefCount *)mem_new;
src_new->init();
int * _size = (int*)(src_new+1);
*_size=*_get_size();
uint32_t *refc = _get_refcount();
T*_data=(T*)(_size+1);
if (*refc > 1) {
/* in use by more than me */
uint32_t current_size = *_get_size();
uint32_t* mem_new = (uint32_t*)Memory::alloc_static(_get_alloc_size(current_size),true);
*(mem_new-2)=1; //refcount
*(mem_new-1)=current_size; //size
T*_data=(T*)(mem_new);
// initialize new elements
for (int i=0;i<*_size;i++) {
for (uint32_t i=0;i<current_size;i++) {
memnew_placement(&_data[i], T( _get_data()[i] ) );
}
@ -280,16 +285,17 @@ Error Vector<T>::resize(int p_size) {
if (size()==0) {
// alloc from scratch
void* ptr=memalloc(alloc_size);
uint32_t *ptr=(uint32_t*)Memory::alloc_static(alloc_size,true);
ERR_FAIL_COND_V( !ptr ,ERR_OUT_OF_MEMORY);
_ptr=(T*)((uint8_t*)ptr+sizeof(int)+sizeof(SafeRefCount));
_get_refcount()->init(); // init refcount
*_get_size()=0; // init size (currently, none)
*(ptr-1)=0; //size, currently none
*(ptr-2)=1; //refcount
_ptr=(T*)ptr;
} else {
void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount), alloc_size);
void *_ptrnew = (T*)Memory::realloc_static(_ptr, alloc_size,true);
ERR_FAIL_COND_V( !_ptrnew ,ERR_OUT_OF_MEMORY);
_ptr=(T*)((uint8_t*)_ptrnew+sizeof(int)+sizeof(SafeRefCount));
_ptr=(T*)(_ptrnew);
}
// construct the newly created elements
@ -305,16 +311,16 @@ Error Vector<T>::resize(int p_size) {
} else if (p_size<size()) {
// deinitialize no longer needed elements
for (int i=p_size;i<*_get_size();i++) {
for (uint32_t i=p_size;i<*_get_size();i++) {
T* t = &_get_data()[i];
t->~T();
}
void *_ptrnew = (T*)memrealloc((uint8_t*)_ptr-sizeof(int)-sizeof(SafeRefCount), alloc_size);
void *_ptrnew = (T*)Memory::realloc_static(_ptr, alloc_size,true);
ERR_FAIL_COND_V( !_ptrnew ,ERR_OUT_OF_MEMORY);
_ptr=(T*)((uint8_t*)_ptrnew+sizeof(int)+sizeof(SafeRefCount));
_ptr=(T*)(_ptrnew);
*_get_size()=p_size;
@ -382,8 +388,9 @@ void Vector<T>::_copy_from(const Vector& p_from) {
if (!p_from._ptr)
return; //nothing to do
if (p_from._get_refcount()->ref()) // could reference
if (atomic_conditional_increment(p_from._get_refcount())>0) { // could reference
_ptr=p_from._ptr;
}
}

View File

@ -370,7 +370,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
}
char *ilogmem = (char*)Memory::alloc_static(iloglen+1);
char *ilogmem = (char*)memalloc(iloglen+1);
ilogmem[iloglen]=0;
glGetShaderInfoLog(v.vert_id, iloglen, &iloglen, ilogmem);
@ -378,7 +378,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
err_string+=ilogmem;
_display_error_with_code(err_string,strings);
Memory::free_static(ilogmem);
memfree(ilogmem);
glDeleteShader(v.vert_id);
glDeleteProgram( v.id );
v.id=0;
@ -473,7 +473,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
iloglen = 4096; //buggy driver (Adreno 220+....)
}
char *ilogmem = (char*)Memory::alloc_static(iloglen+1);
char *ilogmem = (char*)memalloc(iloglen+1);
ilogmem[iloglen]=0;
glGetShaderInfoLog(v.frag_id, iloglen, &iloglen, ilogmem);
@ -482,7 +482,7 @@ ShaderGLES3::Version* ShaderGLES3::get_current_version() {
err_string+=ilogmem;
_display_error_with_code(err_string,strings);
ERR_PRINT(err_string.ascii().get_data());
Memory::free_static(ilogmem);
memfree(ilogmem);
glDeleteShader(v.frag_id);
glDeleteShader(v.vert_id);
glDeleteProgram( v.id );

View File

@ -1,434 +1,2 @@
/*************************************************************************/
/* memory_pool_static_malloc.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "memory_pool_static_malloc.h"
#include "error_macros.h"
#include "os/memory.h"
#include <stdlib.h>
#include <stdio.h>
#include "os/copymem.h"
#include "os/os.h"
/**
* NOTE NOTE NOTE NOTE
* in debug mode, this prepends the memory size to the allocated block
* so BE CAREFUL!
*/
void* MemoryPoolStaticMalloc::alloc(size_t p_bytes,const char *p_description) {
#if DEFAULT_ALIGNMENT == 1
return _alloc(p_bytes, p_description);
#else
size_t total;
#if defined(_add_overflow)
if (_add_overflow(p_bytes, DEFAULT_ALIGNMENT, &total)) return NULL;
#else
total = p_bytes + DEFAULT_ALIGNMENT;
#endif
uint8_t* ptr = (uint8_t*)_alloc(total, p_description);
ERR_FAIL_COND_V( !ptr, ptr );
int ofs = (DEFAULT_ALIGNMENT - ((uintptr_t)ptr & (DEFAULT_ALIGNMENT - 1)));
ptr[ofs-1] = ofs;
return (void*)(ptr + ofs);
#endif
};
void* MemoryPoolStaticMalloc::_alloc(size_t p_bytes,const char *p_description) {
ERR_FAIL_COND_V(p_bytes==0,0);
MutexLock lock(mutex);
#ifdef DEBUG_MEMORY_ENABLED
size_t total;
#if defined(_add_overflow)
if (_add_overflow(p_bytes, sizeof(RingPtr), &total)) return NULL;
#else
total = p_bytes + sizeof(RingPtr);
#endif
void *mem=malloc(total); /// add for size and ringlist
if (!mem) {
printf("**ERROR: out of memory while allocating %lu bytes by %s?\n", (unsigned long) p_bytes, p_description);
printf("**ERROR: memory usage is %lu\n", (unsigned long) get_total_usage());
};
ERR_FAIL_COND_V(!mem,0); //out of memory, or unreasonable request
/* setup the ringlist element */
RingPtr *ringptr = (RingPtr*)mem;
/* setup the ringlist element data (description and size ) */
ringptr->size = p_bytes;
ringptr->descr=p_description;
if (ringlist) { /* existing ringlist */
/* assign next */
ringptr->next = ringlist->next;
ringlist->next = ringptr;
/* assign prev */
ringptr->prev = ringlist;
ringptr->next->prev = ringptr;
} else { /* non existing ringlist */
ringptr->next=ringptr;
ringptr->prev=ringptr;
ringlist=ringptr;
}
total_mem+=p_bytes;
/* update statistics */
if (total_mem > max_mem )
max_mem = total_mem;
total_pointers++;
if (total_pointers > max_pointers)
max_pointers=total_pointers;
return ringptr + 1; /* return memory after ringptr */
#else
void *mem=malloc(p_bytes);
ERR_FAIL_COND_V(!mem,0); //out of memory, or unreasonable request
return mem;
#endif
}
void* MemoryPoolStaticMalloc::realloc(void *p_memory,size_t p_bytes) {
#if DEFAULT_ALIGNMENT == 1
return _realloc(p_memory,p_bytes);
#else
if (!p_memory)
return alloc(p_bytes);
size_t total;
#if defined(_add_overflow)
if (_add_overflow(p_bytes, DEFAULT_ALIGNMENT, &total)) return NULL;
#else
total = p_bytes + DEFAULT_ALIGNMENT;
#endif
uint8_t* mem = (uint8_t*)p_memory;
int ofs = *(mem-1);
mem = mem - ofs;
uint8_t* ptr = (uint8_t*)_realloc(mem, total);
ERR_FAIL_COND_V(ptr == NULL, NULL);
int new_ofs = (DEFAULT_ALIGNMENT - ((uintptr_t)ptr & (DEFAULT_ALIGNMENT - 1)));
if (new_ofs != ofs) {
//printf("realloc moving %i bytes\n", p_bytes);
movemem((ptr + new_ofs), (ptr + ofs), p_bytes);
ptr[new_ofs-1] = new_ofs;
};
return ptr + new_ofs;
#endif
};
void* MemoryPoolStaticMalloc::_realloc(void *p_memory,size_t p_bytes) {
if (p_memory==NULL) {
return alloc( p_bytes );
}
if (p_bytes==0) {
this->free(p_memory);
ERR_FAIL_COND_V( p_bytes < 0 , NULL );
return NULL;
}
MutexLock lock(mutex);
#ifdef DEBUG_MEMORY_ENABLED
RingPtr *ringptr = (RingPtr*)p_memory;
ringptr--; /* go back an element to find the tingptr */
bool single_element = (ringptr->next == ringptr) && (ringptr->prev == ringptr);
bool is_list = ( ringlist == ringptr );
RingPtr *new_ringptr=(RingPtr*)::realloc(ringptr, p_bytes+sizeof(RingPtr));
ERR_FAIL_COND_V( new_ringptr == 0, NULL ); /// reallocation failed
/* actualize mem used */
total_mem -= new_ringptr->size;
new_ringptr->size = p_bytes;
total_mem += new_ringptr->size;
if (total_mem > max_mem ) //update statistics
max_mem = total_mem;
if (new_ringptr == ringptr )
return ringptr + 1; // block didn't move, don't do anything
if (single_element) {
new_ringptr->next=new_ringptr;
new_ringptr->prev=new_ringptr;
} else {
new_ringptr->next->prev=new_ringptr;
new_ringptr->prev->next=new_ringptr;
}
if (is_list)
ringlist=new_ringptr;
return new_ringptr + 1;
#else
return ::realloc( p_memory, p_bytes );
#endif
}
void MemoryPoolStaticMalloc::free(void *p_ptr) {
ERR_FAIL_COND( !MemoryPoolStatic::get_singleton());
#if DEFAULT_ALIGNMENT == 1
_free(p_ptr);
#else
uint8_t* mem = (uint8_t*)p_ptr;
int ofs = *(mem-1);
mem = mem - ofs;
_free(mem);
#endif
};
void MemoryPoolStaticMalloc::_free(void *p_ptr) {
MutexLock lock(mutex);
#ifdef DEBUG_MEMORY_ENABLED
if (p_ptr==0) {
printf("**ERROR: STATIC ALLOC: Attempted free of NULL pointer.\n");
return;
};
RingPtr *ringptr = (RingPtr*)p_ptr;
ringptr--; /* go back an element to find the ringptr */
#if 0
{ // check for existing memory on free.
RingPtr *p = ringlist;
bool found=false;
if (ringlist) {
do {
if (p==ringptr) {
found=true;
break;
}
p=p->next;
} while (p!=ringlist);
}
if (!found) {
printf("**ERROR: STATIC ALLOC: Attempted free of unknown pointer at %p\n",(ringptr+1));
return;
}
}
#endif
/* proceed to erase */
bool single_element = (ringptr->next == ringptr) && (ringptr->prev == ringptr);
bool is_list = ( ringlist == ringptr );
if (single_element) {
/* just get rid of it */
ringlist=0;
} else {
/* auto-remove from ringlist */
if (is_list)
ringlist=ringptr->next;
ringptr->prev->next = ringptr->next;
ringptr->next->prev = ringptr->prev;
}
total_mem -= ringptr->size;
total_pointers--;
// catch more errors
zeromem(ringptr,sizeof(RingPtr)+ringptr->size);
::free(ringptr); //just free that pointer
#else
ERR_FAIL_COND(p_ptr==0);
::free(p_ptr);
#endif
}
size_t MemoryPoolStaticMalloc::get_available_mem() const {
return 0xffffffff;
}
size_t MemoryPoolStaticMalloc::get_total_usage() {
#ifdef DEBUG_MEMORY_ENABLED
return total_mem;
#else
return 0;
#endif
}
size_t MemoryPoolStaticMalloc::get_max_usage() {
return max_mem;
}
/* Most likely available only if memory debugger was compiled in */
int MemoryPoolStaticMalloc::get_alloc_count() {
return total_pointers;
}
void * MemoryPoolStaticMalloc::get_alloc_ptr(int p_alloc_idx) {
return 0;
}
const char* MemoryPoolStaticMalloc::get_alloc_description(int p_alloc_idx) {
return "";
}
size_t MemoryPoolStaticMalloc::get_alloc_size(int p_alloc_idx) {
return 0;
}
void MemoryPoolStaticMalloc::dump_mem_to_file(const char* p_file) {
#ifdef DEBUG_MEMORY_ENABLED
ERR_FAIL_COND( !ringlist ); /** WTF BUG !? */
RingPtr *p = ringlist;
FILE *f = fopen(p_file,"wb");
do {
fprintf(f,"%p-%i-%s\n", p+1, (int)p->size, (p->descr?p->descr:"") );
p=p->next;
} while (p!=ringlist);
fclose(f);
#endif
}
MemoryPoolStaticMalloc::MemoryPoolStaticMalloc() {
#ifdef DEBUG_MEMORY_ENABLED
total_mem=0;
total_pointers=0;
ringlist=0;
max_mem=0;
max_pointers=0;
#endif
mutex=NULL;
#ifndef NO_THREADS
mutex=Mutex::create(); // at this point, this should work
#endif
}
MemoryPoolStaticMalloc::~MemoryPoolStaticMalloc() {
Mutex *old_mutex=mutex;
mutex=NULL;
if (old_mutex)
memdelete(old_mutex);
#ifdef DEBUG_MEMORY_ENABLED
if (OS::get_singleton()->is_stdout_verbose()) {
if (total_mem > 0 ) {
printf("**ERROR: STATIC ALLOC: ** MEMORY LEAKS DETECTED **\n");
printf("**ERROR: STATIC ALLOC: %i bytes of memory in use at exit.\n",(int)total_mem);
if (1){
printf("**ERROR: STATIC ALLOC: Following is the list of leaked allocations: \n");
ERR_FAIL_COND( !ringlist ); /** WTF BUG !? */
RingPtr *p = ringlist;
do {
printf("\t%p - %i bytes - %s\n", (RingPtr*)(p+1), (int)p->size, (p->descr?p->descr:"") );
p=p->next;
} while (p!=ringlist);
printf("**ERROR: STATIC ALLOC: End of Report.\n");
};
printf("mem - max %i, pointers %i, leaks %i.\n",(int)max_mem,max_pointers,(int)total_mem);
} else {
printf("INFO: mem - max %i, pointers %i, no leaks.\n",(int)max_mem,max_pointers);
}
}
#endif
}

View File

@ -1,82 +0,0 @@
/*************************************************************************/
/* memory_pool_static_malloc.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#ifndef MEMORY_POOL_STATIC_MALLOC_H
#define MEMORY_POOL_STATIC_MALLOC_H
#include "os/memory_pool_static.h"
#include "os/mutex.h"
/**
@author Juan Linietsky <red@lunatea>
*/
class MemoryPoolStaticMalloc : public MemoryPoolStatic {
struct RingPtr {
size_t size;
const char *descr; /* description of memory */
RingPtr *next;
RingPtr *prev;
};
RingPtr *ringlist;
size_t total_mem;
int total_pointers;
size_t max_mem;
int max_pointers;
Mutex *mutex;
void* _alloc(size_t p_bytes,const char *p_description=""); ///< Pointer in p_description shold be to a const char const like "hello"
void* _realloc(void *p_memory,size_t p_bytes); ///< Pointer in
void _free(void *p_ptr); ///< Pointer in p_description shold be to a const char const
public:
virtual void* alloc(size_t p_bytes,const char *p_description=""); ///< Pointer in p_description shold be to a const char const like "hello"
virtual void free(void *p_ptr); ///< Pointer in p_description shold be to a const char const
virtual void* realloc(void *p_memory,size_t p_bytes); ///< Pointer in
virtual size_t get_available_mem() const;
virtual size_t get_total_usage();
virtual size_t get_max_usage();
/* Most likely available only if memory debugger was compiled in */
virtual int get_alloc_count();
virtual void * get_alloc_ptr(int p_alloc_idx);
virtual const char* get_alloc_description(int p_alloc_idx);
virtual size_t get_alloc_size(int p_alloc_idx);
void dump_mem_to_file(const char* p_file);
MemoryPoolStaticMalloc();
~MemoryPoolStaticMalloc();
};
#endif

View File

@ -30,7 +30,7 @@
#ifdef UNIX_ENABLED
#include "memory_pool_static_malloc.h"
#include "os/memory_pool_dynamic_static.h"
#include "thread_posix.h"
#include "semaphore_posix.h"
@ -116,7 +116,6 @@ int OS_Unix::unix_initialize_audio(int p_audio_driver) {
return 0;
}
static MemoryPoolStaticMalloc *mempool_static=NULL;
static MemoryPoolDynamicStatic *mempool_dynamic=NULL;
@ -145,7 +144,6 @@ void OS_Unix::initialize_core() {
PacketPeerUDPPosix::make_default();
IP_Unix::make_default();
#endif
mempool_static = new MemoryPoolStaticMalloc;
mempool_dynamic = memnew( MemoryPoolDynamicStatic );
ticks_start=0;
@ -157,7 +155,6 @@ void OS_Unix::finalize_core() {
if (mempool_dynamic)
memdelete( mempool_dynamic );
delete mempool_static;
}

View File

@ -121,9 +121,9 @@ float Performance::get_monitor(Monitor p_monitor) const {
case TIME_FPS: return OS::get_singleton()->get_frames_per_second();
case TIME_PROCESS: return _process_time;
case TIME_FIXED_PROCESS: return _fixed_process_time;
case MEMORY_STATIC: return Memory::get_static_mem_usage();
case MEMORY_STATIC: return Memory::get_mem_usage();
case MEMORY_DYNAMIC: return Memory::get_dynamic_mem_usage();
case MEMORY_STATIC_MAX: return Memory::get_static_mem_max_usage();
case MEMORY_STATIC_MAX: return Memory::get_mem_max_usage();
case MEMORY_DYNAMIC_MAX: return Memory::get_dynamic_mem_available();
case MEMORY_MESSAGE_BUFFER_MAX: return MessageQueue::get_singleton()->get_max_buffer_usage();
case OBJECT_COUNT: return ObjectDB::get_object_count();

View File

@ -30,7 +30,6 @@
#include "os_windows.h"
#include "drivers/gles3/rasterizer_gles3.h"
#include "drivers/unix/memory_pool_static_malloc.h"
#include "os/memory_pool_dynamic_static.h"
#include "drivers/windows/thread_windows.h"
#include "drivers/windows/semaphore_windows.h"
@ -167,7 +166,6 @@ const char * OS_Windows::get_audio_driver_name(int p_driver) const {
return AudioDriverManagerSW::get_driver(p_driver)->get_name();
}
static MemoryPoolStatic *mempool_static=NULL;
static MemoryPoolDynamic *mempool_dynamic=NULL;
void OS_Windows::initialize_core() {
@ -196,7 +194,6 @@ void OS_Windows::initialize_core() {
StreamPeerWinsock::make_default();
PacketPeerUDPWinsock::make_default();
mempool_static = new MemoryPoolStaticMalloc;
#if 1
mempool_dynamic = memnew( MemoryPoolDynamicStatic );
#else
@ -1308,7 +1305,6 @@ void OS_Windows::finalize_core() {
if (mempool_dynamic)
memdelete( mempool_dynamic );
delete mempool_static;
TCPServerWinsock::cleanup();