X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fthread.cpp;h=002819de566ce71a2c91e2566ca481bf1376445c;hp=30c921d1808ebd4716dee58bab6deeefe0e54279;hb=339e1b49f619ceffa75019e196adf4de74b32cce;hpb=fecefbb99cb0147f37d6895765a315f34c935786 diff --git a/src/thread.cpp b/src/thread.cpp index 30c921d1..002819de 100644 --- a/src/thread.cpp +++ b/src/thread.cpp @@ -64,50 +64,48 @@ void ThreadsManager::read_uci_options() { activeThreads = Options["Threads"].value(); } + // init_threads() is called during startup. Initializes locks and condition // variables and launches all threads sending them immediately to sleep. void ThreadsManager::init_threads() { - int i, arg[MAX_THREADS]; - bool ok; + int arg[MAX_THREADS]; // This flag is needed to properly end the threads when program exits allThreadsShouldExit = false; // Threads will sent to sleep as soon as created, only main thread is kept alive activeThreads = 1; + threads[0].state = THREAD_SEARCHING; + + // Allocate pawn and material hash tables for main thread + init_hash_tables(); lock_init(&mpLock); - for (i = 0; i < MAX_THREADS; i++) + // Initialize thread and split point locks + for (int i = 0; i < MAX_THREADS; i++) { - // Initialize thread and split point locks lock_init(&threads[i].sleepLock); cond_init(&threads[i].sleepCond); for (int j = 0; j < MAX_ACTIVE_SPLIT_POINTS; j++) lock_init(&(threads[i].splitPoints[j].lock)); - - // All threads but first should be set to THREAD_INITIALIZING - threads[i].state = (i == 0 ? THREAD_SEARCHING : THREAD_INITIALIZING); - - // Not in Threads c'tor to avoid global initialization order issues - threads[i].pawnTable.init(); - threads[i].materialTable.init(); } - // Create and startup the threads - for (i = 1; i < MAX_THREADS; i++) + // Create and startup all the threads but the main that is already running + for (int i = 1; i < MAX_THREADS; i++) { + threads[i].state = THREAD_INITIALIZING; arg[i] = i; #if !defined(_MSC_VER) pthread_t pthread[1]; - ok = (pthread_create(pthread, NULL, init_thread, (void*)(&arg[i])) == 0); + bool ok = (pthread_create(pthread, NULL, init_thread, (void*)(&arg[i])) == 0); pthread_detach(pthread[0]); #else - ok = (CreateThread(NULL, 0, init_thread, (LPVOID)(&arg[i]), 0, NULL) != NULL); + bool ok = (CreateThread(NULL, 0, init_thread, (LPVOID)(&arg[i]), 0, NULL) != NULL); #endif if (!ok) { @@ -150,6 +148,22 @@ void ThreadsManager::exit_threads() { } +// init_hash_tables() dynamically allocates pawn and material hash tables +// according to the number of active threads. This avoids preallocating +// memory for all possible threads if only few are used as, for instance, +// on mobile devices where memory is scarce and allocating for MAX_THREADS +// threads could even result in a crash. + +void ThreadsManager::init_hash_tables() { + + for (int i = 0; i < activeThreads; i++) + { + threads[i].pawnTable.init(); + threads[i].materialTable.init(); + } +} + + // cutoff_at_splitpoint() checks whether a beta cutoff has occurred in // the thread's currently active split point, or in some ancestor of // the current split point.