LArSoft  v07_13_02
Liquid Argon Software toolkit - http://larsoft.org/
MallocOpts.cc
Go to the documentation of this file.
1 
2 
3 // -*- C++ -*-
4 //
5 // Package: Utilities
6 // Class : MallocOpts
7 //
8 // Original Author: Jim Kowalkowski
9 //
10 //
11 // ------------------ resetting malloc options -----------------------
12 
14 
15 #if !defined(__APPLE__)
16 #include <malloc.h>
17 #endif
18 #include <cstdlib>
19 #include <cstring>
20 #include <iostream>
21 #include <sstream>
22 
23 namespace art {
24 
25  std::ostream&
26  operator<<(std::ostream& ost, const MallocOpts& opts)
27  {
28  ost << "mmap_max=" << opts.mmap_max_ << " trim_threshold=" << opts.trim_thr_
29  << " top_padding=" << opts.top_pad_
30  << " mmap_threshold=" << opts.mmap_thr_;
31  return ost;
32  }
33 
34  namespace {
35  typedef enum { UNKNOWN_CPU = 0, AMD_CPU = 1, INTEL_CPU = 2 } cpu_type;
36 
37  cpu_type
38  get_cpu_type()
39  {
40  // issue: these need to be static. The asm instruction combined
41  // with optimization on the 64 bit platform moves the stack data
42  // member around in such a way that the =m directive misses the
43  // the location. Of course this means that this routine is not
44  // multithread safe.
45  static volatile int op = 0, a;
46  static volatile int ans[4];
47 
48 // Still some problem on x86_64, so only i386 for now
49 #if defined(__x86_64__)
50 
51  __asm__ __volatile__("pushq %%rdx;\
52  pushq %%rcx; \
53  pushq %%rsi; \
54  pushq %%rbx; \
55  cpuid; \
56  movq %%rbx,%%rsi; \
57  popq %%rbx; \
58  movl %%ecx,%0; \
59  movl %%edx,%1; \
60  movl %%esi,%2; \
61  movl %%eax,%3; \
62  popq %%rsi; \
63  popq %%rcx; \
64  popq %%rdx;"
65  : "=m"(ans[2]), "=m"(ans[1]), "=m"(ans[0]), "=m"(a)
66  : "a"(op));
67 
68 #elif defined(__i386__)
69 
70  __asm__ __volatile__("pushl %%edx;\
71  pushl %%ecx; \
72  pushl %%esi; \
73  pushl %%ebx; \
74  cpuid; \
75  movl %%ebx,%%esi; \
76  popl %%ebx; \
77  movl %%ecx,%0; \
78  movl %%edx,%1; \
79  movl %%esi,%2; \
80  movl %%eax,%3; \
81  popl %%esi; \
82  popl %%ecx; \
83  popl %%edx;"
84  : "=m"(ans[2]), "=m"(ans[1]), "=m"(ans[0]), "=m"(a)
85  : "a"(op));
86 
87 #else
88  const char* unknown_str = "Unknown";
89  // int unknown_sz = strlen(unknown_str);
90  strcpy((char*)&ans[0], unknown_str);
91 #endif
92 
93  const char* amd_str = "AuthenticAMD";
94  int amd_sz = strlen(amd_str);
95  const char* intel_str = "GenuineIntel";
96  int intel_sz = strlen(intel_str);
97 
98  char* str = (char*)&ans[0];
99  ans[3] = 0;
100 
101  return strncmp(str, amd_str, amd_sz) == 0 ?
102  AMD_CPU :
103  strncmp(str, intel_str, intel_sz) == 0 ? INTEL_CPU : UNKNOWN_CPU;
104  }
105 
106  // values determined experimentally for each architecture
107  const MallocOpts intel_opts(262144, 524288, 5242880, 131072);
108  const MallocOpts amd_opts(0, 8388608, 131072, 10485760);
109  }
110 
111  bool
113  {
114  bool rc = true;
115 
116  switch (get_cpu_type()) {
117  case AMD_CPU: {
118  values_ = amd_opts;
119  changed_ = true;
120  break;
121  }
122  case INTEL_CPU: {
123  values_ = intel_opts;
124  changed_ = true;
125  break;
126  }
127  case UNKNOWN_CPU:
128  default:
129  rc = false;
130  }
131 
132  return rc;
133  }
134 
136  {
139  if (hasErrors()) {
140  std::cerr << "ERROR: Reset of malloc options has fails:\n"
141  << error_message_ << "\n";
142  }
143  }
144  }
145 
146  void
148  {
149  if (changed_ == false)
150  return; // only adjust if they changed
151  error_message_.clear();
152  changed_ = false;
153 
154 #ifdef M_MMAP_MAX
155  if (mallopt(M_MMAP_MAX, values_.mmap_max_) < 0)
156  error_message_ += "Could not set M_MMAP_MAX\n";
157 #endif
158 #ifdef M_TRIM_THRESHOLD
159  if (mallopt(M_TRIM_THRESHOLD, values_.trim_thr_) < 0)
160  error_message_ += "Could not set M_TRIM_THRESHOLD\n";
161 #endif
162 #ifdef M_TOP_PAD
163  if (mallopt(M_TOP_PAD, values_.top_pad_) < 0)
164  error_message_ += "ERROR: Could not set M_TOP_PAD\n";
165 #endif
166 #ifdef M_MMAP_THRESHOLD
167  if (mallopt(M_MMAP_THRESHOLD, values_.mmap_thr_) < 0)
168  error_message_ += "ERROR: Could not set M_MMAP_THRESHOLD\n";
169 #endif
170  }
171 
172  bool
174  {
175  const char* par = getenv("ART_MALLOC_RESET");
176  if (par == 0)
177  return false; // leave quickly here
178  std::string spar(par);
179  bool rc = false;
180 
181  // ART_MALLOC_RESET = "mmap_max trim_thres top_pad mmap_thres"
182 
183  if (spar.size() > 1) {
184  std::istringstream ist(spar);
187 
188  if (ist.bad()) {
189  std::cerr
190  << "bad malloc options in ART_MALLOC_RESET: " << spar << "\n"
191  << "format is: "
192  << "ART_MALLOC_RESET=\"mmap_max trim_thres top_pad mmap_thres\"\n";
193  } else {
194  std::cout << "MALLOC_OPTIONS> Reset options: "
195  << "ART_MALLOC_RESET=" << par << "\n";
196  }
197  rc = true;
198  changed_ = true;
199  }
200 
201  return rc;
202  }
203 
205 
208  {
209  return global_malloc_options;
210  }
211 
212  // ----------------------------------------------------------------
213 }
std::ostream & operator<<(std::ostream &os, EDAnalyzer::Table< T > const &t)
Definition: EDAnalyzer.h:184
opt_type mmap_max_
Definition: MallocOpts.h:43
opt_type top_pad_
Definition: MallocOpts.h:45
opt_type mmap_thr_
Definition: MallocOpts.h:46
std::string error_message_
Definition: MallocOpts.h:117
bool hasErrors() const
Definition: MallocOpts.h:72
opt_type trim_thr_
Definition: MallocOpts.h:44
MallocOptionSetter global_malloc_options
Definition: MallocOpts.cc:204
HLT enums.
MallocOptionSetter & getGlobalOptionSetter()
Definition: MallocOpts.cc:207