CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_3/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 op=0,a;
00047       static volatile int ans[4];
00048 
00049 // Still some problem on x86_64, so only i386 for now    
00050 #if defined(__x86_64__)
00051 
00052       __asm__ __volatile__ ("pushq %%rdx;\
00053  pushq %%rcx;                            \
00054  pushq %%rsi;                            \
00055  pushq %%rbx;                            \
00056  cpuid;                                  \
00057  movq  %%rbx,%%rsi;                      \
00058  popq  %%rbx;                            \
00059  movl  %%ecx,%0;                         \
00060  movl  %%edx,%1;                         \
00061  movl  %%esi,%2;                         \
00062  movl  %%eax,%3;                         \
00063  popq  %%rsi;                            \
00064  popq  %%rcx;                            \
00065  popq  %%rdx;"
00066                             : "=m"(ans[2]), "=m"(ans[1]), "=m"(ans[0]), "=m"(a)
00067                             : "a"(op)
00068                             );
00069 
00070 #elif defined(__i386__)
00071 
00072 
00073       __asm__ __volatile__ ("pushl %%edx;\
00074  pushl %%ecx;                            \
00075  pushl %%esi;                            \
00076  pushl %%ebx;                            \
00077  cpuid;                                  \
00078  movl  %%ebx,%%esi;                      \
00079  popl  %%ebx;                            \
00080  movl  %%ecx,%0;                         \
00081  movl  %%edx,%1;                         \
00082  movl  %%esi,%2;                         \
00083  movl  %%eax,%3;                         \
00084  popl  %%esi;                            \
00085  popl  %%ecx;                            \
00086  popl  %%edx;"
00087                             : "=m"(ans[2]), "=m"(ans[1]), "=m"(ans[0]), "=m"(a)
00088                             : "a"(op)
00089                             );
00090 
00091     
00092 #else
00093       const char* unknown_str = "Unknown";
00094       // int unknown_sz = strlen(unknown_str);
00095       strcpy((char*)&ans[0],unknown_str);
00096 #endif
00097       
00098       const char* amd_str = "AuthenticAMD";
00099       int amd_sz = strlen(amd_str);
00100       const char* intel_str = "GenuineIntel";
00101       int intel_sz = strlen(intel_str);
00102     
00103       char* str = (char*)&ans[0];
00104       ans[3]=0;
00105 
00106       return strncmp(str,amd_str,amd_sz)==0?AMD_CPU:
00107         strncmp(str,intel_str,intel_sz)==0?INTEL_CPU:UNKNOWN_CPU;
00108     }
00109 
00110     // values determined experimentally for each architecture
00111     const MallocOpts intel_opts(262144, 524288, 5242880, 131072);
00112     const MallocOpts amd_opts(0, 8388608, 131072, 10485760);
00113 
00114   }
00115 
00116 
00117   bool MallocOptionSetter::retrieveFromCpuType()
00118   {
00119     bool rc=true;
00120 
00121     switch(get_cpu_type())
00122       {
00123       case AMD_CPU:
00124         {
00125           values_ = amd_opts;
00126           changed_=true;
00127           break;
00128         }
00129       case INTEL_CPU:
00130         {
00131           values_ = intel_opts;
00132           changed_=true;
00133           break;
00134         }
00135       case UNKNOWN_CPU:
00136       default:
00137         rc=false;
00138       }
00139 
00140     return rc;
00141   }
00142 
00143   MallocOptionSetter::MallocOptionSetter():
00144     changed_(false)
00145   {
00146     if(retrieveFromEnv() || retrieveFromCpuType())
00147       {
00148         adjustMallocParams();
00149         if(hasErrors())
00150           {
00151             std::cerr << "ERROR: Reset of malloc options has fails:\n"
00152                       << error_message_ << "\n";
00153           }
00154       }
00155   }
00156 
00157   void MallocOptionSetter::adjustMallocParams()
00158   {
00159     if(changed_==false) return; // only adjust if they changed
00160     error_message_.clear();
00161     changed_ = false;
00162 
00163 #ifdef M_MMAP_MAX
00164     if(mallopt(M_MMAP_MAX,values_.mmap_max_)<0)
00165       error_message_ += "Could not set M_MMAP_MAX\n"; 
00166 #endif
00167 #ifdef M_TRIM_THRESHOLD
00168     if(mallopt(M_TRIM_THRESHOLD,values_.trim_thr_)<0)
00169       error_message_ += "Could not set M_TRIM_THRESHOLD\n"; 
00170 #endif
00171 #ifdef M_TOP_PAD
00172     if(mallopt(M_TOP_PAD,values_.top_pad_)<0)
00173       error_message_ += "ERROR: Could not set M_TOP_PAD\n";
00174 #endif
00175 #ifdef M_MMAP_THRESHOLD
00176     if(mallopt(M_MMAP_THRESHOLD,values_.mmap_thr_)<0)
00177       error_message_ += "ERROR: Could not set M_MMAP_THRESHOLD\n";
00178 #endif
00179   }
00180 
00181   bool MallocOptionSetter::retrieveFromEnv()
00182   {
00183     const char* par = getenv("CMSRUN_MALLOC_RESET");
00184     if(par==0) return false; // leave quickly here
00185     std::string spar(par);
00186     bool rc = false;
00187       
00188     // CMSRUN_MALLOC_RESET = "mmap_max trim_thres top_pad mmap_thres"
00189       
00190     if(spar.size()>1)
00191       {
00192         std::istringstream ist(spar);
00193         ist >> values_.mmap_max_ >> values_.trim_thr_
00194             >> values_.top_pad_ >> values_.mmap_thr_;
00195 
00196         if(ist.bad())
00197           {
00198             std::cerr << "bad malloc options in CMSRUN_MALLOC_RESET: "
00199                       << spar << "\n"
00200                       << "format is: "
00201                       << "CMSRUN_MALLOC_RESET=\"mmap_max trim_thres top_pad mmap_thres\"\n";
00202           }
00203         else
00204           {
00205             std::cout << "MALLOC_OPTIONS> Reset options: "
00206                       << "CMSRUN_MALLOC_RESET=" << par << "\n";
00207           }
00208         rc=true;
00209         changed_=true;
00210       }
00211 
00212     return rc;
00213   }
00214 
00215   MallocOptionSetter global_malloc_options;
00216 
00217   MallocOptionSetter& getGlobalOptionSetter()
00218   {
00219     return global_malloc_options;
00220   }
00221 
00222 
00223   // ----------------------------------------------------------------
00224 }