Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-03-28 07:46:14

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include <cfenv>
0010 #include <csignal>
0011 #include <cstddef>
0012 #include <cstdint>
0013 #include <optional>
0014 
0015 #include <ucontext.h>
0016 
0017 #include "FpeMonitorPlatform.hpp"
0018 
0019 #if !defined(__linux__) || !defined(__x86_64__)
0020 #error "This translation unit is only valid for Linux x86_64"
0021 #endif
0022 
0023 namespace ActsPlugins {
0024 
0025 namespace {
0026 
0027 // Linux x86_64 signal context exposes raw x87/SSE control and status words.
0028 // These masks are used when disabling the current trap and clearing sticky
0029 // exception bits in the interrupted context.
0030 constexpr std::uint16_t kFpuExceptionMask = 0x3f;
0031 constexpr std::uint16_t kFpuStatusFlags = 0xff;
0032 constexpr std::uint32_t kSseStatusFlags = kFpuExceptionMask;
0033 
0034 }  // namespace
0035 
0036 bool detail::isRuntimeSupported() {
0037   // Linux x86_64 supports feenableexcept/fedisableexcept and SIGFPE si_code
0038   // decoding, so trapping mode is fully available.
0039   return true;
0040 }
0041 
0042 std::optional<FpeType> detail::decodeFpeType(int signal, const siginfo_t* si,
0043                                              void* ctx) {
0044   // This backend only installs SIGFPE handlers. si_code carries the exception
0045   // category we expose in FpeType.
0046   static_cast<void>(ctx);
0047   if (signal != SIGFPE || si == nullptr) {
0048     return std::nullopt;
0049   }
0050   return fpeTypeFromSiCode(si->si_code);
0051 }
0052 
0053 void detail::clearPendingExceptions(int excepts) {
0054   // Clear stale sticky flags before changing trap state.
0055   std::feclearexcept(excepts);
0056 }
0057 
0058 void detail::enableExceptions(int excepts) {
0059   // glibc helper enables hardware traps for requested FE_* bits.
0060   feenableexcept(excepts);
0061 }
0062 
0063 void detail::disableExceptions(int excepts) {
0064   // glibc helper disables hardware traps for requested FE_* bits.
0065   fedisableexcept(excepts);
0066 }
0067 
0068 void detail::maskTrapsInSignalContext(void* ctx, FpeType type) {
0069   // Linux reports enough detail in si_code, so "type" is currently unused.
0070   // We mask all x87 trap bits and clear pending x87/SSE status flags to allow
0071   // safe unwinding past the faulting instruction.
0072   static_cast<void>(type);
0073   auto* uc = static_cast<ucontext_t*>(ctx);
0074   __uint16_t* cw = &uc->uc_mcontext.fpregs->cwd;
0075   *cw |= kFpuExceptionMask;
0076 
0077   __uint16_t* sw = &uc->uc_mcontext.fpregs->swd;
0078   *sw &= ~kFpuStatusFlags;
0079 
0080   __uint32_t* mxcsr = &uc->uc_mcontext.fpregs->mxcsr;
0081   *mxcsr |= ((*mxcsr & kSseStatusFlags) << 7);
0082   *mxcsr &= ~kSseStatusFlags;
0083 }
0084 
0085 std::size_t detail::captureStackFromSignalContext(void* ctx, void* buffer,
0086                                                   std::size_t bufferBytes) {
0087   // Linux x86_64 currently falls back to boost::stacktrace::safe_dump_to in
0088   // the signal handler, so no context-based frame extraction is attempted here.
0089   static_cast<void>(ctx);
0090   static_cast<void>(buffer);
0091   static_cast<void>(bufferBytes);
0092   return 0;
0093 }
0094 
0095 std::size_t detail::safeDumpSkipFrames() {
0096   // Skip two frames to hide signal-handler and dump-helper internals.
0097   return 2;
0098 }
0099 
0100 bool detail::shouldFailFastOnUnknownSignal() {
0101   // Unknown/unsupported signal payloads are tolerated and ignored on Linux.
0102   return false;
0103 }
0104 
0105 void detail::installSignalHandlers(void (*handler)(int, siginfo_t*, void*)) {
0106   // Linux only needs SIGFPE for floating-point trap monitoring.
0107   struct sigaction action{};
0108   action.sa_sigaction = handler;
0109   action.sa_flags = SA_SIGINFO;
0110   sigaction(SIGFPE, &action, nullptr);
0111 }
0112 
0113 }  // namespace ActsPlugins