00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <sys/time.h>
00019 #include <sys/types.h>
00020 #include <sys/stat.h>
00021 #include <fcntl.h>
00022 #include <string.h>
00023
00024 #include "Memory.h"
00025
00026 #ifdef OASYS_DEBUG_MEMORY_ENABLED
00027
00028 namespace oasys {
00029
00030 #define _BYTE char
00031 #define _DBG_MEM_MAGIC 0xf00dbeef
00032
00033 int DbgMemInfo::entries_ = 0;
00034 dbg_mem_entry_t* DbgMemInfo::table_ = 0;
00035 bool DbgMemInfo::init_ = false;
00036 int DbgMemInfo::dump_file_ = -1;
00037 struct sigaction DbgMemInfo::signal_;
00038
00039 void
00040 DbgMemInfo::init(
00041 int flags,
00042 char* dump_file
00043 )
00044 {
00045
00046 entries_ = 0;
00047 table_ = (dbg_mem_entry_t*)
00048 calloc(_DBG_MEM_TABLE_SIZE, sizeof(dbg_mem_entry_t));
00049 memset(table_, 0, sizeof(dbg_mem_entry_t) * _DBG_MEM_TABLE_SIZE);
00050
00051 if(flags & DbgMemInfo::USE_SIGNAL)
00052 {
00053
00054 memset(&signal_, 0, sizeof(struct sigaction));
00055 signal_.sa_sigaction = DbgMemInfo::signal_handler;
00056
00057 signal_.sa_flags = SA_SIGINFO;
00058
00059 ::sigaction(SIGUSR2, &signal_, 0);
00060 }
00061
00062 if(dump_file)
00063 {
00064 dump_file_ = open(dump_file,
00065 O_WRONLY | O_CREAT | O_APPEND);
00066 }
00067
00068 init_ = true;
00069 }
00070
00071
00072 void
00073 DbgMemInfo::debug_dump(bool only_diffs)
00074 {
00075 for(int i=0; i<_DBG_MEM_TABLE_SIZE; ++i)
00076 {
00077 dbg_mem_entry_t* entry = &table_[i];
00078 if (entry->frames_[0] == 0)
00079 continue;
00080
00081 if (! only_diffs || (entry->live_ != entry->last_live_)) {
00082 log_info("/memory", "%5d: [%p %p %p] live=%d last_live=%d size=%.2fkb\n",
00083 i,
00084 entry->frames_[0],
00085 entry->frames_[1],
00086 entry->frames_[2],
00087 entry->live_,
00088 entry->last_live_,
00089 (float)entry->size_/1000);
00090 }
00091
00092 entry->last_live_ = entry->live_;
00093 }
00094 }
00095
00096 void
00097 DbgMemInfo::dump_to_file(int fd)
00098 {
00099 if(fd == -1) {
00100 return;
00101 }
00102
00103 struct timeval time;
00104 char buf[256];
00105
00106 gettimeofday(&time, 0);
00107 ctime_r((const time_t*)&time.tv_sec, buf);
00108 write(fd, buf, strlen(buf));
00109
00110 for(int i=0; i<_DBG_MEM_TABLE_SIZE; ++i)
00111 {
00112 dbg_mem_entry_t* entry = &table_[i];
00113 if(entry->frames_[0] == 0)
00114 continue;
00115
00116 snprintf(buf, 256,
00117 "%5d: [%p %p %p] live=%d size=%.2fkb\n",
00118 i,
00119 entry->frames_[0],
00120 entry->frames_[1],
00121 entry->frames_[2],
00122 entry->live_,
00123 (float)entry->size_/1000);
00124
00125 write(fd, buf, strlen(buf));
00126 }
00127 fsync(fd);
00128 }
00129
00130 void
00131 DbgMemInfo::signal_handler(
00132 int signal,
00133 siginfo_t* info,
00134 void* context
00135 )
00136 {
00137 dump_to_file(dump_file_);
00138 }
00139
00140 }
00141
00145 static inline void
00146 set_frame_info(void** frames)
00147 {
00148 #ifdef __GNUC__
00149 #define FILL_FRAME(_x) \
00150 if(__builtin_frame_address(_x) == 0) { \
00151 return; \
00152 } else { \
00153 frames[_x-1] = __builtin_return_address(_x); \
00154 }
00155
00156 FILL_FRAME(1);
00157 FILL_FRAME(2);
00158 FILL_FRAME(3);
00159 FILL_FRAME(4);
00160 #undef FILL_FRAME
00161 #else
00162 #error Depends on compiler implementation, implement me.
00163 #endif
00164 }
00165
00166 void*
00167 operator new(size_t size) throw (std::bad_alloc)
00168 {
00169
00170
00171
00172 oasys::dbg_mem_t* b = static_cast<oasys::dbg_mem_t*>
00173 (malloc(sizeof(oasys::dbg_mem_t) + size));
00174
00175 if(b == 0) {
00176 throw std::bad_alloc();
00177 }
00178
00179 memset(b, 0, sizeof(oasys::dbg_mem_t));
00180 b->magic_ = _DBG_MEM_MAGIC;
00181 b->size_ = size;
00182
00183
00184 if (oasys::DbgMemInfo::initialized()) {
00185 void* frames[_DBG_MEM_FRAMES];
00186
00187 set_frame_info(frames);
00188 b->entry_ = oasys::DbgMemInfo::inc(frames, size);
00189
00190
00191
00192
00193
00194 }
00195
00196 return (void*)&b->block_;
00197 }
00198
00199 void
00200 operator delete(void *ptr) throw ()
00201 {
00202 oasys::dbg_mem_t* b = PARENT_PTR(ptr, oasys::dbg_mem_t, block_);
00203
00204 ASSERT(b->magic_ == _DBG_MEM_MAGIC);
00205
00206 if (b->entry_ != 0) {
00207
00208
00209
00210
00211
00212
00213
00214 oasys::DbgMemInfo::dec(b);
00215 }
00216
00217 char* bp = (char*)(b);
00218 unsigned int size = b->size_;
00219
00220 for(unsigned int i=0; i<size; ++i)
00221 {
00222 bp[i] = 0xF0;
00223 }
00224
00225 free(b);
00226 }
00227
00228 #endif // OASYS_DEBUG_MEMORY_ENABLED
00229