00001 #include "IgTools/IgProf/src/IgProf.h"
00002 #include "IgTools/IgProf/src/IgProfTrace.h"
00003 #include "IgTools/IgHook/interface/IgHook.h"
00004 #include "IgTools/IgHook/interface/IgHookTrace.h"
00005 #include <cstdlib>
00006 #include <cstring>
00007 #include <cstdio>
00008 #include <pthread.h>
00009
00010
00011
00012 IGPROF_DUAL_HOOK(1, void *, domalloc, _main, _libc,
00013 (size_t n), (n),
00014 "malloc", 0, "libc.so.6")
00015 IGPROF_DUAL_HOOK(2, void *, docalloc, _main, _libc,
00016 (size_t n, size_t m), (n, m),
00017 "calloc", 0, "libc.so.6")
00018 IGPROF_DUAL_HOOK(2, void *, dorealloc, _main, _libc,
00019 (void *ptr, size_t n), (ptr, n),
00020 "realloc", 0, "libc.so.6")
00021 IGPROF_DUAL_HOOK(3, int, dopmemalign, _main, _libc,
00022 (void **ptr, size_t alignment, size_t size),
00023 (ptr, alignment, size),
00024 "posix_memalign", 0, "libc.so.6")
00025 IGPROF_DUAL_HOOK(2, void *, domemalign, _main, _libc,
00026 (size_t alignment, size_t size), (alignment, size),
00027 "memalign", 0, "libc.so.6")
00028 IGPROF_DUAL_HOOK(1, void *, dovalloc, _main, _libc,
00029 (size_t size), (size),
00030 "valloc", 0, "libc.so.6")
00031 IGPROF_DUAL_HOOK(1, void, dofree, _main, _libc,
00032 (void *ptr), (ptr),
00033 "free", 0, "libc.so.6")
00034
00035
00036 static IgProfTrace::CounterDef s_ct_total = { "MEM_TOTAL", IgProfTrace::TICK, -1 };
00037 static IgProfTrace::CounterDef s_ct_largest = { "MEM_MAX", IgProfTrace::MAX, -1 };
00038 static IgProfTrace::CounterDef s_ct_live = { "MEM_LIVE", IgProfTrace::TICK_PEAK, -1 };
00039 static bool s_count_total = 0;
00040 static bool s_count_largest = 0;
00041 static bool s_count_live = 0;
00042 static bool s_initialized = false;
00043 static int s_moduleid = -1;
00044
00048 static void __attribute__((noinline))
00049 add(void *ptr, size_t size)
00050 {
00051 IgProfTrace *buf = IgProf::buffer(s_moduleid);
00052 if (! buf)
00053 return;
00054
00055 void *addresses [IgProfTrace::MAX_DEPTH];
00056 int depth = IgHookTrace::stacktrace(addresses, IgProfTrace::MAX_DEPTH);
00057 IgProfTrace::Record entries [3];
00058 int nentries = 0;
00059
00060 if (s_count_total)
00061 {
00062 entries[nentries].type = IgProfTrace::COUNT;
00063 entries[nentries].def = &s_ct_total;
00064 entries[nentries].amount = size;
00065 entries[nentries].ticks = 1;
00066 nentries++;
00067 }
00068
00069 if (s_count_largest)
00070 {
00071 entries[nentries].type = IgProfTrace::COUNT;
00072 entries[nentries].def = &s_ct_largest;
00073 entries[nentries].amount = size;
00074 entries[nentries].ticks = 1;
00075 nentries++;
00076 }
00077
00078 if (s_count_live)
00079 {
00080 entries[nentries].type = IgProfTrace::COUNT | IgProfTrace::ACQUIRE;
00081 entries[nentries].def = &s_ct_live;
00082 entries[nentries].amount = size;
00083 entries[nentries].ticks = 1;
00084 entries[nentries].resource = (IgProfTrace::Address) ptr;
00085 nentries++;
00086 }
00087
00088
00089 buf->push(addresses+4, depth-5, entries, nentries);
00090 }
00091
00095 static void
00096 remove (void *ptr)
00097 {
00098 if (s_count_live && ptr)
00099 {
00100 IgProfTrace *buf = IgProf::buffer(s_moduleid);
00101 if (! buf)
00102 return;
00103
00104 IgProfTrace::Record entry
00105 = { IgProfTrace::RELEASE, &s_ct_live, 0, 0, (IgProfTrace::Address) ptr };
00106 buf->push(0, 0, &entry, 1);
00107 }
00108 }
00109
00110
00113 static void
00114 initialize(void)
00115 {
00116 if (s_initialized) return;
00117 s_initialized = true;
00118
00119 const char *options = IgProf::options();
00120 bool enable = false;
00121 bool opts = false;
00122
00123 while (options && *options)
00124 {
00125 while (*options == ' ' || *options == ',')
00126 ++options;
00127
00128 if (! strncmp(options, "mem", 3))
00129 {
00130 enable = true;
00131 options += 3;
00132 while (*options)
00133 {
00134 if (! strncmp(options, ":total", 6))
00135 {
00136 s_count_total = 1;
00137 options += 6;
00138 opts = true;
00139 }
00140 else if (! strncmp(options, ":largest", 8))
00141 {
00142 s_count_largest = 1;
00143 options += 8;
00144 opts = true;
00145 }
00146 else if (! strncmp(options, ":live", 5))
00147 {
00148 s_count_live = 1;
00149 options += 5;
00150 opts = true;
00151 }
00152 else if (! strncmp(options, ":all", 4))
00153 {
00154 s_count_total = 1;
00155 s_count_largest = 1;
00156 s_count_live = 1;
00157 options += 4;
00158 opts = true;
00159 }
00160 else
00161 break;
00162 }
00163 }
00164 else
00165 options++;
00166
00167 while (*options && *options != ',' && *options != ' ')
00168 options++;
00169 }
00170
00171 if (! enable)
00172 return;
00173
00174 if (! IgProf::initialize(&s_moduleid, 0, false))
00175 return;
00176
00177 IgProf::disable(true);
00178 if (! opts)
00179 {
00180 IgProf::debug("Memory: defaulting to total memory counting\n");
00181 s_count_total = 1;
00182 }
00183 else
00184 {
00185 if (s_count_total)
00186 IgProf::debug("Memory: enabling total counting\n");
00187 if (s_count_largest)
00188 IgProf::debug("Memory: enabling max counting\n");
00189 if (s_count_live)
00190 IgProf::debug("Memory: enabling live counting\n");
00191 }
00192
00193 IgHook::hook(domalloc_hook_main.raw);
00194 IgHook::hook(docalloc_hook_main.raw);
00195 IgHook::hook(dorealloc_hook_main.raw);
00196 IgHook::hook(dopmemalign_hook_main.raw);
00197 IgHook::hook(domemalign_hook_main.raw);
00198 IgHook::hook(dovalloc_hook_main.raw);
00199 IgHook::hook(dofree_hook_main.raw);
00200 #if __linux
00201 if (domalloc_hook_main.raw.chain) IgHook::hook(domalloc_hook_libc.raw);
00202 if (docalloc_hook_main.raw.chain) IgHook::hook(docalloc_hook_libc.raw);
00203 if (domemalign_hook_main.raw.chain) IgHook::hook(domemalign_hook_libc.raw);
00204 if (dovalloc_hook_main.raw.chain) IgHook::hook(dovalloc_hook_libc.raw);
00205 if (dofree_hook_main.raw.chain) IgHook::hook(dofree_hook_libc.raw);
00206 #endif
00207 IgProf::debug("Memory profiler enabled\n");
00208 IgProf::enable(true);
00209 }
00210
00211
00212
00213 static void *
00214 domalloc(IgHook::SafeData<igprof_domalloc_t> &hook, size_t n)
00215 {
00216 bool enabled = IgProf::disable(false);
00217 void *result = (*hook.chain)(n);
00218
00219 if (enabled && result)
00220 add(result, n);
00221
00222 IgProf::enable(false);
00223 return result;
00224 }
00225
00226 static void *
00227 docalloc(IgHook::SafeData<igprof_docalloc_t> &hook, size_t n, size_t m)
00228 {
00229 bool enabled = IgProf::disable(false);
00230 void *result = (*hook.chain)(n, m);
00231
00232 if (enabled && result)
00233 add(result, n * m);
00234
00235 IgProf::enable(false);
00236 return result;
00237 }
00238
00239 static void *
00240 dorealloc(IgHook::SafeData<igprof_dorealloc_t> &hook, void *ptr, size_t n)
00241 {
00242 bool enabled = IgProf::disable(false);
00243 void *result = (*hook.chain)(ptr, n);
00244
00245 if (result)
00246 {
00247 if (ptr) remove(ptr);
00248 if (enabled && result) add(result, n);
00249 }
00250
00251 IgProf::enable(false);
00252 return result;
00253 }
00254
00255 static void *
00256 domemalign(IgHook::SafeData<igprof_domemalign_t> &hook, size_t alignment, size_t size)
00257 {
00258 bool enabled = IgProf::disable(false);
00259 void *result = (*hook.chain)(alignment, size);
00260
00261 if (enabled && result)
00262 add(result, size);
00263
00264 IgProf::enable(false);
00265 return result;
00266 }
00267
00268 static void *
00269 dovalloc(IgHook::SafeData<igprof_dovalloc_t> &hook, size_t size)
00270 {
00271 bool enabled = IgProf::disable(false);
00272 void *result = (*hook.chain)(size);
00273
00274 if (enabled && result)
00275 add(result, size);
00276
00277 IgProf::enable(false);
00278 return result;
00279 }
00280
00281 static int
00282 dopmemalign(IgHook::SafeData<igprof_dopmemalign_t> &hook,
00283 void **ptr, size_t alignment, size_t size)
00284 {
00285 bool enabled = IgProf::disable(false);
00286 int result = (*hook.chain)(ptr, alignment, size);
00287
00288 if (enabled && ptr && *ptr)
00289 add(*ptr, size);
00290
00291 IgProf::enable(false);
00292 return result;
00293 }
00294
00295 static void
00296 dofree(IgHook::SafeData<igprof_dofree_t> &hook, void *ptr)
00297 {
00298 IgProf::disable(false);
00299 remove(ptr);
00300 (*hook.chain)(ptr);
00301 IgProf::enable(false);
00302 }
00303
00304
00305 static bool autoboot = (initialize(), true);