00001
00002
00003 #include "osl/oslConfig.h"
00004 #include "osl/config.h"
00005 #include "osl/misc/ncores.h"
00006 #include <map>
00007 #include <boost/filesystem/operations.hpp>
00008 #include <boost/static_assert.hpp>
00009 #include <limits>
00010 #include <iostream>
00011 #include <fstream>
00012 #include <cstdlib>
00013 #ifndef _MSC_VER
00014 # include <unistd.h>
00015 #endif
00016 #ifdef _WIN32
00017 # include <windows.h>
00018 # include <psapi.h>
00019 #else
00020 #include <sys/resource.h>
00021 #ifdef __FreeBSD__
00022 # include <kvm.h>
00023 # include <sys/param.h>
00024 # include <sys/sysctl.h>
00025 # include <sys/user.h>
00026 # include <paths.h>
00027 # include <fcntl.h>
00028 #endif
00029 #ifdef __APPLE__
00030 # include <sys/types.h>
00031 # include <sys/sysctl.h>
00032 # include <mach/task.h>
00033 # include <mach/mach_init.h>
00034 #endif
00035 #endif
00036
00037 const int osl::OslConfig::MaxThreads;
00038 unsigned int osl::OslConfig::eval_random = 0;
00039
00040 bool osl::OslConfig::is_verbose = false;
00041 #ifndef OSL_NCPUS
00042 const int osl::OslConfig::default_ncpus = osl::misc::ncores();
00043 #else
00044 BOOST_STATIC_ASSERT(OSL_NCPUS <= osl::OslConfig::MaxThreads);
00045 const int osl::OslConfig::default_ncpus = OSL_NCPUS;
00046 #endif
00047 int osl::OslConfig::num_cpu = default_ncpus;
00048 volatile bool osl::OslConfig::usi_mode = false,
00049 osl::OslConfig::usi_mode_silent = false,
00050 osl::OslConfig::use_log_linear_probability = false,
00051 osl::OslConfig::force_root_null_window = false;
00052 int osl::OslConfig::usi_output_pawn_value = 100;
00053 volatile int osl::OslConfig::root_null_window = 0;
00054 boost::mutex osl::OslConfig::lock_io;
00055
00056 namespace
00057 {
00058 size_t system_memory_use_limit()
00059 {
00060 #ifdef _WIN32
00061 MEMORYSTATUSEX statex;
00062 statex.dwLength = sizeof(statex);
00063 GlobalMemoryStatusEx(&statex);
00064 return statex.ullTotalPhys;
00065 #else
00066 size_t limit_by_rlimit = std::numeric_limits<size_t>::max();
00067 {
00068 rlimit rlp;
00069 if (getrlimit(RLIMIT_AS, &rlp) == 0
00070 && rlp.rlim_cur != std::numeric_limits<rlim_t>::max()) {
00071 limit_by_rlimit = rlp.rlim_cur;
00072 #ifdef __APPLE__
00073 limit_by_rlimit *= 1024;
00074 #endif
00075 std::cerr << "rlimit " << limit_by_rlimit << "\n";
00076 }
00077 }
00078 #ifdef __APPLE__
00079 {
00080 int mib[2];
00081 unsigned int usermem;
00082 size_t len=sizeof(usermem);
00083 mib[0] = CTL_HW;
00084 mib[1] = HW_USERMEM;
00085 if (sysctl(mib, 2, &usermem, &len, NULL, 0) == 0
00086 && len == sizeof(usermem)) {
00087 std::cerr << "usermem " << usermem << std::endl;
00088 return std::min((size_t)usermem, limit_by_rlimit);
00089 }
00090 }
00091 #endif
00092 {
00093 std::string name, unit;
00094 size_t value;
00095 std::ifstream is("/proc/meminfo");
00096 if (is >> name >> value >> unit
00097 && name == "MemTotal:" && unit == "kB")
00098 return std::min(value * 1024, limit_by_rlimit);
00099 }
00100 #if (defined __FreeBSD__)
00101 const long mem = sysconf(_SC_PHYS_PAGES);
00102 if (mem != -1)
00103 return std::min(mem * getpagesize(), limit_by_rlimit);
00104 #endif
00105 return std::min((rlim_t)limit_by_rlimit, std::numeric_limits<rlim_t>::max());
00106 #endif
00107 }
00108 }
00109
00110 size_t osl::OslConfig::memory_use_limit = system_memory_use_limit();
00111 const size_t osl::OslConfig::memory_use_limit_system_max =
00112 #ifdef _WIN32
00113 3000000000;
00114 #else
00115 std::numeric_limits<rlim_t>::max();
00116 #endif
00117
00118 void osl::OslConfig::setNumCPUs(int ncpu)
00119 {
00120 if (ncpu > MaxThreads) {
00121 std::cerr << "ncpu " << ncpu << " > " << "MaxThreads " << MaxThreads << "\n";
00122 ncpu = MaxThreads;
00123 }
00124 num_cpu = ncpu;
00125 }
00126
00127 int osl::OslConfig::numCPUs()
00128 {
00129 return num_cpu;
00130 }
00131
00132 void osl::OslConfig::setVerbose(bool v)
00133 {
00134 is_verbose = v;
00135 }
00136
00137 bool osl::OslConfig::verbose()
00138 {
00139 return is_verbose;
00140 }
00141
00142 bool osl::OslConfig::usiMode()
00143 {
00144 return usi_mode;
00145 }
00146 void osl::OslConfig::setUsiMode(bool enable)
00147 {
00148 usi_mode = enable;
00149 }
00150 bool osl::OslConfig::usiModeInSilent()
00151 {
00152 return usi_mode_silent;
00153 }
00154 void osl::OslConfig::setUsiSilent(bool enable)
00155 {
00156 usi_mode_silent = enable;
00157 }
00158
00159 bool osl::OslConfig::useLogLinearProbability()
00160 {
00161 static bool fixed_use_log_linear_probability
00162 = use_log_linear_probability || getenv("OSL_USE_LOG_LINEAR_PROBABILITY");
00163 return fixed_use_log_linear_probability;
00164 }
00165 void osl::OslConfig::enableLogLinearProbability(bool enabled)
00166 {
00167 use_log_linear_probability = enabled;
00168 }
00169
00170 void osl::OslConfig::showOslHome(const std::string& home)
00171 {
00172 std::cerr << "using " << home << " as OSL_HOME, word size "
00173 << OSL_WORDSIZE << std::endl;
00174 }
00175
00176 void osl::OslConfig::showOslHome()
00177 {
00178 showOslHome(home());
00179 }
00180
00181 bool osl::OslConfig::isGoodDir(const std::string& dir)
00182 {
00183 return boost::filesystem::exists(dir)
00184 && boost::filesystem::is_directory(dir);
00185 }
00186
00187 void osl::OslConfig::trySetDir(std::string& dir, const std::string& candidate)
00188 {
00189 if (isGoodDir(candidate))
00190 {
00191 dir = candidate;
00192 return;
00193 }
00194 if (verbose())
00195 std::cerr << "skipping " << candidate << std::endl;
00196 }
00197
00198 const std::string osl::OslConfig::makeHome()
00199 {
00200 std::string result;
00201 if (const char *env = getenv("GPSSHOGI_HOME"))
00202 trySetDir(result, env);
00203
00204 #if defined GPSSHOGI_HOME
00205 if (result.empty())
00206 trySetDir(result, GPSSHOGI_HOME);
00207 #endif
00208
00209 if (result.empty())
00210 if (const char *env = getenv("OSL_HOME"))
00211 trySetDir(result, env);
00212
00213 if (result.empty())
00214 result = OSL_HOME;
00215
00216 if (verbose())
00217 showOslHome(result);
00218 return result;
00219 }
00220
00221 const std::string& osl::OslConfig::home()
00222 {
00223 static const std::string home_directory = makeHome();
00224 return home_directory;
00225 }
00226
00227 const char * osl::OslConfig::home_c_str()
00228 {
00229 return home().c_str();
00230 }
00231
00232 const std::string osl::OslConfig::gpsusiConf()
00233 {
00234
00235
00236
00237 #ifdef OSL_PUBLIC_RELEASE
00238
00239 if (const char *env = getenv("HOME"))
00240 return std::string(env) + "/gpsusi.conf";
00241 if (const char *env = getenv("USERPROFILE"))
00242 return std::string(env) + "/gpsusi.conf";
00243 #endif
00244
00245 static const std::string home_directory = makeHome();
00246 return home_directory + "/gpsusi.conf";
00247 }
00248
00249 const std::string osl::OslConfig::makeTest()
00250 {
00251 std::string result;
00252 if (const char *env = getenv("OSL_TEST"))
00253 trySetDir(result, env);
00254
00255 if (result.empty())
00256 result = home() + "/data";
00257
00258 std::cerr << "using " << result << " as OSL_TEST" << std::endl;
00259 return result;
00260 }
00261
00262 const std::string osl::OslConfig::test()
00263 {
00264 static const std::string test_directory = makeTest();
00265 return test_directory;
00266 }
00267
00268 namespace
00269 {
00270 struct NameHolder : std::map<std::string,std::string>
00271 {
00272 std::string directory;
00273
00274 NameHolder(const std::string& d) : directory(d)
00275 {
00276 directory += "/";
00277 }
00278
00279 iterator add(const std::string& key, const std::string& value)
00280 {
00281 return insert(std::make_pair(key, value)).first;
00282 }
00283 iterator addRelative(const std::string& key, const std::string& filename)
00284 {
00285 std::string value = directory + filename;
00286 return add(key, value);
00287 }
00288 iterator addRelative(const std::string& filename)
00289 {
00290 return addRelative(filename, filename);
00291 }
00292 };
00293 }
00294
00295 const char * osl::OslConfig::testFile(const std::string& filename)
00296 {
00297 static NameHolder table(test());
00298 NameHolder::iterator p=table.find(filename);
00299 if (p == table.end()) {
00300 p = table.addRelative(filename);
00301 }
00302 return p->second.c_str();
00303 }
00304
00305 const char * osl::OslConfig::testCsaFile(const std::string& filename)
00306 {
00307 static NameHolder table(test()+"/kifdat");
00308 NameHolder::iterator p=table.find(filename);
00309 if (p == table.end()) {
00310 p = table.addRelative(filename);
00311 }
00312 return p->second.c_str();
00313 }
00314
00315 const char *osl::OslConfig::openingBook(const std::string& filename)
00316 {
00317 static NameHolder table(home()+"/data");
00318 NameHolder::iterator p=table.find(filename);
00319 if (p == table.end()) {
00320 if (! filename.empty() && filename[0] == '/') {
00321
00322 p = table.add(filename, filename);
00323 }
00324 else {
00325
00326 p = table.addRelative(filename,
00327 (filename == "" ? "joseki.dat" : filename));
00328 }
00329 }
00330 return p->second.c_str();
00331 }
00332
00333
00334 size_t osl::OslConfig::residentMemoryUse()
00335 {
00336 #if defined(_WIN32)
00337 static const DWORD process_id = GetCurrentProcessId();
00338 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
00339 FALSE, process_id);
00340 if (NULL == hProcess)
00341 {
00342 std::cerr << "Failed to get residentMemoryUse()\n";
00343 return 0;
00344 }
00345
00346 size_t working_set = 0;
00347 PROCESS_MEMORY_COUNTERS pmc;
00348 if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
00349 working_set = pmc.WorkingSetSize;
00350 }
00351 CloseHandle(hProcess);
00352 return working_set;
00353 #else
00354
00355
00356 std::ifstream is("/proc/self/statm");
00357 size_t total, resident;
00358 if (is >> total >> resident)
00359 return resident*getpagesize();
00360 #ifdef __APPLE__
00361 mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
00362 task_basic_info_64 ti;
00363 if (task_info(current_task(), TASK_BASIC_INFO_64, (task_info_t)&ti, &count)
00364 == KERN_SUCCESS)
00365 return ti.resident_size;
00366 #endif
00367 #ifdef __FreeBSD__
00368 static kvm_t *kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "osl kvm_open");
00369 int nproc;
00370 kinfo_proc *pp = kvm_getprocs(kd, KERN_PROC_PID, getpid(), &nproc);
00371 if (pp)
00372 return pp->ki_rssize * getpagesize();
00373 #endif
00374 #endif
00375 return 0;
00376 }
00377
00378
00379
00380
00381
00382