My Project
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
38const int osl::OslConfig::MaxThreads; // define
39unsigned int osl::OslConfig::eval_random = 0;
40
42#ifndef OSL_NCPUS
43const int osl::OslConfig::default_ncpus = std::thread::hardware_concurrency();
44#else
45static_assert(OSL_NCPUS <= osl::OslConfig::MaxThreads, "#threads");
46const int osl::OslConfig::default_ncpus = OSL_NCPUS;
47#endif
48int osl::OslConfig::num_cpu = default_ncpus;
50volatile bool osl::OslConfig::usi_mode_silent = false,
53volatile int osl::OslConfig::root_window_alpha = 0;
54volatile int osl::OslConfig::root_window_beta = 0;
55volatile int osl::OslConfig::in_unit_test = 0;
60
61namespace
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
115size_t osl::OslConfig::memory_use_limit = system_memory_use_limit();
117#ifdef _WIN32
118 3000000000; // 3GB
119#else
120 std::numeric_limits<rlim_t>::max();
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{
168 return search_exact_value_in_one_reply;
169}
171{
172 search_exact_value_in_one_reply = enable;
173}
174
176{
177 return has_byoyomi;
178}
179
181{
182 has_byoyomi = value;
183}
184
185void 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
196bool osl::OslConfig::isGoodDir(const std::string& dir)
197{
198 return boost::filesystem::exists(dir)
199 && boost::filesystem::is_directory(dir);
200}
201
202void 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
213const 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
239const 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
250const 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
274const 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
301{
302 static const std::string test_directory = makeTest();
303 return test_directory;
304}
305
306const std::string osl::OslConfig::testPublic()
307{
308 static const std::string test_directory = makeTestPublic();
309 return test_directory;
310}
311
312namespace
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
339const 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
349const 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
359const 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
369const 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
432static 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
449void 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 std::string defaultFilename()
Definition progress.cc:288
#define OSL_WORDSIZE
Definition config.h:6
static std::vector< std::function< void()> > & function_vector()
Definition oslConfig.cc:432
static std::mutex lock_io
Definition oslConfig.h:123
static bool is_verbose
Definition oslConfig.h:111
static void registerInitializer(std::function< void()>)
Definition oslConfig.cc:449
static void showOslHome()
Definition oslConfig.cc:191
static int concurrency()
Definition oslConfig.cc:133
static volatile int in_unit_test
Definition oslConfig.h:120
static int usi_output_pawn_value
Definition oslConfig.h:116
static void trySetDir(std::string &, const std::string &)
Definition oslConfig.cc:202
static volatile int root_window_alpha
Definition oslConfig.h:119
static int resignThreshold()
Definition oslConfig.cc:267
static bool verbose()
Definition oslConfig.cc:145
static const std::string testPublic()
Definition oslConfig.cc:306
static void setUsiSilent(bool silent=true)
Definition oslConfig.cc:162
static const std::string gpsusiConf()
Definition oslConfig.cc:250
static volatile bool force_root_window
Definition oslConfig.h:118
static int dfpn_max_depth
Definition oslConfig.h:121
static double memory_use_percent
Definition oslConfig.h:108
static bool search_exact_value_in_one_reply
Definition oslConfig.h:117
static const char * home_c_str()
Definition oslConfig.cc:245
static bool healthCheck()
Definition oslConfig.cc:453
static unsigned int eval_random
Definition oslConfig.h:110
static bool searchExactValueInOneReply()
Definition oslConfig.cc:166
static int dfpnMaxDepth()
Definition oslConfig.cc:491
static void setUsiMode(UsiMode new_mode=PortableUSI)
Definition oslConfig.cc:154
static const std::string makeHome(const std::string &first_try="")
Definition oslConfig.cc:213
static const size_t memory_use_limit_system_max
Definition oslConfig.h:109
static bool isGoodDir(const std::string &)
Definition oslConfig.cc:196
static void setUp()
評価関数等を初期化.
Definition oslConfig.cc:438
static const char * openingBook(const std::string &filenamme="")
標準の定跡ファイルを返す
Definition oslConfig.cc:369
static void setNumCPUs(int ncpu)
Definition oslConfig.cc:124
static size_t memory_use_limit
Definition oslConfig.h:107
static volatile UsiMode usi_mode
Definition oslConfig.h:114
static bool hasByoyomi()
Definition oslConfig.cc:175
static bool has_byoyomi
Definition oslConfig.h:117
static const int default_ncpus
Definition oslConfig.h:112
static std::string configuration()
Definition oslConfig.cc:500
static const std::string makeTest()
Definition oslConfig.cc:274
static bool usiModeInSilent()
Definition oslConfig.cc:158
static void setHasByoyomi(bool)
Definition oslConfig.cc:180
static const std::string testPrivate()
テストケースのデータ
Definition oslConfig.cc:300
static int num_cpu
Definition oslConfig.h:113
static void setSearchExactValueInOneReply(bool new_value)
Definition oslConfig.cc:170
static const std::string makeTestPublic()
Definition oslConfig.cc:287
static volatile int root_window_beta
Definition oslConfig.h:119
static void setDfpnMaxDepth(int)
Definition oslConfig.cc:495
static const char * testCsaFile(const std::string &filename)
Definition oslConfig.cc:359
static const char * testPublicFile(const std::string &filename)
Definition oslConfig.cc:349
static void setVerbose(bool verbose)
Definition oslConfig.cc:140
static UsiMode usiMode()
Definition oslConfig.cc:150
static size_t residentMemoryUse()
Definition oslConfig.cc:388
static volatile bool usi_mode_silent
Definition oslConfig.h:115
static const char * testPrivateFile(const std::string &filename)
Definition oslConfig.cc:339
static const std::string & home(const std::string &initialize_if_first_invocation="")
compile時に指定されたディレクトリを返す.
Definition oslConfig.cc:239
static const int MaxThreads
Definition oslConfig.h:20