oslConfig.cc
Go to the documentation of this file.
00001 /* oslConfig.cc
00002  */
00003 #include "osl/oslConfig.h"
00004 #include "osl/config.h"
00005 #include "osl/misc/ncores.h"
00006 #include "osl/eval/ml/openMidEndingEval.h"
00007 #include "osl/progress/ml/newProgress.h"
00008 #include <map>
00009 #include <boost/filesystem/operations.hpp>
00010 #include <boost/static_assert.hpp>
00011 #include <limits>
00012 #include <iostream>
00013 #include <fstream>
00014 #include <cstdlib>
00015 #ifndef _MSC_VER
00016 #  include <unistd.h>
00017 #endif
00018 #ifdef _WIN32
00019 #  include <windows.h>
00020 #  include <psapi.h>
00021 #else
00022 #include <sys/resource.h>
00023 #ifdef __FreeBSD__
00024 #  include <kvm.h>
00025 #  include <sys/param.h>
00026 #  include <sys/sysctl.h>
00027 #  include <sys/user.h>
00028 #  include <paths.h>
00029 #  include <fcntl.h>
00030 #endif
00031 #ifdef __APPLE__
00032 #  include <sys/types.h>
00033 #  include <sys/sysctl.h>
00034 #  include <mach/task.h>
00035 #  include <mach/mach_init.h>
00036 #endif
00037 #endif
00038 
00039 const int osl::OslConfig::MaxThreads; // define
00040 unsigned int osl::OslConfig::eval_random = 0;
00041 
00042 bool osl::OslConfig::is_verbose = false;
00043 #ifndef OSL_NCPUS
00044 const int osl::OslConfig::default_ncpus = osl::misc::ncores();
00045 #else
00046 BOOST_STATIC_ASSERT(OSL_NCPUS <= osl::OslConfig::MaxThreads);
00047 const int osl::OslConfig::default_ncpus = OSL_NCPUS;
00048 #endif
00049 int osl::OslConfig::num_cpu = default_ncpus;
00050 volatile bool osl::OslConfig::usi_mode = false, 
00051   osl::OslConfig::usi_mode_silent = false, 
00052   osl::OslConfig::force_root_window = false;
00053 int osl::OslConfig::usi_output_pawn_value = 100; 
00054 volatile int osl::OslConfig::root_window_alpha = 0; 
00055 volatile int osl::OslConfig::root_window_beta = 0; 
00056 volatile int osl::OslConfig::in_unit_test = 0;
00057 bool osl::OslConfig::search_exact_value_in_one_reply = false;
00058 bool osl::OslConfig::has_byoyomi = false;
00059 boost::mutex osl::OslConfig::lock_io;
00060 
00061 namespace
00062 {
00063   size_t system_memory_use_limit() 
00064   {
00065 #ifdef _WIN32
00066     MEMORYSTATUSEX statex;
00067     statex.dwLength = sizeof(statex);
00068     GlobalMemoryStatusEx(&statex);
00069     return statex.ullTotalPhys; // in bytes
00070 #else
00071     size_t limit_by_rlimit = std::numeric_limits<size_t>::max();
00072     {
00073       rlimit rlp;
00074       if (getrlimit(RLIMIT_AS, &rlp) == 0
00075           && rlp.rlim_cur != std::numeric_limits<rlim_t>::max()) {
00076         limit_by_rlimit = rlp.rlim_cur;
00077 #ifdef __APPLE__
00078         limit_by_rlimit *= 1024;
00079 #endif
00080         std::cerr << "rlimit " << limit_by_rlimit << "\n";
00081       }
00082     }
00083 #ifdef __APPLE__
00084     {
00085       int mib[2];
00086       unsigned int usermem;
00087       size_t len=sizeof(usermem);
00088       mib[0] = CTL_HW;
00089       mib[1] = HW_USERMEM;
00090       if (sysctl(mib, 2, &usermem, &len, NULL, 0) == 0
00091           && len == sizeof(usermem)) {
00092         std::cerr << "usermem " << usermem << std::endl;
00093         return std::min((size_t)usermem, limit_by_rlimit);
00094       }
00095     }
00096 #endif
00097     {
00098       std::string name, unit;
00099       size_t value;
00100       std::ifstream is("/proc/meminfo");
00101       if (is >> name >> value >> unit
00102           && name == "MemTotal:" && unit == "kB")
00103         return std::min(value * 1024, limit_by_rlimit);
00104     }
00105 #if (defined __FreeBSD__)
00106     const long mem = sysconf(_SC_PHYS_PAGES);
00107     if (mem != -1) 
00108       return std::min(mem * getpagesize(), limit_by_rlimit);
00109 #endif
00110     return std::min((rlim_t)limit_by_rlimit, std::numeric_limits<rlim_t>::max());
00111 #endif
00112   }
00113 }
00114 
00115 size_t osl::OslConfig::memory_use_limit = system_memory_use_limit();
00116 const size_t osl::OslConfig::memory_use_limit_system_max = 
00117 #ifdef _WIN32
00118   3000000000; // 3GB
00119 #else
00120   std::numeric_limits<rlim_t>::max();
00121 #endif
00122 double osl::OslConfig::memory_use_percent = 100.0;
00123 
00124 void osl::OslConfig::setNumCPUs(int ncpu)
00125 {
00126   if (ncpu > MaxThreads) {
00127     std::cerr << "ncpu " << ncpu << " > " << "MaxThreads " << MaxThreads << "\n";
00128     ncpu = MaxThreads;
00129   }
00130   num_cpu = ncpu;
00131 }
00132 
00133 int osl::OslConfig::numCPUs()
00134 {
00135   return num_cpu;
00136 }
00137 
00138 void osl::OslConfig::setVerbose(bool v)
00139 {
00140   is_verbose = v;
00141 }
00142 
00143 bool osl::OslConfig::verbose()
00144 {
00145   return is_verbose;
00146 }
00147 
00148 bool osl::OslConfig::usiMode()
00149 {
00150   return usi_mode;
00151 }
00152 void osl::OslConfig::setUsiMode(bool enable)
00153 {
00154   usi_mode = enable;
00155 }
00156 bool osl::OslConfig::usiModeInSilent()
00157 {
00158   return usi_mode_silent;
00159 }
00160 void osl::OslConfig::setUsiSilent(bool enable)
00161 {
00162   usi_mode_silent = enable;
00163 }
00164 bool osl::OslConfig::searchExactValueInOneReply()
00165 {
00166   return search_exact_value_in_one_reply;
00167 }
00168 void osl::OslConfig::setSearchExactValueInOneReply(bool enable)
00169 {
00170   search_exact_value_in_one_reply = enable;
00171 }
00172 
00173 bool osl::OslConfig::hasByoyomi()
00174 {
00175   return has_byoyomi;
00176 }
00177 
00178 void osl::OslConfig::setHasByoyomi(bool value)
00179 {
00180   has_byoyomi = value;
00181 }
00182 
00183 void osl::OslConfig::showOslHome(const std::string& home)
00184 {
00185   std::cerr << "using " << home << " as OSL_HOME, word size "
00186             << OSL_WORDSIZE << std::endl;
00187 }
00188 
00189 void osl::OslConfig::showOslHome()
00190 {
00191   showOslHome(home());
00192 }
00193 
00194 bool osl::OslConfig::isGoodDir(const std::string& dir)
00195 {
00196   return boost::filesystem::exists(dir)
00197     && boost::filesystem::is_directory(dir);
00198 }
00199 
00200 void osl::OslConfig::trySetDir(std::string& dir, const std::string& candidate)
00201 {
00202   if (isGoodDir(candidate))
00203   {
00204     dir = candidate;
00205     return;
00206   }
00207   if (verbose())
00208     std::cerr << "skipping " << candidate << std::endl;
00209 }
00210 
00211 const std::string osl::OslConfig::makeHome()
00212 {
00213   std::string result;
00214   if (const char *env = getenv("GPSSHOGI_HOME"))
00215     trySetDir(result, env);
00216   
00217 #if defined GPSSHOGI_HOME
00218   if (result.empty())
00219     trySetDir(result, GPSSHOGI_HOME);
00220 #endif
00221 
00222   if (result.empty())
00223     if (const char *env = getenv("OSL_HOME"))
00224       trySetDir(result, env);
00225 
00226   if (result.empty())
00227     result = OSL_HOME;
00228 
00229   if (verbose())
00230     showOslHome(result);
00231   return result;
00232 }
00233 
00234 const std::string& osl::OslConfig::home()
00235 {
00236   static const std::string home_directory = makeHome();
00237   return home_directory;
00238 }
00239 
00240 const char * osl::OslConfig::home_c_str()
00241 {
00242   return home().c_str();
00243 }
00244 
00245 const std::string osl::OslConfig::gpsusiConf()
00246 {
00247   // issue:
00248   // - 開発者には $HOME ではなく OSL_HOME の方が使い分ける都合が良い
00249   // - 一方、配布版では OSL_HOME は共有ディレクトリで書き込めないかもしれない
00250 #ifdef OSL_PUBLIC_RELEASE
00251   // for personal users
00252   if (const char *env = getenv("HOME"))
00253     return std::string(env) + "/gpsusi.conf";
00254   if (const char *env = getenv("USERPROFILE"))
00255     return std::string(env) + "/gpsusi.conf";
00256 #endif
00257   // for developpers
00258   static const std::string home_directory = makeHome();
00259   return home_directory + "/gpsusi.conf";
00260 }
00261 
00262 const std::string osl::OslConfig::makeTest()
00263 {
00264   std::string result;
00265   if (const char *env = getenv("OSL_TEST"))
00266     trySetDir(result, env);
00267 
00268   if (result.empty())
00269     result = home() + "/data";  // 今はdata内に混在
00270 
00271   std::cerr << "using " << result << " as OSL_TEST" << std::endl;
00272   return result;
00273 }
00274 
00275 const std::string osl::OslConfig::makeTestPublic()
00276 {
00277   std::string result;
00278   if (const char *env = getenv("OSL_TEST_PUBLIC"))
00279     trySetDir(result, env);
00280 
00281   if (result.empty())
00282     result = home() + "/public-domain";
00283 
00284   std::cerr << "using " << result << " as OSL_TEST_PUBLIC" << std::endl;
00285   return result;
00286 }
00287 
00288 const std::string osl::OslConfig::testPrivate()
00289 {
00290   static const std::string test_directory = makeTest();
00291   return test_directory;
00292 }
00293 
00294 const std::string osl::OslConfig::testPublic()
00295 {
00296   static const std::string test_directory = makeTestPublic();
00297   return test_directory;
00298 }
00299 
00300 namespace 
00301 {
00302   struct NameHolder : std::map<std::string,std::string>
00303   {
00304     std::string directory;
00305 
00306     NameHolder(const std::string& d) : directory(d)
00307     {
00308       directory += "/";
00309     }
00310 
00311     iterator add(const std::string& key, const std::string& value)
00312     {
00313       return insert(std::make_pair(key, value)).first;
00314     }
00315     iterator addRelative(const std::string& key, const std::string& filename)
00316     {
00317       std::string value = directory + filename;
00318       return add(key, value);
00319     }
00320     iterator addRelative(const std::string& filename)
00321     {
00322       return addRelative(filename, filename);
00323     }
00324   };
00325 }
00326 
00327 const char * osl::OslConfig::testPrivateFile(const std::string& filename)
00328 {
00329   static NameHolder table(testPrivate());
00330   NameHolder::iterator p=table.find(filename);
00331   if (p == table.end()) {
00332     p = table.addRelative(filename);
00333   }
00334   return p->second.c_str();
00335 }
00336 
00337 const char * osl::OslConfig::testPublicFile(const std::string& filename)
00338 {
00339   static NameHolder table(testPublic());
00340   NameHolder::iterator p=table.find(filename);
00341   if (p == table.end()) {
00342     p = table.addRelative(filename);
00343   }
00344   return p->second.c_str();
00345 }
00346 
00347 const char * osl::OslConfig::testCsaFile(const std::string& filename)
00348 {
00349   static NameHolder table(testPublic()+"/floodgate2010");
00350   NameHolder::iterator p=table.find(filename);
00351   if (p == table.end()) {
00352     p = table.addRelative(filename);
00353   }
00354   return p->second.c_str();
00355 }
00356 
00357 const char *osl::OslConfig::openingBook(const std::string& filename)
00358 {
00359   static NameHolder table(home()+"/data");
00360   NameHolder::iterator p=table.find(filename);
00361   if (p == table.end()) {
00362     if (! filename.empty() && filename[0] == '/') {
00363       // absolute path
00364       p = table.add(filename, filename);
00365     }
00366     else {
00367       // relative path
00368       p = table.addRelative(filename, 
00369                             (filename == "" ? "joseki.dat" : filename));
00370     }
00371   }
00372   return p->second.c_str();
00373 }
00374 
00375 
00376 size_t osl::OslConfig::residentMemoryUse()
00377 {
00378 #if defined(_WIN32)
00379   static const DWORD process_id = GetCurrentProcessId();
00380   HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
00381                                 FALSE, process_id);
00382   if (NULL == hProcess)
00383   {
00384     std::cerr << "Failed to get residentMemoryUse()\n";
00385     return 0;
00386   }
00387 
00388   size_t working_set = 0;
00389   PROCESS_MEMORY_COUNTERS pmc;
00390   if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
00391     working_set = pmc.WorkingSetSize; // in bytes
00392   }
00393   CloseHandle(hProcess);
00394   return working_set;
00395 #else
00396   // see proc(5)
00397   // note: < 40000 cycles @macpro2
00398   std::ifstream is("/proc/self/statm");
00399   size_t total, resident;
00400   if (is >> total >> resident)
00401     return resident*getpagesize();
00402 #ifdef __APPLE__
00403   mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
00404   task_basic_info_64 ti;
00405   if (task_info(current_task(), TASK_BASIC_INFO_64, (task_info_t)&ti, &count)
00406       == KERN_SUCCESS)
00407     return ti.resident_size;
00408 #endif
00409 #ifdef __FreeBSD__
00410   static kvm_t *kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "osl kvm_open");
00411   int nproc;
00412   kinfo_proc *pp = kvm_getprocs(kd, KERN_PROC_PID, getpid(), &nproc);
00413   if (pp)
00414     return pp->ki_rssize * getpagesize();
00415 #endif  
00416 #endif
00417   return 0;
00418 }
00419 
00420 #ifndef DFPNSTATONE
00421 void osl::OslConfig::setUp()
00422 {
00423   eval::ml::OpenMidEndingEval::setUp();
00424   progress::ml::NewProgress::setUp();
00425 }
00426 #endif
00427 
00428 /* ------------------------------------------------------------------------- */
00429 // ;;; Local Variables:
00430 // ;;; mode:c++
00431 // ;;; c-basic-offset:2
00432 // ;;; End:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines