X-Git-Url: https://git.sesse.net/?p=stockfish;a=blobdiff_plain;f=src%2Fmisc.cpp;h=2eb62f3e4ff7e4fbf6d01845337e10b5fe6284d9;hp=7075dd3cdc8498192cd8f256740fcc497cb63827;hb=378c8bdbb8f930472fc4316aa6c417802294bbad;hpb=0d9a9f5e985c13852cf9f29767e95f295bb29575 diff --git a/src/misc.cpp b/src/misc.cpp index 7075dd3c..2eb62f3e 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -2,7 +2,7 @@ Stockfish, a UCI chess playing engine derived from Glaurung 2.1 Copyright (C) 2004-2008 Tord Romstad (Glaurung author) Copyright (C) 2008-2015 Marco Costalba, Joona Kiiski, Tord Romstad - Copyright (C) 2015-2016 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad + Copyright (C) 2015-2018 Marco Costalba, Joona Kiiski, Gary Linscott, Tord Romstad Stockfish is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,9 +21,19 @@ #ifdef _WIN32 #if _WIN32_WINNT < 0x0601 #undef _WIN32_WINNT -#define _WIN32_WINNT 0x0601 // Force to include newest API (Win 7 or later) +#define _WIN32_WINNT 0x0601 // Force to include needed API prototypes #endif -#include // For processor groups +#include +// The needed Windows API for processor groups could be missed from old Windows +// versions, so instead of calling them directly (forcing the linker to resolve +// the calls at compile time), try to load them at runtime. To do this we need +// first to define the corresponding function pointers. +extern "C" { +typedef bool(*fun1_t)(LOGICAL_PROCESSOR_RELATIONSHIP, + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD); +typedef bool(*fun2_t)(USHORT, PGROUP_AFFINITY); +typedef bool(*fun3_t)(HANDLE, CONST GROUP_AFFINITY*, PGROUP_AFFINITY); +} #endif #include @@ -41,7 +51,7 @@ namespace { /// Version number. If Version is left empty, then compile date in the format /// DD-MM-YY and show in engine_info. -const string Version = ""; +const string Version = "9"; /// Our fancy logging facility. The trick here is to replace cin.rdbuf() and /// cout.rdbuf() with two Tie objects that tie cin and cout to a file stream. We @@ -53,10 +63,10 @@ struct Tie: public streambuf { // MSVC requires split streambuf for cin and cout Tie(streambuf* b, streambuf* l) : buf(b), logBuf(l) {} - int sync() { return logBuf->pubsync(), buf->pubsync(); } - int overflow(int c) { return log(buf->sputc((char)c), "<< "); } - int underflow() { return buf->sgetc(); } - int uflow() { return log(buf->sbumpc(), ">> "); } + int sync() override { return logBuf->pubsync(), buf->pubsync(); } + int overflow(int c) override { return log(buf->sputc((char)c), "<< "); } + int underflow() override { return buf->sgetc(); } + int uflow() override { return log(buf->sbumpc(), ">> "); } streambuf *buf, *logBuf; @@ -195,6 +205,12 @@ void prefetch(void* addr) { #endif +void prefetch2(void* addr) { + + prefetch(addr); + prefetch((uint8_t*)addr + 64); +} + namespace WinProcGroup { #ifndef _WIN32 @@ -215,15 +231,14 @@ int get_group(size_t idx) { DWORD returnLength = 0; DWORD byteOffset = 0; - // Early exit if the needed API are not available at runtime + // Early exit if the needed API is not available at runtime HMODULE k32 = GetModuleHandle("Kernel32.dll"); - if ( !GetProcAddress(k32, "GetLogicalProcessorInformationEx") - || !GetProcAddress(k32, "GetNumaNodeProcessorMaskEx") - || !GetProcAddress(k32, "SetThreadGroupAffinity")) + auto fun1 = (fun1_t)GetProcAddress(k32, "GetLogicalProcessorInformationEx"); + if (!fun1) return -1; // First call to get returnLength. We expect it to fail due to null buffer - if (GetLogicalProcessorInformationEx(RelationAll, nullptr, &returnLength)) + if (fun1(RelationAll, nullptr, &returnLength)) return -1; // Once we know returnLength, allocate the buffer @@ -231,7 +246,7 @@ int get_group(size_t idx) { ptr = buffer = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(returnLength); // Second call, now we expect to succeed - if (!GetLogicalProcessorInformationEx(RelationAll, buffer, &returnLength)) + if (!fun1(RelationAll, buffer, &returnLength)) { free(buffer); return -1; @@ -278,15 +293,23 @@ int get_group(size_t idx) { void bindThisThread(size_t idx) { - // Use a local variable instead of a static: slower but thread-safe + // Use only local variables to be thread-safe int group = get_group(idx); if (group == -1) return; - GROUP_AFFINITY mask; - if (GetNumaNodeProcessorMaskEx(group, &mask)) - SetThreadGroupAffinity(GetCurrentThread(), &mask, nullptr); + // Early exit if the needed API are not available at runtime + HMODULE k32 = GetModuleHandle("Kernel32.dll"); + auto fun2 = (fun2_t)GetProcAddress(k32, "GetNumaNodeProcessorMaskEx"); + auto fun3 = (fun3_t)GetProcAddress(k32, "SetThreadGroupAffinity"); + + if (!fun2 || !fun3) + return; + + GROUP_AFFINITY affinity; + if (fun2(group, &affinity)) + fun3(GetCurrentThread(), &affinity, nullptr); } #endif