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