00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef _OASYS_MEMORY_H_
00018 #define _OASYS_MEMORY_H_
00019
00020 #include "config.h"
00021
00022 #ifdef OASYS_DEBUG_MEMORY_ENABLED
00023
00024 #include <cstddef>
00025 #include <cstdlib>
00026 #include <cstring>
00027
00028 #include <signal.h>
00029 #include <sys/mman.h>
00030
00031 #include "../compat/inttypes.h"
00032 #include "../debug/DebugUtils.h"
00033 #include "../debug/Log.h"
00034 #include "../util/jenkins_hash.h"
00035
00039 void* operator new(size_t size) throw (std::bad_alloc);
00040
00045 void operator delete(void *ptr) throw ();
00046
00047 namespace oasys {
00048
00079 #ifdef __GNUC__
00080
00081 #define _ALIGNED __attribute__((aligned))
00082 #else
00083 #error Must define aligned attribute for this compiler.
00084 #endif
00085
00086 #define _BYTE char
00087 #define _DBG_MEM_FRAMES 3
00088
00089 #ifndef _DBG_MEM_TABLE_EXP
00090 #define _DBG_MEM_TABLE_EXP 10
00091 #endif
00092
00093 #define _DBG_MEM_TABLE_SIZE 1<<_DBG_MEM_TABLE_EXP
00094 #define _DBG_MEM_MMAP_HIGH
00095
00099 #define PARENT_PTR(_ptr, _type, _field) \
00100 ( (_type*) ((_BYTE*)_ptr - offsetof(_type, _field)) )
00101
00105 struct dbg_mem_entry_t {
00106 void* frames_[_DBG_MEM_FRAMES];
00107 int live_;
00108 int last_live_;
00109 u_int32_t size_;
00110 };
00111
00116 struct dbg_mem_t {
00117 unsigned long magic_;
00118 dbg_mem_entry_t* entry_;
00119 u_int32_t size_;
00120
00121 _BYTE block_ _ALIGNED;
00122 };
00123
00128 class DbgMemInfo {
00129 public:
00130 enum {
00131 NO_FLAGS = 0,
00132 USE_SIGNAL = 1,
00133 };
00134
00135
00141 static void init(int flags = NO_FLAGS, char* dump_file = 0);
00142
00143
00144 #define MATCH(_f1, _f2) \
00145 (memcmp((_f1), (_f2), sizeof(void*) * _DBG_MEM_FRAMES) == 0)
00146
00147
00148 #define MOD(_x, _m) \
00149 ((_x) & ((unsigned int)(~0))>>((sizeof(int)*8) - (_m)))
00150
00154 static inline dbg_mem_entry_t* find(void** frames) {
00155 int key = MOD(jenkins_hash((u_int8_t*)frames,
00156 sizeof(void*) * _DBG_MEM_FRAMES, 0),
00157 _DBG_MEM_TABLE_EXP);
00158 dbg_mem_entry_t* entry = &table_[key];
00159
00160
00161
00162 while(entry->frames_[0] != 0 &&
00163 !MATCH(frames, entry->frames_))
00164 {
00165 ++key;
00166 entry = &table_[key];
00167 }
00168
00169 return entry;
00170 }
00171
00175 static inline dbg_mem_entry_t* inc(
00176 void** frames,
00177 u_int32_t size
00178 )
00179 {
00180 dbg_mem_entry_t* entry = find(frames);
00181
00182 if(entry->frames_[0] == 0) {
00183 memcpy(entry->frames_, frames, sizeof(void*) * _DBG_MEM_FRAMES);
00184 entry->live_ = 1;
00185 entry->last_live_ = 0;
00186 } else {
00187 ++(entry->live_);
00188 }
00189
00190 entry->size_ += size;
00191 ++entries_;
00192
00193 return entry;
00194 }
00195
00199 static inline dbg_mem_entry_t* dec(dbg_mem_t* mem) {
00200 void** frames = mem->entry_->frames_;
00201 u_int32_t size = mem->size_;
00202
00203 dbg_mem_entry_t* entry = find(frames);
00204
00205 if(entry->frames_[0] == 0) {
00206 PANIC("Decrementing memory entry with no frame info");
00207 } else {
00208 entry->live_ -= 1;
00209 entry->size_ -= size;
00210
00211 if(entry->live_ < 0) {
00212 PANIC("Memory object live count < 0");
00213 }
00214 }
00215
00216 return entry;
00217 }
00218
00222 static dbg_mem_entry_t** get_table() { return &table_; }
00223
00229 static void debug_dump(bool only_diffs = false);
00230
00236 static void dump_to_file(int fd);
00237
00241 static bool initialized() { return init_; }
00242
00246 static void signal_handler(int signal, siginfo_t* info, void* context);
00247
00248 private:
00252 static int entries_;
00253 static dbg_mem_entry_t* table_;
00254 static bool init_;
00255 static int dump_file_;
00256 static struct sigaction signal_;
00257 };
00258
00259
00260 #undef _ALIGNED
00261 #undef _BYTE
00262
00263 #undef MATCH
00264 #undef MOD
00265
00266 }
00267
00268 #endif // OASYS_DEBUG_MEMORY_ENABLED
00269
00270 #endif //_OASYS_MEMORY_H_