292 lines · c
1//===- OmptAsserter.h - Asserter-related classes, enums, etc. ---*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// Contains all asserter-related class declarations and important enums.11///12//===----------------------------------------------------------------------===//13 14#ifndef OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTASSERTER_H15#define OPENMP_TOOLS_OMPTEST_INCLUDE_OMPTASSERTER_H16 17#include "Logging.h"18#include "OmptAssertEvent.h"19 20#include <cassert>21#include <iostream>22#include <map>23#include <mutex>24#include <set>25#include <vector>26 27namespace omptest {28 29// Forward declaration.30class OmptEventGroupInterface;31 32enum class AssertMode { Strict, Relaxed };33enum class AssertState { Pass, Fail };34 35/// General base class for the subscriber/notification pattern in36/// OmptCallbackHandler. Derived classes need to implement the notify method.37class OmptListener {38public:39 virtual ~OmptListener() = default;40 41 /// Called for each registered OMPT event of the OmptCallbackHandler42 virtual void notify(omptest::OmptAssertEvent &&AE) = 0;43 44 /// Control whether this asserter should be considered 'active'.45 void setActive(bool Enabled);46 47 /// Check if this asserter is considered 'active'.48 bool isActive();49 50 /// Check if the given event type is from the set of suppressed event types.51 bool isSuppressedEventType(omptest::internal::EventTy EvTy);52 53 /// Remove the given event type to the set of suppressed events.54 void permitEvent(omptest::internal::EventTy EvTy);55 56 /// Add the given event type to the set of suppressed events.57 void suppressEvent(omptest::internal::EventTy EvTy);58 59private:60 bool Active{true};61 62 // Add event types to the set of suppressed events by default.63 std::set<omptest::internal::EventTy> SuppressedEvents{64 omptest::internal::EventTy::ThreadBegin,65 omptest::internal::EventTy::ThreadEnd,66 omptest::internal::EventTy::ParallelBegin,67 omptest::internal::EventTy::ParallelEnd,68 omptest::internal::EventTy::Work,69 omptest::internal::EventTy::Dispatch,70 omptest::internal::EventTy::TaskCreate,71 omptest::internal::EventTy::Dependences,72 omptest::internal::EventTy::TaskDependence,73 omptest::internal::EventTy::TaskSchedule,74 omptest::internal::EventTy::ImplicitTask,75 omptest::internal::EventTy::Masked,76 omptest::internal::EventTy::SyncRegion,77 omptest::internal::EventTy::MutexAcquire,78 omptest::internal::EventTy::Mutex,79 omptest::internal::EventTy::NestLock,80 omptest::internal::EventTy::Flush,81 omptest::internal::EventTy::Cancel};82};83 84/// Base class for asserting on OMPT events85class OmptAsserter : public OmptListener {86public:87 OmptAsserter();88 virtual ~OmptAsserter() = default;89 90 /// Add an event to the asserter's internal data structure.91 virtual void insert(omptest::OmptAssertEvent &&AE);92 93 /// Called from the CallbackHandler with a corresponding AssertEvent to which94 /// callback was handled.95 void notify(omptest::OmptAssertEvent &&AE) override;96 97 /// Implemented in subclasses to implement what should actually be done with98 /// the notification.99 virtual void notifyImpl(omptest::OmptAssertEvent &&AE) = 0;100 101 /// Get the number of currently remaining events, with: ObserveState::Always.102 virtual size_t getRemainingEventCount() = 0;103 104 /// Get the total number of received, effective notifications.105 int getNotificationCount() { return NumNotifications; }106 107 /// Get the total number of successful assertion checks.108 int getSuccessfulAssertionCount() { return NumSuccessfulAsserts; }109 110 /// Get the asserter's current operationmode: e.g.: Strict or Relaxed.111 AssertMode getOperationMode() { return OperationMode; }112 113 /// Return the asserter's current state.114 omptest::AssertState getState() { return State; }115 116 /// Determine and return the asserter's state.117 virtual omptest::AssertState checkState();118 119 /// Accessor for the event group interface.120 std::shared_ptr<OmptEventGroupInterface> getEventGroups() const {121 return EventGroups;122 }123 124 /// Accessor for the event group interface.125 std::shared_ptr<logging::Logger> getLog() const { return Log; }126 127 /// Check the observed events' group association. If the event indicates the128 /// begin/end of an OpenMP target region, we will create/deprecate the129 /// expected event's group. Return true if the expected event group exists130 /// (and is active), otherwise: false. Note: BufferRecords may also match with131 /// deprecated groups as they may be delivered asynchronously.132 bool verifyEventGroups(const omptest::OmptAssertEvent &ExpectedEvent,133 const omptest::OmptAssertEvent &ObservedEvent);134 135 /// Set the asserter's mode of operation w.r.t. assertion.136 void setOperationMode(AssertMode Mode);137 138protected:139 /// The asserter's current state.140 omptest::AssertState State{omptest::AssertState::Pass};141 142 /// Mutex to avoid data races w.r.t. event notifications and/or insertions.143 std::mutex AssertMutex;144 145 /// Pointer to the OmptEventGroupInterface.146 std::shared_ptr<OmptEventGroupInterface> EventGroups{nullptr};147 148 /// Pointer to the logging instance.149 std::shared_ptr<logging::Logger> Log{nullptr};150 151 /// Operation mode during assertion / notification.152 AssertMode OperationMode{AssertMode::Strict};153 154 /// The total number of effective notifications. For example, if specific155 /// notifications are to be ignored, they will not count towards this total.156 int NumNotifications{0};157 158 /// The number of successful assertion checks.159 int NumSuccessfulAsserts{0};160 161private:162 /// Mutex for creating/accessing the singleton members163 static std::mutex StaticMemberAccessMutex;164 165 /// Static member to manage the singleton event group interface instance166 static std::weak_ptr<OmptEventGroupInterface> EventGroupInterfaceInstance;167 168 /// Static member to manage the singleton logging instance169 static std::weak_ptr<logging::Logger> LoggingInstance;170};171 172/// Class that can assert in a sequenced fashion, i.e., events have to occur in173/// the order they were registered174class OmptSequencedAsserter : public OmptAsserter {175public:176 OmptSequencedAsserter() : OmptAsserter(), NextEvent(0) {}177 178 /// Add the event to the in-sequence set of events that the asserter should179 /// check for.180 void insert(omptest::OmptAssertEvent &&AE) override;181 182 /// Implements the asserter's actual logic183 virtual void notifyImpl(omptest::OmptAssertEvent &&AE) override;184 185 size_t getRemainingEventCount() override;186 187 omptest::AssertState checkState() override;188 189 bool AssertionSuspended{false};190 191protected:192 /// Notification helper function, implementing SyncPoint logic. Returns true193 /// in case of consumed event, indicating early exit of notification.194 bool consumeSyncPoint(const omptest::OmptAssertEvent &AE);195 196 /// Notification helper function, implementing excess event notification197 /// logic. Returns true when no more events were expected, indicating early198 /// exit of notification.199 bool checkExcessNotify(const omptest::OmptAssertEvent &AE);200 201 /// Notification helper function, implementing Suspend logic. Returns true202 /// in case of consumed event, indicating early exit of notification.203 bool consumeSuspend();204 205 /// Notification helper function, implementing regular event notification206 /// logic. Returns true when a matching event was encountered, indicating207 /// early exit of notification.208 bool consumeRegularEvent(const omptest::OmptAssertEvent &AE);209 210public:211 /// Index of the next, expected event.212 size_t NextEvent{0};213 std::vector<omptest::OmptAssertEvent> Events{};214};215 216/// Class that asserts with set semantics, i.e., unordered217struct OmptEventAsserter : public OmptAsserter {218 OmptEventAsserter() : OmptAsserter(), NumEvents(0), Events() {}219 220 /// Add the event to the set of events that the asserter should check for.221 void insert(omptest::OmptAssertEvent &&AE) override;222 223 /// Implements the asserter's logic224 virtual void notifyImpl(omptest::OmptAssertEvent &&AE) override;225 226 size_t getRemainingEventCount() override;227 228 omptest::AssertState checkState() override;229 230 size_t NumEvents{0};231 232 /// For now use vector (but do set semantics)233 // TODO std::unordered_set?234 std::vector<omptest::OmptAssertEvent> Events{};235};236 237/// Class that reports the occurred events238class OmptEventReporter : public OmptListener {239public:240 OmptEventReporter(std::ostream &OutStream = std::cout)241 : OutStream(OutStream) {}242 243 /// Called from the CallbackHandler with a corresponding AssertEvent to which244 /// callback was handled.245 void notify(omptest::OmptAssertEvent &&AE) override;246 247private:248 std::ostream &OutStream;249};250 251/// This class provides the members and methods to manage event groups and252/// SyncPoints in conjunction with asserters. Most importantly it maintains a253/// coherent view of active and past events or SyncPoints.254class OmptEventGroupInterface {255public:256 OmptEventGroupInterface() = default;257 ~OmptEventGroupInterface() = default;258 259 /// Non-copyable and non-movable260 OmptEventGroupInterface(const OmptEventGroupInterface &) = delete;261 OmptEventGroupInterface &operator=(const OmptEventGroupInterface &) = delete;262 OmptEventGroupInterface(OmptEventGroupInterface &&) = delete;263 OmptEventGroupInterface &operator=(OmptEventGroupInterface &&) = delete;264 265 /// Add given group to the set of active event groups. Effectively connecting266 /// the given groupname (expected) with a target region id (observed).267 bool addActiveEventGroup(const std::string &GroupName,268 omptest::AssertEventGroup Group);269 270 /// Move given group from the set of active event groups to the set of271 /// previously active event groups.272 bool deprecateActiveEventGroup(const std::string &GroupName);273 274 /// Check if given group is currently part of the active event groups.275 bool checkActiveEventGroups(const std::string &GroupName,276 omptest::AssertEventGroup Group);277 278 /// Check if given group is currently part of the deprecated event groups.279 bool checkDeprecatedEventGroups(const std::string &GroupName,280 omptest::AssertEventGroup Group);281 282private:283 mutable std::mutex GroupMutex;284 std::map<std::string, omptest::AssertEventGroup> ActiveEventGroups{};285 std::map<std::string, omptest::AssertEventGroup> DeprecatedEventGroups{};286 std::set<std::string> EncounteredSyncPoints{};287};288 289} // namespace omptest290 291#endif292