Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:27:41

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2022 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 http://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/Utilities/Helpers.hpp"
0012 
0013 #include <array>
0014 #include <atomic>
0015 #include <csignal>
0016 #include <cstddef>
0017 #include <limits>
0018 #include <memory>
0019 #include <mutex>
0020 #include <stack>
0021 
0022 #include <boost/container/static_vector.hpp>
0023 #include <boost/stacktrace/stacktrace_fwd.hpp>
0024 
0025 namespace Acts {
0026 
0027 enum class FpeType : uint32_t {
0028   INTDIV = FPE_INTDIV,
0029   INTOVF = FPE_INTOVF,
0030   FLTDIV = FPE_FLTDIV,
0031   FLTOVF = FPE_FLTOVF,
0032   FLTUND = FPE_FLTUND,
0033   FLTRES = FPE_FLTRES,
0034   FLTINV = FPE_FLTINV,
0035   FLTSUB = FPE_FLTSUB,
0036 };
0037 
0038 std::ostream &operator<<(std::ostream &os, FpeType type);
0039 
0040 class FpeMonitor {
0041  public:
0042   struct Buffer {
0043     Buffer(std::size_t bufferSize)
0044         : m_data{std::make_unique<std::byte[]>(bufferSize)},
0045           m_size{bufferSize} {}
0046 
0047     Buffer(const Buffer &) = delete;
0048     Buffer(Buffer &&other) {
0049       m_data = std::move(other.m_data);
0050       m_size = other.m_size;
0051       m_offset = other.m_offset;
0052       other.m_size = 0;
0053       other.m_offset = 0;
0054     }
0055 
0056     std::pair<void *, std::size_t> next() {
0057       return {m_data.get() + m_offset, m_size - m_offset};
0058     }
0059 
0060     void pushOffset(std::size_t offset) {
0061       assert(m_offset + offset < m_size);
0062       m_offset = offset;
0063     }
0064 
0065     void reset() { m_offset = 0; }
0066 
0067     std::size_t size() const { return m_size; }
0068     std::size_t offset() const { return m_offset; }
0069 
0070     std::byte *data() { return m_data.get(); }
0071 
0072    private:
0073     std::unique_ptr<std::byte[]> m_data;
0074     std::size_t m_size{};
0075     std::size_t m_offset{};
0076   };
0077 
0078   struct Result {
0079     struct FpeInfo {
0080       std::size_t count;
0081       FpeType type;
0082       std::shared_ptr<const boost::stacktrace::stacktrace> st;
0083 
0084       FpeInfo(std::size_t countIn, FpeType typeIn,
0085               std::shared_ptr<const boost::stacktrace::stacktrace> stIn);
0086       ~FpeInfo();
0087     };
0088 
0089     Result merged(const Result &with) const;
0090     void merge(const Result &with);
0091 
0092     bool encountered(FpeType type) const;
0093     unsigned int count(FpeType type) const;
0094 
0095     const std::vector<FpeInfo> &stackTraces() const;
0096     unsigned int numStackTraces() const;
0097 
0098     void deduplicate();
0099 
0100     bool contains(FpeType type, const boost::stacktrace::stacktrace &st) const;
0101 
0102     void summary(
0103         std::ostream &os,
0104         std::size_t depth = std::numeric_limits<std::size_t>::max()) const;
0105 
0106     Result() = default;
0107 
0108     operator bool() const { return !m_stracktraces.empty(); }
0109 
0110     void add(Acts::FpeType type, void *stackPtr, std::size_t bufferSize);
0111 
0112    private:
0113     std::vector<FpeInfo> m_stracktraces;
0114     std::array<unsigned int, 32> m_counts{};
0115 
0116     friend FpeMonitor;
0117   };
0118 
0119   FpeMonitor();
0120   explicit FpeMonitor(int excepts);
0121   FpeMonitor(FpeMonitor &&other) = default;
0122   ~FpeMonitor();
0123 
0124   Result &result();
0125 
0126   void consumeRecorded();
0127 
0128   void rearm();
0129 
0130   static std::string stackTraceToString(const boost::stacktrace::stacktrace &st,
0131                                         std::size_t depth);
0132   static std::string getSourceLocation(const boost::stacktrace::frame &frame);
0133 
0134  private:
0135   void enable();
0136   void disable();
0137 
0138   static void ensureSignalHandlerInstalled();
0139   static void signalHandler(int signal, siginfo_t *si, void *ctx);
0140 
0141   struct GlobalState {
0142     std::atomic_bool isSignalHandlerInstalled{false};
0143     std::mutex mutex{};
0144   };
0145 
0146   static std::stack<FpeMonitor *> &stack();
0147   static GlobalState &globalState();
0148 
0149   int m_excepts = 0;
0150 
0151   Result m_result;
0152 
0153   Buffer m_buffer{65536};
0154 
0155   boost::container::static_vector<std::tuple<FpeType, void *, std::size_t>, 128>
0156       m_recorded;
0157 };
0158 
0159 }  // namespace Acts