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