diff --git a/IntelPresentMon/CommonUtilities/log/IdentificationTable.cpp b/IntelPresentMon/CommonUtilities/log/IdentificationTable.cpp index 850dc8ad..7cc896cc 100644 --- a/IntelPresentMon/CommonUtilities/log/IdentificationTable.cpp +++ b/IntelPresentMon/CommonUtilities/log/IdentificationTable.cpp @@ -51,18 +51,6 @@ namespace pmon::util::log } } - IdentificationTableCallbacks IdentificationTable::MakeForwardingCallbacks() noexcept - { - return { - .addThread = [](uint32_t tid, uint32_t pid, const char* name) { - IdentificationTable::AddThread(tid, pid, name ? name : ""); - }, - .addProcess = [](uint32_t pid, const char* name) { - IdentificationTable::AddProcess(pid, name ? name : ""); - } - }; - } - void IdentificationTable::RegisterSink(std::shared_ptr pSink) noexcept { try { diff --git a/IntelPresentMon/CommonUtilities/log/IdentificationTable.h b/IntelPresentMon/CommonUtilities/log/IdentificationTable.h index 386b4c5b..1a0b7ab6 100644 --- a/IntelPresentMon/CommonUtilities/log/IdentificationTable.h +++ b/IntelPresentMon/CommonUtilities/log/IdentificationTable.h @@ -16,16 +16,6 @@ namespace pmon::util::log virtual void AddProcess(uint32_t pid, std::string name) = 0; }; - struct IdentificationTableCallbacks - { - void(*addThread)(uint32_t tid, uint32_t pid, const char* name) = nullptr; - void(*addProcess)(uint32_t pid, const char* name) = nullptr; - operator bool() const noexcept - { - return addThread || addProcess; - } - }; - class IdentificationTable { public: @@ -54,7 +44,6 @@ namespace pmon::util::log static std::optional LookupThread(uint32_t tid) noexcept; static std::optional LookupProcess(uint32_t pid) noexcept; static Bulk GetBulk() noexcept; - static IdentificationTableCallbacks MakeForwardingCallbacks() noexcept; static void RegisterSink(std::shared_ptr pSink) noexcept; static void UnregisterSink(const IIdentificationSink* pSink) noexcept; static IdentificationTable* GetPtr() noexcept; diff --git a/IntelPresentMon/Core/source/infra/LogSetup.cpp b/IntelPresentMon/Core/source/infra/LogSetup.cpp index 113c5906..432438e5 100644 --- a/IntelPresentMon/Core/source/infra/LogSetup.cpp +++ b/IntelPresentMon/Core/source/infra/LogSetup.cpp @@ -131,7 +131,8 @@ namespace p2c // connect dll channel and id table to exe, get access to global settings in dll LoggingSingletons getters; if (linkMiddlewareLogs) { - getters = pmLinkLogging_(pChan, IdentificationTable::MakeForwardingCallbacks()); + getters = pmLinkLogging_(pChan, []() -> IdentificationTable& { + return IdentificationTable::Get_(); }); } // set the global policy settings if (opt.logLevel) { diff --git a/IntelPresentMon/PresentMonAPI2/Internal.h b/IntelPresentMon/PresentMonAPI2/Internal.h index 00212ada..1347bd21 100644 --- a/IntelPresentMon/PresentMonAPI2/Internal.h +++ b/IntelPresentMon/PresentMonAPI2/Internal.h @@ -28,7 +28,7 @@ struct LoggingSingletons // return getters for config singletons in the dll to config from the exe PRESENTMON_API2_EXPORT LoggingSingletons pmLinkLogging_( std::shared_ptr pChannel, - pmon::util::log::IdentificationTableCallbacks idTableCallbacks); + std::function getIdTable); // disconnect any logging bridge created by pmLinkLogging_ PRESENTMON_API2_EXPORT void pmUnlinkLogging_() noexcept; // function to flush the dll's log channel worker queue when before exiting diff --git a/IntelPresentMon/PresentMonAPI2/PresentMonAPI.cpp b/IntelPresentMon/PresentMonAPI2/PresentMonAPI.cpp index 57a04293..4bcdea19 100644 --- a/IntelPresentMon/PresentMonAPI2/PresentMonAPI.cpp +++ b/IntelPresentMon/PresentMonAPI2/PresentMonAPI.cpp @@ -102,7 +102,7 @@ PRESENTMON_API2_EXPORT _CrtMemState pmCreateHeapCheckpoint_() PRESENTMON_API2_EXPORT LoggingSingletons pmLinkLogging_( std::shared_ptr pChannel, - pmon::util::log::IdentificationTableCallbacks idTableCallbacks) + std::function getIdTable) { using namespace util::log; // set api dll default logging channel to copy to exe logging channel @@ -112,33 +112,27 @@ PRESENTMON_API2_EXPORT LoggingSingletons pmLinkLogging_( IdentificationTable::UnregisterSink(pLinkedIdTableSink_.get()); pLinkedIdTableSink_.reset(); } - if (idTableCallbacks) { + if (getIdTable) { class Sink : public IIdentificationSink { public: - Sink(IdentificationTableCallbacks callbacks) + Sink(std::function getTable) : - callbacks_{ callbacks } + getTable_{ std::move(getTable) } {} void AddThread(uint32_t tid, uint32_t pid, std::string name) override { - if (callbacks_.addThread) { - callbacks_.addThread(tid, pid, name.c_str()); - } + getTable_().AddThread_(tid, pid, name); } void AddProcess(uint32_t pid, std::string name) override { - if (callbacks_.addProcess) { - callbacks_.addProcess(pid, name.c_str()); - } + getTable_().AddProcess_(pid, name); } private: - IdentificationTableCallbacks callbacks_; + std::function getTable_; }; - pLinkedIdTableSink_ = std::make_shared(idTableCallbacks); - // hooking exe table up so that it receives updates + pLinkedIdTableSink_ = std::make_shared(getIdTable); IdentificationTable::RegisterSink(pLinkedIdTableSink_); - // copying current contents of table to exe const auto bulk = IdentificationTable::GetBulk(); for (auto& t : bulk.threads) { pLinkedIdTableSink_->AddThread(t.tid, t.pid, t.name); diff --git a/IntelPresentMon/PresentMonAPI2Loader/Implementation.cpp b/IntelPresentMon/PresentMonAPI2Loader/Implementation.cpp index 88f5e18a..3f2962bd 100644 --- a/IntelPresentMon/PresentMonAPI2Loader/Implementation.cpp +++ b/IntelPresentMon/PresentMonAPI2Loader/Implementation.cpp @@ -59,7 +59,7 @@ PM_STATUS(*pFunc_pmDiagnosticUnblockWaitingThread_)() = nullptr; // pointers to runtime-resolved internal functions _CrtMemState(*pFunc_pmCreateHeapCheckpoint__)() = nullptr; LoggingSingletons(*pFunc_pmLinkLogging__)(std::shared_ptr, - pmon::util::log::IdentificationTableCallbacks) = nullptr; + std::function) = nullptr; void(*pFunc_pmUnlinkLogging__)() = nullptr; void(*pFunc_pmFlushEntryPoint__)() = nullptr; void(*pFunc_pmSetupODSLogging__)(PM_DIAGNOSTIC_LEVEL, PM_DIAGNOSTIC_LEVEL, bool) = nullptr; @@ -79,7 +79,7 @@ bool middlewareLoadedSuccessfully_ = false; // loader-internal implementation functions // inner impl of method for deriving the mangled name of a cpp-linkage function and loading it -void* GetCppProcAddress_Impl_(HMODULE h,const char* name, const char* mangledEmbeddedSignature) +void* GetCppProcAddress_Impl_(HMODULE h, const char* name, const char* mangledEmbeddedSignature, bool required) { // don't bother including receiving template function name std::string Signature = mangledEmbeddedSignature + 22; @@ -92,13 +92,20 @@ void* GetCppProcAddress_Impl_(HMODULE h,const char* name, const char* mangledEmb if (auto pFunc = GetProcAddress(h, funName.c_str())) { return pFunc; } - throw LoaderExcept_(PM_STATUS_MIDDLEWARE_MISSING_ENDPOINT); + if (required) { + throw LoaderExcept_(PM_STATUS_MIDDLEWARE_MISSING_ENDPOINT); + } + return nullptr; } // load a cpp linkage function from a dll module template -F GetCppProcAddress_(HMODULE h, const char* name) +F GetCppProcAddress_(HMODULE h, const char* name, bool required = true) { - return reinterpret_cast(GetCppProcAddress_Impl_(h, name, __FUNCDNAME__)); + void* pFunc = GetCppProcAddress_Impl_(h, name, __FUNCDNAME__, required); + if (!pFunc) { + return nullptr; + } + return reinterpret_cast(pFunc); } // load a c-linkage function FARPROC GetProcAddress_(HMODULE h, const char* name) @@ -134,7 +141,7 @@ PRESENTMON_API2_EXPORT PM_STATUS LoadLibrary_(bool versionOnly = false) } } #define RESOLVE(f) pFunc_##f##_ = reinterpret_cast(GetProcAddress_(hMod_, #f)) -#define RESOLVE_CPP(f) pFunc_##f##_ = GetCppProcAddress_(hMod_, #f) +#define RESOLVE_CPP_OPTIONAL(f) pFunc_##f##_ = GetCppProcAddress_(hMod_, #f, false) // resolve version endpoint first as it is needed here RESOLVE(pmGetApiVersion); // if this load operation was instigated by calling version, don't do version check or load other endpoints @@ -188,14 +195,14 @@ PRESENTMON_API2_EXPORT PM_STATUS LoadLibrary_(bool versionOnly = false) RESOLVE(pmDiagnosticFreeMessage); RESOLVE(pmDiagnosticWaitForMessage); RESOLVE(pmDiagnosticUnblockWaitingThread); - // internal - RESOLVE_CPP(pmCreateHeapCheckpoint_); - RESOLVE_CPP(pmLinkLogging_); - RESOLVE_CPP(pmUnlinkLogging_); - RESOLVE_CPP(pmFlushEntryPoint_); - RESOLVE_CPP(pmSetupODSLogging_); - RESOLVE_CPP(pmSetupFileLogging_); - RESOLVE_CPP(pmStopPlayback_); + // internal (optional: older middleware may omit refactored hooks) + RESOLVE_CPP_OPTIONAL(pmCreateHeapCheckpoint_); + RESOLVE_CPP_OPTIONAL(pmLinkLogging_); + RESOLVE_CPP_OPTIONAL(pmUnlinkLogging_); + RESOLVE_CPP_OPTIONAL(pmFlushEntryPoint_); + RESOLVE_CPP_OPTIONAL(pmSetupODSLogging_); + RESOLVE_CPP_OPTIONAL(pmSetupFileLogging_); + RESOLVE_CPP_OPTIONAL(pmStopPlayback_); // if we make it here then we have succeeded middlewareLoadResult_ = PM_STATUS_SUCCESS; } @@ -339,21 +346,27 @@ PRESENTMON_API2_EXPORT _CrtMemState pmCreateHeapCheckpoint_() throw LoaderExcept_(status); } } + if (!pFunc_pmCreateHeapCheckpoint__) { + throw LoaderExcept_(PM_STATUS_MIDDLEWARE_MISSING_ENDPOINT); + } return pFunc_pmCreateHeapCheckpoint__(); } PRESENTMON_API2_EXPORT LoggingSingletons pmLinkLogging_(std::shared_ptr pChannel, - pmon::util::log::IdentificationTableCallbacks idTableCallbacks) + std::function getIdTable) { if (!middlewareLoadedSuccessfully_) { if (auto status = LoadLibrary_(); status != PM_STATUS_SUCCESS) { throw LoaderExcept_(status); } } - return pFunc_pmLinkLogging__(pChannel, idTableCallbacks); + if (!pFunc_pmLinkLogging__) { + return {}; + } + return pFunc_pmLinkLogging__(pChannel, std::move(getIdTable)); } PRESENTMON_API2_EXPORT void pmUnlinkLogging_() noexcept { - if (middlewareLoadedSuccessfully_) { + if (middlewareLoadedSuccessfully_ && pFunc_pmUnlinkLogging__) { pFunc_pmUnlinkLogging__(); } } @@ -363,7 +376,7 @@ PRESENTMON_API2_EXPORT void pmFlushEntryPoint_() noexcept // flush is called even in cases where the dll hasn't been loaded // allow it to be elided in this case since it has no effect without // other functions being called previously anyways - if (middlewareLoadedSuccessfully_) { + if (middlewareLoadedSuccessfully_ && pFunc_pmFlushEntryPoint__) { pFunc_pmFlushEntryPoint__(); } } @@ -375,6 +388,9 @@ PRESENTMON_API2_EXPORT void pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL logLevel, throw LoaderExcept_(status); } } + if (!pFunc_pmSetupODSLogging__) { + throw LoaderExcept_(PM_STATUS_MIDDLEWARE_MISSING_ENDPOINT); + } pFunc_pmSetupODSLogging__(logLevel, stackTraceLevel, exceptionTrace); } PRESENTMON_API2_EXPORT PM_STATUS pmDiagnosticSetup(const PM_DIAGNOSTIC_CONFIGURATION* pConfig) @@ -437,12 +453,18 @@ PRESENTMON_API2_EXPORT PM_STATUS pmSetupFileLogging_(const char* file, PM_DIAGNO PM_DIAGNOSTIC_LEVEL stackTraceLevel, bool exceptionTrace) { LoadEndpointsIfEmpty_(); + if (!pFunc_pmSetupFileLogging__) { + return PM_STATUS_MIDDLEWARE_MISSING_ENDPOINT; + } return pFunc_pmSetupFileLogging__(file, logLevel, stackTraceLevel, exceptionTrace); } PRESENTMON_API2_EXPORT PM_STATUS pmStopPlayback_(PM_SESSION_HANDLE hSession) { LoadEndpointsIfEmpty_(); + if (!pFunc_pmStopPlayback__) { + return PM_STATUS_MIDDLEWARE_MISSING_ENDPOINT; + } return pFunc_pmStopPlayback__(hSession); } diff --git a/IntelPresentMon/PresentMonAPI2Tests/Logging.cpp b/IntelPresentMon/PresentMonAPI2Tests/Logging.cpp index e5587052..41d19998 100644 --- a/IntelPresentMon/PresentMonAPI2Tests/Logging.cpp +++ b/IntelPresentMon/PresentMonAPI2Tests/Logging.cpp @@ -171,7 +171,8 @@ namespace pmon::test if (!linkState.linked) { linkState.getters = pmLinkLogging_( pChannel, - util::log::IdentificationTable::MakeForwardingCallbacks()); + []() -> util::log::IdentificationTable& { + return util::log::IdentificationTable::Get_(); }); linkState.linked = true; } gettersCopy = linkState.getters; diff --git a/IntelPresentMon/SampleClient/LogSetup.cpp b/IntelPresentMon/SampleClient/LogSetup.cpp index b99e8294..06e98b04 100644 --- a/IntelPresentMon/SampleClient/LogSetup.cpp +++ b/IntelPresentMon/SampleClient/LogSetup.cpp @@ -64,7 +64,8 @@ namespace p2sam // get the channel to work on it auto pChan = GetDefaultChannel(); // connect dll channel and id table to exe, get access to global settings in dll - const auto getters = pmLinkLogging_(pChan, IdentificationTable::MakeForwardingCallbacks()); + const auto getters = pmLinkLogging_(pChan, []() -> IdentificationTable& { + return IdentificationTable::Get_(); }); // shortcut for command line const auto& opt = clio::Options::Get(); // configure logging based on command line