00001
00002
00003 #include "osl/oslConfig.h"
00004 #include "osl/config.h"
00005 #include "osl/eval/openMidEndingEval.h"
00006 #include "osl/progress.h"
00007 #include <boost/filesystem/operations.hpp>
00008 #include <map>
00009 #include <limits>
00010 #include <iostream>
00011 #include <fstream>
00012 #include <cstdlib>
00013 #include <thread>
00014 #ifndef _MSC_VER
00015 # include <unistd.h>
00016 #endif
00017 #ifdef _WIN32
00018 # include <windows.h>
00019 # include <psapi.h>
00020 #else
00021 #include <sys/resource.h>
00022 #ifdef __FreeBSD__
00023 # include <kvm.h>
00024 # include <sys/param.h>
00025 # include <sys/sysctl.h>
00026 # include <sys/user.h>
00027 # include <paths.h>
00028 # include <fcntl.h>
00029 #endif
00030 #ifdef __APPLE__
00031 # include <sys/types.h>
00032 # include <sys/sysctl.h>
00033 # include <mach/task.h>
00034 # include <mach/mach_init.h>
00035 #endif
00036 #endif
00037
00038 const int osl::OslConfig::MaxThreads;
00039 unsigned int osl::OslConfig::eval_random = 0;
00040
00041 bool osl::OslConfig::is_verbose = false;
00042 #ifndef OSL_NCPUS
00043 const int osl::OslConfig::default_ncpus = std::thread::hardware_concurrency();
00044 #else
00045 static_assert(OSL_NCPUS <= osl::OslConfig::MaxThreads, "#threads");
00046 const int osl::OslConfig::default_ncpus = OSL_NCPUS;
00047 #endif
00048 int osl::OslConfig::num_cpu = default_ncpus;
00049 volatile osl::OslConfig::UsiMode osl::OslConfig::usi_mode = osl::OslConfig::NoUSI;
00050 volatile bool osl::OslConfig::usi_mode_silent = false,
00051 osl::OslConfig::force_root_window = false;
00052 int osl::OslConfig::usi_output_pawn_value = 100;
00053 volatile int osl::OslConfig::root_window_alpha = 0;
00054 volatile int osl::OslConfig::root_window_beta = 0;
00055 volatile int osl::OslConfig::in_unit_test = 0;
00056 int osl::OslConfig::dfpn_max_depth = 256;
00057 bool osl::OslConfig::search_exact_value_in_one_reply = false;
00058 bool osl::OslConfig::has_byoyomi = false;
00059 std::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;
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;
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::concurrency()
00134 {
00135 if (num_cpu > MaxThreads)
00136 std::cerr << "ncpu " << num_cpu << " > " << "MaxThreads " << MaxThreads << "\n";
00137 return std::min(num_cpu, MaxThreads);
00138 }
00139
00140 void osl::OslConfig::setVerbose(bool v)
00141 {
00142 is_verbose = v;
00143 }
00144
00145 bool osl::OslConfig::verbose()
00146 {
00147 return is_verbose;
00148 }
00149
00150 osl::OslConfig::UsiMode osl::OslConfig::usiMode()
00151 {
00152 return usi_mode;
00153 }
00154 void osl::OslConfig::setUsiMode(UsiMode enable)
00155 {
00156 usi_mode = enable;
00157 }
00158 bool osl::OslConfig::usiModeInSilent()
00159 {
00160 return usi_mode_silent;
00161 }
00162 void osl::OslConfig::setUsiSilent(bool enable)
00163 {
00164 usi_mode_silent = enable;
00165 }
00166 bool osl::OslConfig::searchExactValueInOneReply()
00167 {
00168 return search_exact_value_in_one_reply;
00169 }
00170 void osl::OslConfig::setSearchExactValueInOneReply(bool enable)
00171 {
00172 search_exact_value_in_one_reply = enable;
00173 }
00174
00175 bool osl::OslConfig::hasByoyomi()
00176 {
00177 return has_byoyomi;
00178 }
00179
00180 void osl::OslConfig::setHasByoyomi(bool value)
00181 {
00182 has_byoyomi = value;
00183 }
00184
00185 void osl::OslConfig::showOslHome(const std::string& home)
00186 {
00187 std::cerr << "using " << home << " as OSL_HOME, word size "
00188 << OSL_WORDSIZE << std::endl;
00189 }
00190
00191 void osl::OslConfig::showOslHome()
00192 {
00193 showOslHome(home());
00194 }
00195
00196 bool osl::OslConfig::isGoodDir(const std::string& dir)
00197 {
00198 return boost::filesystem::exists(dir)
00199 && boost::filesystem::is_directory(dir);
00200 }
00201
00202 void osl::OslConfig::trySetDir(std::string& dir, const std::string& candidate)
00203 {
00204 if (isGoodDir(candidate))
00205 {
00206 dir = candidate;
00207 return;
00208 }
00209 if (verbose())
00210 std::cerr << "skipping " << candidate << std::endl;
00211 }
00212
00213 const std::string osl::OslConfig::makeHome(const std::string& first_try)
00214 {
00215 std::string result;
00216 if (first_try != "")
00217 trySetDir(result, first_try);
00218
00219 if (const char *env = getenv("GPSSHOGI_HOME"))
00220 trySetDir(result, env);
00221
00222 #if defined GPSSHOGI_HOME
00223 if (result.empty())
00224 trySetDir(result, GPSSHOGI_HOME);
00225 #endif
00226
00227 if (result.empty())
00228 if (const char *env = getenv("OSL_HOME"))
00229 trySetDir(result, env);
00230
00231 if (result.empty())
00232 result = OSL_HOME;
00233
00234 if (verbose())
00235 showOslHome(result);
00236 return result;
00237 }
00238
00239 const std::string& osl::OslConfig::home(const std::string& init)
00240 {
00241 static const std::string home_directory = makeHome(init);
00242 return home_directory;
00243 }
00244
00245 const char * osl::OslConfig::home_c_str()
00246 {
00247 return home().c_str();
00248 }
00249
00250 const std::string osl::OslConfig::gpsusiConf()
00251 {
00252
00253
00254
00255 #ifdef OSL_PUBLIC_RELEASE
00256
00257 if (const char *env = getenv("HOME"))
00258 return std::string(env) + "/gpsusi.conf";
00259 if (const char *env = getenv("USERPROFILE"))
00260 return std::string(env) + "/gpsusi.conf";
00261 #endif
00262
00263 static const std::string home_directory = makeHome();
00264 return home_directory + "/gpsusi.conf";
00265 }
00266
00267 int osl::OslConfig::resignThreshold()
00268 {
00269 static const int value = getenv("OSL_RESIGN_VALUE")
00270 ? atoi(getenv("OSL_RESIGN_VALUE")) : 0;
00271 return (value > 0) ? value : 10000;
00272 }
00273
00274 const std::string osl::OslConfig::makeTest()
00275 {
00276 std::string result;
00277 if (const char *env = getenv("OSL_TEST"))
00278 trySetDir(result, env);
00279
00280 if (result.empty())
00281 result = home() + "/data";
00282
00283 std::cerr << "using " << result << " as OSL_TEST" << std::endl;
00284 return result;
00285 }
00286
00287 const std::string osl::OslConfig::makeTestPublic()
00288 {
00289 std::string result;
00290 if (const char *env = getenv("OSL_TEST_PUBLIC"))
00291 trySetDir(result, env);
00292
00293 if (result.empty())
00294 result = home() + "/public-data";
00295
00296 std::cerr << "using " << result << " as OSL_TEST_PUBLIC" << std::endl;
00297 return result;
00298 }
00299
00300 const std::string osl::OslConfig::testPrivate()
00301 {
00302 static const std::string test_directory = makeTest();
00303 return test_directory;
00304 }
00305
00306 const std::string osl::OslConfig::testPublic()
00307 {
00308 static const std::string test_directory = makeTestPublic();
00309 return test_directory;
00310 }
00311
00312 namespace
00313 {
00314 struct NameHolder : std::map<std::string,std::string>
00315 {
00316 std::string directory;
00317
00318 NameHolder(const std::string& d) : directory(d)
00319 {
00320 directory += "/";
00321 }
00322
00323 iterator add(const std::string& key, const std::string& value)
00324 {
00325 return insert(std::make_pair(key, value)).first;
00326 }
00327 iterator addRelative(const std::string& key, const std::string& filename)
00328 {
00329 std::string value = directory + filename;
00330 return add(key, value);
00331 }
00332 iterator addRelative(const std::string& filename)
00333 {
00334 return addRelative(filename, filename);
00335 }
00336 };
00337 }
00338
00339 const char * osl::OslConfig::testPrivateFile(const std::string& filename)
00340 {
00341 static NameHolder table(testPrivate());
00342 NameHolder::iterator p=table.find(filename);
00343 if (p == table.end()) {
00344 p = table.addRelative(filename);
00345 }
00346 return p->second.c_str();
00347 }
00348
00349 const char * osl::OslConfig::testPublicFile(const std::string& filename)
00350 {
00351 static NameHolder table(testPublic());
00352 NameHolder::iterator p=table.find(filename);
00353 if (p == table.end()) {
00354 p = table.addRelative(filename);
00355 }
00356 return p->second.c_str();
00357 }
00358
00359 const char * osl::OslConfig::testCsaFile(const std::string& filename)
00360 {
00361 static NameHolder table(testPublic()+"/floodgate2010");
00362 NameHolder::iterator p=table.find(filename);
00363 if (p == table.end()) {
00364 p = table.addRelative(filename);
00365 }
00366 return p->second.c_str();
00367 }
00368
00369 const char *osl::OslConfig::openingBook(const std::string& filename)
00370 {
00371 static NameHolder table(home()+"/data");
00372 NameHolder::iterator p=table.find(filename);
00373 if (p == table.end()) {
00374 if (! filename.empty() && filename[0] == '/') {
00375
00376 p = table.add(filename, filename);
00377 }
00378 else {
00379
00380 p = table.addRelative(filename,
00381 (filename == "" ? "joseki.dat" : filename));
00382 }
00383 }
00384 return p->second.c_str();
00385 }
00386
00387
00388 size_t osl::OslConfig::residentMemoryUse()
00389 {
00390 #if defined(_WIN32)
00391 static const DWORD process_id = GetCurrentProcessId();
00392 HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
00393 FALSE, process_id);
00394 if (NULL == hProcess)
00395 {
00396 std::cerr << "Failed to get residentMemoryUse()\n";
00397 return 0;
00398 }
00399
00400 size_t working_set = 0;
00401 PROCESS_MEMORY_COUNTERS pmc;
00402 if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
00403 working_set = pmc.WorkingSetSize;
00404 }
00405 CloseHandle(hProcess);
00406 return working_set;
00407 #else
00408
00409
00410 std::ifstream is("/proc/self/statm");
00411 size_t total, resident;
00412 if (is >> total >> resident)
00413 return resident*getpagesize();
00414 #ifdef __APPLE__
00415 mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
00416 task_basic_info_64 ti;
00417 if (task_info(current_task(), TASK_BASIC_INFO_64, (task_info_t)&ti, &count)
00418 == KERN_SUCCESS)
00419 return ti.resident_size;
00420 #endif
00421 #ifdef __FreeBSD__
00422 static kvm_t *kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "osl kvm_open");
00423 int nproc;
00424 kinfo_proc *pp = kvm_getprocs(kd, KERN_PROC_PID, getpid(), &nproc);
00425 if (pp)
00426 return pp->ki_rssize * getpagesize();
00427 #endif
00428 #endif
00429 return 0;
00430 }
00431
00432 static std::vector<std::function<void()>>& function_vector()
00433 {
00434 static std::vector<std::function<void()>> initialize_functions;
00435 return initialize_functions;
00436 }
00437
00438 void osl::OslConfig::setUp()
00439 {
00440 for (auto f:function_vector())
00441 f();
00442 function_vector().clear();
00443 #ifndef DFPNSTATONE
00444 eval::OpenMidEndingEval::setUp();
00445 progress::NewProgress::setUp();
00446 #endif
00447 }
00448
00449 void osl::OslConfig::registerInitializer(std::function<void()> f) {
00450 function_vector().push_back(f);
00451 }
00452
00453 bool osl::OslConfig::healthCheck()
00454 {
00455 bool old_verbose = verbose();
00456 setVerbose(true);
00457 std::cerr << "health check\n";
00458 showOslHome(home());
00459 #ifndef DFPNSTATONE
00460 {
00461
00462 std::string filename = "eval.bin";
00463 std::cerr << "loading " << filename << ' ';
00464
00465 bool success = true;
00466 std::cerr << (success ? "success" : "failed\a") << "\n";
00467 if (! success) {
00468 std::cerr << "exists? " << boost::filesystem::exists(filename.c_str()) << "\n";
00469 std::cerr << "regular? " << boost::filesystem::is_regular_file(filename.c_str()) << "\n";
00470 return false;
00471 }
00472 }
00473 #if 0
00474 {
00475 std::string filename = progress::ml::NewProgress::defaultFilename();
00476 std::cerr << "loading " << filename << ' ';
00477 bool success = progress::ml::NewProgress::setUp(filename.c_str());
00478 std::cerr << (success ? "success" : "failed\a") << "\n";
00479 if (! success) {
00480 std::cerr << "exists? " << boost::filesystem::exists(filename.c_str()) << "\n";
00481 std::cerr << "regular? " << boost::filesystem::is_regular_file(filename.c_str()) << "\n";
00482 return false;
00483 }
00484 }
00485 #endif
00486 #endif
00487 setVerbose(old_verbose);
00488 return true;
00489 }
00490
00491 int osl::OslConfig::dfpnMaxDepth()
00492 {
00493 return dfpn_max_depth;
00494 }
00495 void osl::OslConfig::setDfpnMaxDepth(int new_depth)
00496 {
00497 dfpn_max_depth = new_depth;
00498 }
00499
00500 std::string osl::OslConfig::configuration()
00501 {
00502 return
00503 "wordsize " +std::to_string(OSL_WORDSIZE)+""
00504 # ifdef __GNUC__
00505 " gcc " __VERSION__
00506 # endif
00507 #ifndef OSL_USE_SSE
00508 " nosse"
00509 #endif
00510 # ifndef NDEBUG
00511 " (debug)"
00512 # endif
00513 ;
00514 }
00515
00516
00517
00518
00519
00520