CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/FWCore/Utilities/src/MallocOpts.cc

Go to the documentation of this file.
00001 
00002 
00003 // -*- C++ -*-
00004 //
00005 // Package:     Utilities
00006 // Class  :     MallocOpts
00007 // 
00008 // Original Author:  Jim Kowalkowski
00009 //
00010 // ------------------ resetting malloc options -----------------------
00011 
00012 
00013 #include "FWCore/Utilities/interface/MallocOpts.h"
00014 
00015 #if !defined(__APPLE__)
00016 #include <malloc.h>
00017 #endif
00018 #include <sstream>
00019 #include <iostream>
00020 #include <cstdlib>
00021 #include <cstring>
00022 
00023 namespace edm
00024 {
00025 
00026   std::ostream& operator<<(std::ostream& ost,const MallocOpts& opts)
00027   {
00028     ost << "mmap_max=" << opts.mmap_max_
00029         << " trim_threshold=" << opts.trim_thr_
00030         << " top_padding=" << opts.top_pad_
00031         << " mmap_threshold=" << opts.mmap_thr_;
00032     return ost;
00033   }
00034 
00035   namespace 
00036   {
00037     typedef enum { UNKNOWN_CPU=0, AMD_CPU=1, INTEL_CPU=2 } cpu_type;
00038   
00039     cpu_type get_cpu_type()
00040     {
00041       // issue: these need to be static.  The asm instruction combined
00042       // with optimization on the 64 bit platform moves the stack data
00043       // member around in such a way that the =m directive misses the
00044       // the location.   Of course this means that this routine is not
00045       // multithread safe.
00046       static volatile int ans[4];
00047 #if defined(__i386__) || defined(__x86_64__)
00048       static volatile int op=0,a;
00049 #endif
00050 
00051 // Still some problem on x86_64, so only i386 for now    
00052 #if defined(__x86_64__)
00053 
00054       __asm__ __volatile__ ("pushq %%rdx;\
00055  pushq %%rcx;                            \
00056  pushq %%rsi;                            \
00057  pushq %%rbx;                            \
00058  cpuid;                                  \
00059  movq  %%rbx,%%rsi;                      \
00060  popq  %%rbx;                            \
00061  movl  %%ecx,%0;                         \
00062  movl  %%edx,%1;                         \
00063  movl  %%esi,%2;                         \
00064  movl  %%eax,%3;                         \
00065  popq  %%rsi;                            \
00066  popq  %%rcx;                            \
00067  popq  %%rdx;"
00068                             : "=m"(ans[2]), "=m"(ans[1]), "=m"(ans[0]), "=m"(a)
00069                             : "a"(op)
00070                             );
00071 
00072 #elif defined(__i386__)
00073 
00074 
00075       __asm__ __volatile__ ("pushl %%edx;\
00076  pushl %%ecx;                            \
00077  pushl %%esi;                            \
00078  pushl %%ebx;                            \
00079  cpuid;                                  \
00080  movl  %%ebx,%%esi;                      \
00081  popl  %%ebx;                            \
00082  movl  %%ecx,%0;                         \
00083  movl  %%edx,%1;                         \
00084  movl  %%esi,%2;                         \
00085  movl  %%eax,%3;                         \
00086  popl  %%esi;                            \
00087  popl  %%ecx;                            \
00088  popl  %%edx;"
00089                             : "=m"(ans[2]), "=m"(ans[1]), "=m"(ans[0]), "=m"(a)
00090                             : "a"(op)
00091                             );
00092 
00093     
00094 #else
00095       const char* unknown_str = "Unknown";
00096       // int unknown_sz = strlen(unknown_str);
00097       strcpy((char*)&ans[0],unknown_str);
00098 #endif
00099       
00100       const char* amd_str = "AuthenticAMD";
00101       int amd_sz = strlen(amd_str);
00102       const char* intel_str = "GenuineIntel";
00103       int intel_sz = strlen(intel_str);
00104     
00105       char* str = (char*)&ans[0];
00106       ans[3]=0;
00107 
00108       return strncmp(str,amd_str,amd_sz)==0?AMD_CPU:
00109         strncmp(str,intel_str,intel_sz)==0?INTEL_CPU:UNKNOWN_CPU;
00110     }
00111 
00112     // values determined experimentally for each architecture
00113     const MallocOpts intel_opts(262144, 524288, 5242880, 131072);
00114     const MallocOpts amd_opts(0, 8388608, 131072, 10485760);
00115 
00116   }
00117 
00118 
00119   bool MallocOptionSetter::retrieveFromCpuType()
00120   {
00121     bool rc=true;
00122 
00123     switch(get_cpu_type())
00124       {
00125       case AMD_CPU:
00126         {
00127           values_ = amd_opts;
00128           changed_=true;
00129           break;
00130         }
00131       case INTEL_CPU:
00132         {
00133           values_ = intel_opts;
00134           changed_=true;
00135           break;
00136         }
00137       case UNKNOWN_CPU:
00138       default:
00139         rc=false;
00140       }
00141 
00142     return rc;
00143   }
00144 
00145   MallocOptionSetter::MallocOptionSetter():
00146     changed_(false)
00147   {
00148     if(retrieveFromEnv() || retrieveFromCpuType())
00149       {
00150         adjustMallocParams();
00151         if(hasErrors())
00152           {
00153             std::cerr << "ERROR: Reset of malloc options has fails:\n"
00154                       << error_message_ << "\n";
00155           }
00156       }
00157   }
00158 
00159   void MallocOptionSetter::adjustMallocParams()
00160   {
00161     if(changed_==false) return; // only adjust if they changed
00162     error_message_.clear();
00163     changed_ = false;
00164 
00165 #ifdef M_MMAP_MAX
00166     if(mallopt(M_MMAP_MAX,values_.mmap_max_)<0)
00167       error_message_ += "Could not set M_MMAP_MAX\n"; 
00168 #endif
00169 #ifdef M_TRIM_THRESHOLD
00170     if(mallopt(M_TRIM_THRESHOLD,values_.trim_thr_)<0)
00171       error_message_ += "Could not set M_TRIM_THRESHOLD\n"; 
00172 #endif
00173 #ifdef M_TOP_PAD
00174     if(mallopt(M_TOP_PAD,values_.top_pad_)<0)
00175       error_message_ += "ERROR: Could not set M_TOP_PAD\n";
00176 #endif
00177 #ifdef M_MMAP_THRESHOLD
00178     if(mallopt(M_MMAP_THRESHOLD,values_.mmap_thr_)<0)
00179       error_message_ += "ERROR: Could not set M_MMAP_THRESHOLD\n";
00180 #endif
00181   }
00182 
00183   bool MallocOptionSetter::retrieveFromEnv()
00184   {
00185     const char* par = getenv("CMSRUN_MALLOC_RESET");
00186     if(par==0) return false; // leave quickly here
00187     std::string spar(par);
00188     bool rc = false;
00189       
00190     // CMSRUN_MALLOC_RESET = "mmap_max trim_thres top_pad mmap_thres"
00191       
00192     if(spar.size()>1)
00193       {
00194         std::istringstream ist(spar);
00195         ist >> values_.mmap_max_ >> values_.trim_thr_
00196             >> values_.top_pad_ >> values_.mmap_thr_;
00197 
00198         if(ist.bad())
00199           {
00200             std::cerr << "bad malloc options in CMSRUN_MALLOC_RESET: "
00201                       << spar << "\n"
00202                       << "format is: "
00203                       << "CMSRUN_MALLOC_RESET=\"mmap_max trim_thres top_pad mmap_thres\"\n";
00204           }
00205         else
00206           {
00207             std::cout << "MALLOC_OPTIONS> Reset options: "
00208                       << "CMSRUN_MALLOC_RESET=" << par << "\n";
00209           }
00210         rc=true;
00211         changed_=true;
00212       }
00213 
00214     return rc;
00215   }
00216 
00217   MallocOptionSetter global_malloc_options;
00218 
00219   MallocOptionSetter& getGlobalOptionSetter()
00220   {
00221     return global_malloc_options;
00222   }
00223 
00224 
00225   // ----------------------------------------------------------------
00226 }