Memory.cc

Go to the documentation of this file.
00001 /*
00002  *    Copyright 2004-2006 Intel Corporation
00003  * 
00004  *    Licensed under the Apache License, Version 2.0 (the "License");
00005  *    you may not use this file except in compliance with the License.
00006  *    You may obtain a copy of the License at
00007  * 
00008  *        http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  *    Unless required by applicable law or agreed to in writing, software
00011  *    distributed under the License is distributed on an "AS IS" BASIS,
00012  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  *    See the License for the specific language governing permissions and
00014  *    limitations under the License.
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     // XXX/bowei Needs to be changed to MMAP
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         //signal_.sa_mask    = 
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 } // namespace oasys
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     // The reason for these two code paths is the prescence of static
00170     // initializers which allocate memory on the heap. Memory
00171     // allocated before init is called is not tracked.
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     // non-init allocations have frame == 0
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 // logging may not be initialized yet...
00191         
00192 //      log_debug("/memory", "new a=%p, f=[%p %p %p]\n",              
00193 //                &b->block_, frames[0], frames[1], frames[2]);     
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 // logging may not be initialized yet...
00208         
00209 //      log_debug("/memory", "delete a=%p, f=[%p %p %p]\n", 
00210 //                &b->block_, 
00211 //                b->entry_->frames_[0], b->entry_->frames_[1], 
00212 //                b->entry_->frames_[2]);
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 

Generated on Thu Jun 7 16:56:50 2007 for DTN Reference Implementation by  doxygen 1.5.1