oslConfig.cc
Go to the documentation of this file.
1 /* oslConfig.cc
2  */
3 #include "osl/oslConfig.h"
4 #include "osl/config.h"
6 #include "osl/progress.h"
7 #include <boost/filesystem/operations.hpp>
8 #include <map>
9 #include <limits>
10 #include <iostream>
11 #include <fstream>
12 #include <cstdlib>
13 #include <thread>
14 #ifndef _MSC_VER
15 # include <unistd.h>
16 #endif
17 #ifdef _WIN32
18 # include <windows.h>
19 # include <psapi.h>
20 #else
21 #include <sys/resource.h>
22 #ifdef __FreeBSD__
23 # include <kvm.h>
24 # include <sys/param.h>
25 # include <sys/sysctl.h>
26 # include <sys/user.h>
27 # include <paths.h>
28 # include <fcntl.h>
29 #endif
30 #ifdef __APPLE__
31 # include <sys/types.h>
32 # include <sys/sysctl.h>
33 # include <mach/task.h>
34 # include <mach/mach_init.h>
35 #endif
36 #endif
37 
38 const int osl::OslConfig::MaxThreads; // define
39 unsigned int osl::OslConfig::eval_random = 0;
40 
41 bool osl::OslConfig::is_verbose = false;
42 #ifndef OSL_NCPUS
43 const int osl::OslConfig::default_ncpus = std::thread::hardware_concurrency();
44 #else
45 static_assert(OSL_NCPUS <= osl::OslConfig::MaxThreads, "#threads");
46 const int osl::OslConfig::default_ncpus = OSL_NCPUS;
47 #endif
48 int osl::OslConfig::num_cpu = default_ncpus;
50 volatile bool osl::OslConfig::usi_mode_silent = false,
53 volatile int osl::OslConfig::root_window_alpha = 0;
54 volatile int osl::OslConfig::root_window_beta = 0;
55 volatile int osl::OslConfig::in_unit_test = 0;
58 bool osl::OslConfig::has_byoyomi = false;
59 std::mutex osl::OslConfig::lock_io;
60 
61 namespace
62 {
63  size_t system_memory_use_limit()
64  {
65 #ifdef _WIN32
66  MEMORYSTATUSEX statex;
67  statex.dwLength = sizeof(statex);
68  GlobalMemoryStatusEx(&statex);
69  return statex.ullTotalPhys; // in bytes
70 #else
71  size_t limit_by_rlimit = std::numeric_limits<size_t>::max();
72  {
73  rlimit rlp;
74  if (getrlimit(RLIMIT_AS, &rlp) == 0
75  && rlp.rlim_cur != std::numeric_limits<rlim_t>::max()) {
76  limit_by_rlimit = rlp.rlim_cur;
77 #ifdef __APPLE__
78  limit_by_rlimit *= 1024;
79 #endif
80  std::cerr << "rlimit " << limit_by_rlimit << "\n";
81  }
82  }
83 #ifdef __APPLE__
84  {
85  int mib[2];
86  unsigned int usermem;
87  size_t len=sizeof(usermem);
88  mib[0] = CTL_HW;
89  mib[1] = HW_USERMEM;
90  if (sysctl(mib, 2, &usermem, &len, NULL, 0) == 0
91  && len == sizeof(usermem)) {
92  std::cerr << "usermem " << usermem << std::endl;
93  return std::min((size_t)usermem, limit_by_rlimit);
94  }
95  }
96 #endif
97  {
98  std::string name, unit;
99  size_t value;
100  std::ifstream is("/proc/meminfo");
101  if (is >> name >> value >> unit
102  && name == "MemTotal:" && unit == "kB")
103  return std::min(value * 1024, limit_by_rlimit);
104  }
105 #if (defined __FreeBSD__)
106  const long mem = sysconf(_SC_PHYS_PAGES);
107  if (mem != -1)
108  return std::min(mem * getpagesize(), limit_by_rlimit);
109 #endif
110  return std::min((rlim_t)limit_by_rlimit, std::numeric_limits<rlim_t>::max());
111 #endif
112  }
113 }
114 
115 size_t osl::OslConfig::memory_use_limit = system_memory_use_limit();
117 #ifdef _WIN32
118  3000000000; // 3GB
119 #else
121 #endif
123 
125 {
126  if (ncpu > MaxThreads) {
127  std::cerr << "ncpu " << ncpu << " > " << "MaxThreads " << MaxThreads << "\n";
128  ncpu = MaxThreads;
129  }
130  num_cpu = ncpu;
131 }
132 
134 {
135  if (num_cpu > MaxThreads)
136  std::cerr << "ncpu " << num_cpu << " > " << "MaxThreads " << MaxThreads << "\n";
137  return std::min(num_cpu, MaxThreads);
138 }
139 
141 {
142  is_verbose = v;
143 }
144 
146 {
147  return is_verbose;
148 }
149 
151 {
152  return usi_mode;
153 }
155 {
156  usi_mode = enable;
157 }
159 {
160  return usi_mode_silent;
161 }
163 {
164  usi_mode_silent = enable;
165 }
167 {
169 }
171 {
173 }
174 
176 {
177  return has_byoyomi;
178 }
179 
181 {
182  has_byoyomi = value;
183 }
184 
185 void osl::OslConfig::showOslHome(const std::string& home)
186 {
187  std::cerr << "using " << home << " as OSL_HOME, word size "
188  << OSL_WORDSIZE << std::endl;
189 }
190 
192 {
193  showOslHome(home());
194 }
195 
196 bool osl::OslConfig::isGoodDir(const std::string& dir)
197 {
198  return boost::filesystem::exists(dir)
199  && boost::filesystem::is_directory(dir);
200 }
201 
202 void osl::OslConfig::trySetDir(std::string& dir, const std::string& candidate)
203 {
204  if (isGoodDir(candidate))
205  {
206  dir = candidate;
207  return;
208  }
209  if (verbose())
210  std::cerr << "skipping " << candidate << std::endl;
211 }
212 
213 const std::string osl::OslConfig::makeHome(const std::string& first_try)
214 {
215  std::string result;
216  if (first_try != "")
217  trySetDir(result, first_try);
218 
219  if (const char *env = getenv("GPSSHOGI_HOME"))
220  trySetDir(result, env);
221 
222 #if defined GPSSHOGI_HOME
223  if (result.empty())
224  trySetDir(result, GPSSHOGI_HOME);
225 #endif
226 
227  if (result.empty())
228  if (const char *env = getenv("OSL_HOME"))
229  trySetDir(result, env);
230 
231  if (result.empty())
232  result = OSL_HOME;
233 
234  if (verbose())
235  showOslHome(result);
236  return result;
237 }
238 
239 const std::string& osl::OslConfig::home(const std::string& init)
240 {
241  static const std::string home_directory = makeHome(init);
242  return home_directory;
243 }
244 
246 {
247  return home().c_str();
248 }
249 
250 const std::string osl::OslConfig::gpsusiConf()
251 {
252  // issue:
253  // - 開発者には $HOME ではなく OSL_HOME の方が使い分ける都合が良い
254  // - 一方、配布版では OSL_HOME は共有ディレクトリで書き込めないかもしれない
255 #ifdef OSL_PUBLIC_RELEASE
256  // for personal users
257  if (const char *env = getenv("HOME"))
258  return std::string(env) + "/gpsusi.conf";
259  if (const char *env = getenv("USERPROFILE"))
260  return std::string(env) + "/gpsusi.conf";
261 #endif
262  // for developpers
263  static const std::string home_directory = makeHome();
264  return home_directory + "/gpsusi.conf";
265 }
266 
268 {
269  static const int value = getenv("OSL_RESIGN_VALUE")
270  ? atoi(getenv("OSL_RESIGN_VALUE")) : 0;
271  return (value > 0) ? value : 10000;
272 }
273 
274 const std::string osl::OslConfig::makeTest()
275 {
276  std::string result;
277  if (const char *env = getenv("OSL_TEST"))
278  trySetDir(result, env);
279 
280  if (result.empty())
281  result = home() + "/data"; // 今はdata内に混在
282 
283  std::cerr << "using " << result << " as OSL_TEST" << std::endl;
284  return result;
285 }
286 
288 {
289  std::string result;
290  if (const char *env = getenv("OSL_TEST_PUBLIC"))
291  trySetDir(result, env);
292 
293  if (result.empty())
294  result = home() + "/public-data";
295 
296  std::cerr << "using " << result << " as OSL_TEST_PUBLIC" << std::endl;
297  return result;
298 }
299 
300 const std::string osl::OslConfig::testPrivate()
301 {
302  static const std::string test_directory = makeTest();
303  return test_directory;
304 }
305 
306 const std::string osl::OslConfig::testPublic()
307 {
308  static const std::string test_directory = makeTestPublic();
309  return test_directory;
310 }
311 
312 namespace
313 {
314  struct NameHolder : std::map<std::string,std::string>
315  {
316  std::string directory;
317 
318  NameHolder(const std::string& d) : directory(d)
319  {
320  directory += "/";
321  }
322 
323  iterator add(const std::string& key, const std::string& value)
324  {
325  return insert(std::make_pair(key, value)).first;
326  }
327  iterator addRelative(const std::string& key, const std::string& filename)
328  {
329  std::string value = directory + filename;
330  return add(key, value);
331  }
332  iterator addRelative(const std::string& filename)
333  {
334  return addRelative(filename, filename);
335  }
336  };
337 }
338 
339 const char * osl::OslConfig::testPrivateFile(const std::string& filename)
340 {
341  static NameHolder table(testPrivate());
342  NameHolder::iterator p=table.find(filename);
343  if (p == table.end()) {
344  p = table.addRelative(filename);
345  }
346  return p->second.c_str();
347 }
348 
349 const char * osl::OslConfig::testPublicFile(const std::string& filename)
350 {
351  static NameHolder table(testPublic());
352  NameHolder::iterator p=table.find(filename);
353  if (p == table.end()) {
354  p = table.addRelative(filename);
355  }
356  return p->second.c_str();
357 }
358 
359 const char * osl::OslConfig::testCsaFile(const std::string& filename)
360 {
361  static NameHolder table(testPublic()+"/floodgate2010");
362  NameHolder::iterator p=table.find(filename);
363  if (p == table.end()) {
364  p = table.addRelative(filename);
365  }
366  return p->second.c_str();
367 }
368 
369 const char *osl::OslConfig::openingBook(const std::string& filename)
370 {
371  static NameHolder table(home()+"/data");
372  NameHolder::iterator p=table.find(filename);
373  if (p == table.end()) {
374  if (! filename.empty() && filename[0] == '/') {
375  // absolute path
376  p = table.add(filename, filename);
377  }
378  else {
379  // relative path
380  p = table.addRelative(filename,
381  (filename == "" ? "joseki.dat" : filename));
382  }
383  }
384  return p->second.c_str();
385 }
386 
387 
389 {
390 #if defined(_WIN32)
391  static const DWORD process_id = GetCurrentProcessId();
392  HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
393  FALSE, process_id);
394  if (NULL == hProcess)
395  {
396  std::cerr << "Failed to get residentMemoryUse()\n";
397  return 0;
398  }
399 
400  size_t working_set = 0;
401  PROCESS_MEMORY_COUNTERS pmc;
402  if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) {
403  working_set = pmc.WorkingSetSize; // in bytes
404  }
405  CloseHandle(hProcess);
406  return working_set;
407 #else
408  // see proc(5)
409  // note: < 40000 cycles @macpro2
410  std::ifstream is("/proc/self/statm");
411  size_t total, resident;
412  if (is >> total >> resident)
413  return resident*getpagesize();
414 #ifdef __APPLE__
415  mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT;
416  task_basic_info_64 ti;
417  if (task_info(current_task(), TASK_BASIC_INFO_64, (task_info_t)&ti, &count)
418  == KERN_SUCCESS)
419  return ti.resident_size;
420 #endif
421 #ifdef __FreeBSD__
422  static kvm_t *kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "osl kvm_open");
423  int nproc;
424  kinfo_proc *pp = kvm_getprocs(kd, KERN_PROC_PID, getpid(), &nproc);
425  if (pp)
426  return pp->ki_rssize * getpagesize();
427 #endif
428 #endif
429  return 0;
430 }
431 
432 static std::vector<std::function<void()>>& function_vector()
433 {
434  static std::vector<std::function<void()>> initialize_functions;
435  return initialize_functions;
436 }
437 
439 {
440  for (auto f:function_vector())
441  f();
442  function_vector().clear();
443 #ifndef DFPNSTATONE
446 #endif
447 }
448 
449 void osl::OslConfig::registerInitializer(std::function<void()> f) {
450  function_vector().push_back(f);
451 }
452 
454 {
455  bool old_verbose = verbose();
456  setVerbose(true);
457  std::cerr << "health check\n";
458  showOslHome(home());
459 #ifndef DFPNSTATONE
460  {
461  //std::string filename = eval::ml::OpenMidEndingEval::defaultFilename();
462  std::string filename = "eval.bin";
463  std::cerr << "loading " << filename << ' ';
464  //bool success = eval::ml::OpenMidEndingEval::setUp(filename.c_str());
465  bool success = true;
466  std::cerr << (success ? "success" : "failed\a") << "\n";
467  if (! success) {
468  std::cerr << "exists? " << boost::filesystem::exists(filename.c_str()) << "\n";
469  std::cerr << "regular? " << boost::filesystem::is_regular_file(filename.c_str()) << "\n";
470  return false;
471  }
472  }
473 #if 0
474  {
475  std::string filename = progress::ml::NewProgress::defaultFilename();
476  std::cerr << "loading " << filename << ' ';
477  bool success = progress::ml::NewProgress::setUp(filename.c_str());
478  std::cerr << (success ? "success" : "failed\a") << "\n";
479  if (! success) {
480  std::cerr << "exists? " << boost::filesystem::exists(filename.c_str()) << "\n";
481  std::cerr << "regular? " << boost::filesystem::is_regular_file(filename.c_str()) << "\n";
482  return false;
483  }
484  }
485 #endif
486 #endif
487  setVerbose(old_verbose);
488  return true;
489 }
490 
492 {
493  return dfpn_max_depth;
494 }
496 {
497  dfpn_max_depth = new_depth;
498 }
499 
501 {
502  return
503  "wordsize " +std::to_string(OSL_WORDSIZE)+""
504 # ifdef __GNUC__
505  " gcc " __VERSION__
506 # endif
507 #ifndef OSL_USE_SSE
508  " nosse"
509 #endif
510 # ifndef NDEBUG
511  " (debug)"
512 # endif
513  ;
514 }
515 
516 /* ------------------------------------------------------------------------- */
517 // ;;; Local Variables:
518 // ;;; mode:c++
519 // ;;; c-basic-offset:2
520 // ;;; End:
static const size_t memory_use_limit_system_max
Definition: oslConfig.h:109
static const std::string makeTest()
Definition: oslConfig.cc:274
int max(Player p, int v1, int v2)
Definition: evalTraits.h:84
static int usi_output_pawn_value
Definition: oslConfig.h:116
static size_t memory_use_limit
Definition: oslConfig.h:107
static void setUsiMode(UsiMode new_mode=PortableUSI)
Definition: oslConfig.cc:154
static const std::string makeTestPublic()
Definition: oslConfig.cc:287
static void setDfpnMaxDepth(int)
Definition: oslConfig.cc:495
static const std::string makeHome(const std::string &first_try="")
Definition: oslConfig.cc:213
static const std::string testPrivate()
テストケースのデータ
Definition: oslConfig.cc:300
static volatile int root_window_beta
Definition: oslConfig.h:119
static void setUp()
評価関数等を初期化.
Definition: oslConfig.cc:438
int min(Player p, int v1, int v2)
Definition: evalTraits.h:92
static const char * testCsaFile(const std::string &filename)
Definition: oslConfig.cc:359
static volatile bool usi_mode_silent
Definition: oslConfig.h:115
static size_t residentMemoryUse()
Definition: oslConfig.cc:388
static bool is_verbose
Definition: oslConfig.h:111
static bool verbose()
Definition: oslConfig.cc:145
static const char * testPrivateFile(const std::string &filename)
Definition: oslConfig.cc:339
static volatile bool force_root_window
Definition: oslConfig.h:118
static double memory_use_percent
Definition: oslConfig.h:108
static void setSearchExactValueInOneReply(bool new_value)
Definition: oslConfig.cc:170
static int dfpnMaxDepth()
Definition: oslConfig.cc:491
static std::mutex lock_io
Definition: oslConfig.h:123
static void showOslHome()
Definition: oslConfig.cc:191
static bool hasByoyomi()
Definition: oslConfig.cc:175
static volatile UsiMode usi_mode
Definition: oslConfig.h:114
static volatile int in_unit_test
Definition: oslConfig.h:120
static bool isGoodDir(const std::string &)
Definition: oslConfig.cc:196
#define OSL_WORDSIZE
Definition: config.h:6
static int dfpn_max_depth
Definition: oslConfig.h:121
static bool search_exact_value_in_one_reply
Definition: oslConfig.h:117
static void setVerbose(bool verbose)
Definition: oslConfig.cc:140
static std::string configuration()
Definition: oslConfig.cc:500
static const char * testPublicFile(const std::string &filename)
Definition: oslConfig.cc:349
static const int default_ncpus
Definition: oslConfig.h:112
static void setNumCPUs(int ncpu)
Definition: oslConfig.cc:124
static int resignThreshold()
Definition: oslConfig.cc:267
static std::vector< std::function< void()> > & function_vector()
Definition: oslConfig.cc:432
static const std::string & home(const std::string &initialize_if_first_invocation="")
compile時に指定されたディレクトリを返す.
Definition: oslConfig.cc:239
static bool usiModeInSilent()
Definition: oslConfig.cc:158
static void registerInitializer(std::function< void()>)
Definition: oslConfig.cc:449
static void setUsiSilent(bool silent=true)
Definition: oslConfig.cc:162
static std::string defaultFilename()
Definition: progress.cc:288
static const char * openingBook(const std::string &filenamme="")
標準の定跡ファイルを返す
Definition: oslConfig.cc:369
static bool healthCheck()
Definition: oslConfig.cc:453
static int concurrency()
Definition: oslConfig.cc:133
static const std::string testPublic()
Definition: oslConfig.cc:306
static bool has_byoyomi
Definition: oslConfig.h:117
static UsiMode usiMode()
Definition: oslConfig.cc:150
static volatile int root_window_alpha
Definition: oslConfig.h:119
static bool searchExactValueInOneReply()
Definition: oslConfig.cc:166
static const int MaxThreads
Definition: oslConfig.h:20
static void setHasByoyomi(bool)
Definition: oslConfig.cc:180
static unsigned int eval_random
Definition: oslConfig.h:110
static const char * home_c_str()
Definition: oslConfig.cc:245
static int num_cpu
Definition: oslConfig.h:113
static const std::string gpsusiConf()
Definition: oslConfig.cc:250
static void trySetDir(std::string &, const std::string &)
Definition: oslConfig.cc:202