00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef _OASYS_MEMORY_H_
00039 #define _OASYS_MEMORY_H_
00040
00041 #include "config.h"
00042
00043 #ifdef OASYS_DEBUG_MEMORY_ENABLED
00044
00045 #include <cstddef>
00046 #include <cstdlib>
00047 #include <cstring>
00048
00049 #include <signal.h>
00050 #include <sys/mman.h>
00051
00052 #include "../compat/inttypes.h"
00053 #include "../debug/DebugUtils.h"
00054 #include "../debug/Log.h"
00055 #include "../util/jenkins_hash.h"
00056
00060 void* operator new(size_t size) throw (std::bad_alloc);
00061
00066 void operator delete(void *ptr) throw ();
00067
00068 namespace oasys {
00069
00100 #ifdef __GNUC__
00101
00102 #define _ALIGNED __attribute__((aligned))
00103 #else
00104 #error Must define aligned attribute for this compiler.
00105 #endif
00106
00107 #define _BYTE char
00108 #define _DBG_MEM_FRAMES 3
00109
00110 #ifndef _DBG_MEM_TABLE_EXP
00111 #define _DBG_MEM_TABLE_EXP 10
00112 #endif
00113
00114 #define _DBG_MEM_TABLE_SIZE 1<<_DBG_MEM_TABLE_EXP
00115 #define _DBG_MEM_MMAP_HIGH
00116
00120 #define PARENT_PTR(_ptr, _type, _field) \
00121 ( (_type*) ((_BYTE*)_ptr - offsetof(_type, _field)) )
00122
00126 struct dbg_mem_entry_t {
00127 void* frames_[_DBG_MEM_FRAMES];
00128 int live_;
00129 int last_live_;
00130 u_int32_t size_;
00131 };
00132
00137 struct dbg_mem_t {
00138 unsigned long magic_;
00139 dbg_mem_entry_t* entry_;
00140 u_int32_t size_;
00141
00142 _BYTE block_ _ALIGNED;
00143 };
00144
00149 class DbgMemInfo {
00150 public:
00151 enum {
00152 NO_FLAGS = 0,
00153 USE_SIGNAL = 1,
00154 };
00155
00156
00162 static void init(int flags = NO_FLAGS, char* dump_file = 0);
00163
00164
00165 #define MATCH(_f1, _f2) \
00166 (memcmp((_f1), (_f2), sizeof(void*) * _DBG_MEM_FRAMES) == 0)
00167
00168
00169 #define MOD(_x, _m) \
00170 ((_x) & ((unsigned int)(~0))>>((sizeof(int)*8) - (_m)))
00171
00175 static inline dbg_mem_entry_t* find(void** frames) {
00176 int key = MOD(jenkins_hash((u_int8_t*)frames,
00177 sizeof(void*) * _DBG_MEM_FRAMES, 0),
00178 _DBG_MEM_TABLE_EXP);
00179 dbg_mem_entry_t* entry = &table_[key];
00180
00181
00182
00183 while(entry->frames_[0] != 0 &&
00184 !MATCH(frames, entry->frames_))
00185 {
00186 ++key;
00187 entry = &table_[key];
00188 }
00189
00190 return entry;
00191 }
00192
00196 static inline dbg_mem_entry_t* inc(
00197 void** frames,
00198 u_int32_t size
00199 )
00200 {
00201 dbg_mem_entry_t* entry = find(frames);
00202
00203 if(entry->frames_[0] == 0) {
00204 memcpy(entry->frames_, frames, sizeof(void*) * _DBG_MEM_FRAMES);
00205 entry->live_ = 1;
00206 entry->last_live_ = 0;
00207 } else {
00208 ++(entry->live_);
00209 }
00210
00211 entry->size_ += size;
00212 ++entries_;
00213
00214 return entry;
00215 }
00216
00220 static inline dbg_mem_entry_t* dec(dbg_mem_t* mem) {
00221 void** frames = mem->entry_->frames_;
00222 u_int32_t size = mem->size_;
00223
00224 dbg_mem_entry_t* entry = find(frames);
00225
00226 if(entry->frames_[0] == 0) {
00227 PANIC("Decrementing memory entry with no frame info");
00228 } else {
00229 entry->live_ -= 1;
00230 entry->size_ -= size;
00231
00232 if(entry->live_ < 0) {
00233 PANIC("Memory object live count < 0");
00234 }
00235 }
00236
00237 return entry;
00238 }
00239
00243 static dbg_mem_entry_t** get_table() { return &table_; }
00244
00250 static void debug_dump(bool only_diffs = false);
00251
00257 static void dump_to_file(int fd);
00258
00262 static bool initialized() { return init_; }
00263
00267 static void signal_handler(int signal, siginfo_t* info, void* context);
00268
00269 private:
00273 static int entries_;
00274 static dbg_mem_entry_t* table_;
00275 static bool init_;
00276 static int dump_file_;
00277 static struct sigaction signal_;
00278 };
00279
00280
00281 #undef _ALIGNED
00282 #undef _BYTE
00283
00284 #undef MATCH
00285 #undef MOD
00286
00287 }
00288
00289 #endif // OASYS_DEBUG_MEMORY_ENABLED
00290
00291 #endif //_OASYS_MEMORY_H_