mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Merge pull request #4234 from igron99/check_instructions_at_start
Check instructions at start
This commit is contained in:
commit
c411362b75
@ -231,6 +231,10 @@ private:
|
||||
|
||||
/// Previous value of logger element in config. It is used to reinitialize loggers whenever the value changed.
|
||||
std::string config_logger;
|
||||
|
||||
/// Check SSE and others instructions availability
|
||||
/// Calls exit on fail
|
||||
void checkRequiredInstructions();
|
||||
};
|
||||
|
||||
|
||||
|
@ -68,7 +68,6 @@
|
||||
#include <Common/CurrentThread.h>
|
||||
#include <Poco/Net/RemoteSyslogChannel.h>
|
||||
|
||||
|
||||
/** For transferring information from signal handler to a separate thread.
|
||||
* If you need to do something serious in case of a signal (example: write a message to the log),
|
||||
* then sending information to a separate thread through pipe and doing all the stuff asynchronously
|
||||
@ -597,8 +596,10 @@ void BaseDaemon::reloadConfiguration()
|
||||
}
|
||||
|
||||
|
||||
/// For creating and destroying unique_ptr of incomplete type.
|
||||
BaseDaemon::BaseDaemon() = default;
|
||||
BaseDaemon::BaseDaemon()
|
||||
{
|
||||
checkRequiredInstructions();
|
||||
}
|
||||
|
||||
|
||||
BaseDaemon::~BaseDaemon()
|
||||
@ -609,6 +610,127 @@ BaseDaemon::~BaseDaemon()
|
||||
}
|
||||
|
||||
|
||||
enum class InstructionFail
|
||||
{
|
||||
NONE = 0,
|
||||
SSE3 = 1,
|
||||
SSSE3 = 2,
|
||||
SSE4_1 = 3,
|
||||
SSE4_2 = 4,
|
||||
AVX = 5,
|
||||
AVX2 = 6,
|
||||
AVX512 = 7
|
||||
};
|
||||
|
||||
static std::string instructionFailToString(InstructionFail fail)
|
||||
{
|
||||
switch(fail)
|
||||
{
|
||||
case InstructionFail::NONE:
|
||||
return "NONE";
|
||||
case InstructionFail::SSE3:
|
||||
return "SSE3";
|
||||
case InstructionFail::SSSE3:
|
||||
return "SSSE3";
|
||||
case InstructionFail::SSE4_1:
|
||||
return "SSE4.1";
|
||||
case InstructionFail::SSE4_2:
|
||||
return "SSE4.2";
|
||||
case InstructionFail::AVX:
|
||||
return "AVX";
|
||||
case InstructionFail::AVX2:
|
||||
return "AVX2";
|
||||
case InstructionFail::AVX512:
|
||||
return "AVX512";
|
||||
}
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
|
||||
static sigjmp_buf jmpbuf;
|
||||
|
||||
static void sigIllCheckHandler(int sig, siginfo_t * info, void * context)
|
||||
{
|
||||
siglongjmp(jmpbuf, 1);
|
||||
}
|
||||
|
||||
/// Check if necessary sse extensions are available by trying to execute some sse instructions.
|
||||
/// If instruction is unavailable, SIGILL will be sent by kernel.
|
||||
static void checkRequiredInstructions(volatile InstructionFail & fail)
|
||||
{
|
||||
#if __SSE3__
|
||||
fail = InstructionFail::SSE3;
|
||||
__asm__ volatile ("addsubpd %%xmm0, %%xmm0" : : : "xmm0");
|
||||
#endif
|
||||
|
||||
#if __SSSE3__
|
||||
fail = InstructionFail::SSSE3;
|
||||
__asm__ volatile ("pabsw %%xmm0, %%xmm0" : : : "xmm0");
|
||||
|
||||
#endif
|
||||
|
||||
#if __SSE4_1__
|
||||
fail = InstructionFail::SSE4_1;
|
||||
__asm__ volatile ("pmaxud %%xmm0, %%xmm0" : : : "xmm0");
|
||||
#endif
|
||||
|
||||
#if __SSE4_2__
|
||||
fail = InstructionFail::SSE4_2;
|
||||
__asm__ volatile ("pcmpgtq %%xmm0, %%xmm0" : : : "xmm0");
|
||||
#endif
|
||||
|
||||
#if __AVX__
|
||||
fail = InstructionFail::AVX;
|
||||
__asm__ volatile ("vaddpd %%ymm0, %%ymm0" : : : "ymm0");
|
||||
#endif
|
||||
|
||||
#if __AVX2__
|
||||
fail = InstructionFail::AVX2;
|
||||
__asm__ volatile ("vpabsw %%ymm0, %%ymm0" : : : "ymm0");
|
||||
#endif
|
||||
|
||||
#if __AVX512__
|
||||
fail = InstructionFail::AVX512;
|
||||
__asm__ volatile ("vpabsw %%zmm0, %%zmm0" : : : "zmm0");
|
||||
#endif
|
||||
|
||||
fail = InstructionFail::NONE;
|
||||
}
|
||||
|
||||
|
||||
void BaseDaemon::checkRequiredInstructions()
|
||||
{
|
||||
struct sigaction sa{};
|
||||
struct sigaction sa_old{};
|
||||
sa.sa_sigaction = sigIllCheckHandler;
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
auto signal = SIGILL;
|
||||
if (sigemptyset(&sa.sa_mask) != 0
|
||||
|| sigaddset(&sa.sa_mask, signal) != 0
|
||||
|| sigaction(signal, &sa, &sa_old) != 0)
|
||||
{
|
||||
std::cerr << "Can not set signal handler\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
volatile InstructionFail fail = InstructionFail::NONE;
|
||||
|
||||
if (sigsetjmp(jmpbuf, 1))
|
||||
{
|
||||
std::cerr << "Instruction check fail. There is no " << instructionFailToString(fail) << " instruction set\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
::checkRequiredInstructions(fail);
|
||||
|
||||
if (sigaction(signal, &sa_old, nullptr))
|
||||
{
|
||||
std::cerr << "Can not set signal handler\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BaseDaemon::terminate()
|
||||
{
|
||||
getTaskManager().cancelAll();
|
||||
|
Loading…
Reference in New Issue
Block a user