Protector Code
Brought to you by:
raimundheid
--- a +++ b/coordination.c @@ -0,0 +1,391 @@ +/* + Protector -- a UCI chess engine + + Copyright (C) 2008 Raimund Heid (Raimund_Heid@yahoo.com) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +*/ + +#include "coordination.h" +#include "protector.h" +#include "search.h" +#include "matesearch.h" +#include "io.h" +#include "hash.h" +#include <stdio.h> +#include <assert.h> + +#ifdef TARGET_WINDOWS +#include <windows.h> +#endif +#ifdef TARGET_LINUX +#include <pthread.h> +#endif + +/* #define DEBUG_COORDINATION */ + +#ifdef TARGET_WINDOWS +HANDLE searchThread[MAX_THREADS]; +DWORD searchThreadId[MAX_THREADS]; +LPCTSTR commonMutexObject = "MO"; +HANDLE guiSearchMutex; +#endif +#ifdef TARGET_LINUX +pthread_t searchThread[MAX_THREADS]; +static pthread_mutex_t guiSearchMutex = PTHREAD_MUTEX_INITIALIZER; +long searchThreadId[MAX_THREADS]; +#endif + +static int numThreads = 1; +static SearchTask dummyTask; +static SearchTask *currentTask = &dummyTask; +static Variation variations[MAX_THREADS]; +static Hashtable localHashtable; +static bool guiLocked = FALSE, searchLocked = FALSE; +static PawnHashInfo pawnHashtable[MAX_THREADS][PAWN_HASHTABLE_SIZE]; +static KingSafetyHashInfo + kingSafetyHashtable[MAX_THREADS][KINGSAFETY_HASHTABLE_SIZE]; +static UINT16 _historyValue[MAX_THREADS][HISTORY_SIZE]; +static UINT16 _historyTotalCount[MAX_THREADS][HISTORY_SIZE]; +static UINT16 _historyHitCount[MAX_THREADS][HISTORY_SIZE]; + +int setNumberOfThreads(int _numThreads) +{ + numThreads = max(1, min(MAX_THREADS, _numThreads)); + + return numThreads; +} + +UINT64 getNodeCount() +{ + int threadCount; + UINT64 sum = 0; + + for (threadCount = 0; threadCount < numThreads; threadCount++) + { + sum += variations[threadCount].nodes; + } + + return sum; +} + +Variation *getCurrentVariation() +{ + return &variations[0]; +} + +void getGuiSearchMutex() +{ +#ifdef DEBUG_COORDINATION + logDebug("aquiring search lock...\n"); +#endif + +#ifdef MSFT_CC + WaitForSingleObject(guiSearchMutex, INFINITE); +#else + pthread_mutex_lock(&guiSearchMutex); +#endif + +#ifdef DEBUG_COORDINATION + logDebug("search lock aquired...\n"); +#endif +} + +void releaseGuiSearchMutex() +{ +#ifdef MSFT_CC + ReleaseMutex(guiSearchMutex); +#else + pthread_mutex_unlock(&guiSearchMutex); +#endif + +#ifdef DEBUG_COORDINATION + logDebug("search lock released...\n"); +#endif +} + +int startSearch(Variation * currentVariation) +{ + currentVariation->searchStatus = SEARCH_STATUS_RUNNING; + + switch (currentTask->type) + { + case TASKTYPE_BEST_MOVE: + currentTask->bestMove = search(currentVariation, NULL); + break; + + case TASKTYPE_TEST_BEST_MOVE: + currentTask->bestMove = + search(currentVariation, ¤tTask->solutions); + break; + + case TASKTYPE_MATE_IN_N: + searchForMate(currentVariation, + ¤tTask->calculatedSolutions, + currentTask->numberOfMoves); + break; + + case TASKTYPE_TEST_MATE_IN_N: + searchForMate(currentVariation, + ¤tTask->calculatedSolutions, + currentTask->numberOfMoves); + break; + + default: + break; + } + + currentTask->nodes = getNodeCount(); + currentVariation->searchStatus = SEARCH_STATUS_FINISHED; + + if (currentVariation->threadNumber == 0) + { + int threadCount; + + for (threadCount = 1; threadCount < numThreads; threadCount++) + { + variations[threadCount].terminate = TRUE; + } + } + +#ifdef DEBUG_COORDINATION + logDebug("Search thread terminated.\n"); +#endif + + return 0; +} + +#ifdef TARGET_WINDOWS +DWORD WINAPI executeSearch(PVOID arg) +{ + Variation *currentVariation = arg; + + startSearch(currentVariation); + + return 0; +} +#endif +#ifdef TARGET_LINUX +static void *executeSearch(void *arg) +{ + Variation *currentVariation = arg; + + startSearch(currentVariation); + + return 0; +} +#endif + +void scheduleTask(SearchTask * task) +{ + int threadCount; + + localHashtable.entriesUsed = 0; + + for (threadCount = 0; threadCount < numThreads; threadCount++) + { + Variation *currentVariation = &variations[threadCount]; + + currentVariation->terminate = TRUE; + +#ifdef DEBUG_COORDINATION + logDebug("Schedule task: Search abort signaled.\n"); +#endif + + while (currentVariation->searchStatus != SEARCH_STATUS_FINISHED) + { +#ifdef DEBUG_COORDINATION + logDebug("Stopping search thread ...\n"); +#endif + +#ifdef TARGET_WINDOWS + WaitForSingleObject(searchThread[threadCount], 100); +#endif +#ifdef TARGET_LINUX + pthread_join(searchThread[threadCount], NULL); +#endif + } + + currentTask = task; + *currentVariation = *(currentTask->variation); + currentVariation->searchStatus = SEARCH_STATUS_TERMINATE; + currentVariation->terminate = FALSE; + currentVariation->hashtable = &localHashtable; + currentVariation->pawnHashtable = &(pawnHashtable[threadCount][0]); + currentVariation->kingsafetyHashtable = + &(kingSafetyHashtable[threadCount][0]); + currentVariation->historyValue = &(_historyValue[threadCount][0]); + currentVariation->historyTotalCount = + &(_historyTotalCount[threadCount][0]); + currentVariation->historyHitCount = &(_historyHitCount[threadCount][0]); + currentVariation->threadNumber = threadCount; + + if (threadCount != 0) + { + currentVariation->handleSearchEvent = 0; + } + +#ifdef TARGET_WINDOWS + searchThread[threadCount] = + CreateThread(NULL, 0, executeSearch, currentVariation, + 0, &searchThreadId[threadCount]); + + if (searchThread[threadCount] != NULL) + { + SetThreadPriority(searchThread[threadCount], + THREAD_PRIORITY_BELOW_NORMAL); + +#ifdef DEBUG_COORDINATION + logDebug("Search thread %d started.\n", threadCount); +#endif + } + else + { + logDebug("### Search thread could not be started. ###\n"); + + exit(EXIT_FAILURE); + } +#endif +#ifdef TARGET_LINUX + if (pthread_create(&searchThread[threadCount], NULL, + &executeSearch, currentVariation) == 0) + { +#ifdef DEBUG_COORDINATION + logDebug("Search thread %d started.\n", threadCount); +#endif + } + else + { + logDebug("### Search thread could not be started. ###\n"); + + exit(EXIT_FAILURE); + } +#endif + } +} + +void waitForSearchTermination(void) +{ + int threadCount; + + for (threadCount = 0; threadCount < numThreads; threadCount++) + { + Variation *currentVariation = &variations[threadCount]; + + if (currentVariation->searchStatus != SEARCH_STATUS_FINISHED) + { +#ifdef TARGET_WINDOWS + WaitForSingleObject(searchThread[threadCount], INFINITE); +#endif +#ifdef TARGET_LINUX + pthread_join(searchThread[threadCount], NULL); +#endif + } + +#ifdef DEBUG_COORDINATION + logDebug("Task %d finished.\n", threadCount); +#endif + } +} + +void completeTask(SearchTask * task) +{ + scheduleTask(task); + +#ifdef DEBUG_COORDINATION + logDebug("Task scheduled. Waiting for completion.\n"); +#endif + + waitForSearchTermination(); +} + +void prepareSearchAbort(Variation * variation) +{ + int threadCount; + + for (threadCount = 0; threadCount < numThreads; threadCount++) + { + variations[threadCount].terminate = TRUE; + } + + *variation = variations[0]; +} + +void unsetPonderMode(void) +{ + int threadCount; + + for (threadCount = 0; threadCount < numThreads; threadCount++) + { + Variation *currentVariation = &variations[threadCount]; + + currentVariation->ponderMode = FALSE; + } +} + +void setTimeLimit(unsigned long timeTarget, unsigned long timeLimit) +{ + int threadCount; + + for (threadCount = 0; threadCount < numThreads; threadCount++) + { + Variation *currentVariation = &variations[threadCount]; + + currentVariation->timeTarget = timeTarget; + currentVariation->timeLimit = timeLimit; + } +} + +void setHashtableSize(unsigned int size) +{ + unsigned long tablesize = sizeof(Hashentry); + int exponent = 0; + + while (tablesize <= (unsigned long) size * 512 * 1024) + { + exponent++; + tablesize *= 2; + } + + setHashtableExponent(&localHashtable, exponent); + resetHashtable(&localHashtable); +} + +int initializeModuleCoordination() +{ + int threadCount; + +#ifdef TARGET_WINDOWS + guiSearchMutex = CreateMutex(NULL, FALSE, commonMutexObject); +#endif + + initializeHashtable(&localHashtable); + setHashtableExponent(&localHashtable, 22); + resetHashtable(&localHashtable); + + for (threadCount = 0; threadCount < MAX_THREADS; threadCount++) + { + Variation *currentVariation = &variations[threadCount]; + + currentVariation->searchStatus = SEARCH_STATUS_FINISHED; + } + + return 0; +} + +int testModuleCoordination() +{ + return 0; +}