Memory.cc

Go to the documentation of this file.
00001 /*
00002  * IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. By
00003  * downloading, copying, installing or using the software you agree to
00004  * this license. If you do not agree to this license, do not download,
00005  * install, copy or use the software.
00006  * 
00007  * Intel Open Source License 
00008  * 
00009  * Copyright (c) 2004 Intel Corporation. All rights reserved. 
00010  * 
00011  * Redistribution and use in source and binary forms, with or without
00012  * modification, are permitted provided that the following conditions are
00013  * met:
00014  * 
00015  *   Redistributions of source code must retain the above copyright
00016  *   notice, this list of conditions and the following disclaimer.
00017  * 
00018  *   Redistributions in binary form must reproduce the above copyright
00019  *   notice, this list of conditions and the following disclaimer in the
00020  *   documentation and/or other materials provided with the distribution.
00021  * 
00022  *   Neither the name of the Intel Corporation nor the names of its
00023  *   contributors may be used to endorse or promote products derived from
00024  *   this software without specific prior written permission.
00025  *  
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00029  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR
00030  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00031  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00032  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00033  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00034  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00035  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00036  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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     // XXX/bowei Needs to be changed to MMAP
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         //signal_.sa_mask    = 
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 } // namespace oasys
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     // The reason for these two code paths is the prescence of static
00191     // initializers which allocate memory on the heap. Memory
00192     // allocated before init is called is not tracked.
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     // non-init allocations have frame == 0
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 // logging may not be initialized yet...
00212         
00213 //      log_debug("/memory", "new a=%p, f=[%p %p %p]\n",              
00214 //                &b->block_, frames[0], frames[1], frames[2]);     
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 // logging may not be initialized yet...
00229         
00230 //      log_debug("/memory", "delete a=%p, f=[%p %p %p]\n", 
00231 //                &b->block_, 
00232 //                b->entry_->frames_[0], b->entry_->frames_[1], 
00233 //                b->entry_->frames_[2]);
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 

Generated on Fri Dec 22 14:47:59 2006 for DTN Reference Implementation by  doxygen 1.5.1