Skip to content

Commit 41526d4

Browse files
authored
Fix loader ABI compatibility (#665)
Keep sink tracking and pmUnlinkLogging_ teardown while reverting the id-table link parameter to the v2.5.1 interface. Treat internal middleware hooks as optional at loader bind time. Resolve pm*_ exports with best-effort C++ lookup and guard loader proxies when hooks are absent so session C API load is not blocked.
1 parent ad1e30f commit 41526d4

8 files changed

Lines changed: 55 additions & 59 deletions

File tree

IntelPresentMon/CommonUtilities/log/IdentificationTable.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,18 +51,6 @@ namespace pmon::util::log
5151
}
5252
}
5353

54-
IdentificationTableCallbacks IdentificationTable::MakeForwardingCallbacks() noexcept
55-
{
56-
return {
57-
.addThread = [](uint32_t tid, uint32_t pid, const char* name) {
58-
IdentificationTable::AddThread(tid, pid, name ? name : "");
59-
},
60-
.addProcess = [](uint32_t pid, const char* name) {
61-
IdentificationTable::AddProcess(pid, name ? name : "");
62-
}
63-
};
64-
}
65-
6654
void IdentificationTable::RegisterSink(std::shared_ptr<IIdentificationSink> pSink) noexcept
6755
{
6856
try {

IntelPresentMon/CommonUtilities/log/IdentificationTable.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,6 @@ namespace pmon::util::log
1616
virtual void AddProcess(uint32_t pid, std::string name) = 0;
1717
};
1818

19-
struct IdentificationTableCallbacks
20-
{
21-
void(*addThread)(uint32_t tid, uint32_t pid, const char* name) = nullptr;
22-
void(*addProcess)(uint32_t pid, const char* name) = nullptr;
23-
operator bool() const noexcept
24-
{
25-
return addThread || addProcess;
26-
}
27-
};
28-
2919
class IdentificationTable
3020
{
3121
public:
@@ -54,7 +44,6 @@ namespace pmon::util::log
5444
static std::optional<Thread> LookupThread(uint32_t tid) noexcept;
5545
static std::optional<Process> LookupProcess(uint32_t pid) noexcept;
5646
static Bulk GetBulk() noexcept;
57-
static IdentificationTableCallbacks MakeForwardingCallbacks() noexcept;
5847
static void RegisterSink(std::shared_ptr<IIdentificationSink> pSink) noexcept;
5948
static void UnregisterSink(const IIdentificationSink* pSink) noexcept;
6049
static IdentificationTable* GetPtr() noexcept;

IntelPresentMon/Core/source/infra/LogSetup.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ namespace p2c
131131
// connect dll channel and id table to exe, get access to global settings in dll
132132
LoggingSingletons getters;
133133
if (linkMiddlewareLogs) {
134-
getters = pmLinkLogging_(pChan, IdentificationTable::MakeForwardingCallbacks());
134+
getters = pmLinkLogging_(pChan, []() -> IdentificationTable& {
135+
return IdentificationTable::Get_(); });
135136
}
136137
// set the global policy settings
137138
if (opt.logLevel) {

IntelPresentMon/PresentMonAPI2/Internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ struct LoggingSingletons
2828
// return getters for config singletons in the dll to config from the exe
2929
PRESENTMON_API2_EXPORT LoggingSingletons pmLinkLogging_(
3030
std::shared_ptr<pmon::util::log::IChannel> pChannel,
31-
pmon::util::log::IdentificationTableCallbacks idTableCallbacks);
31+
std::function<pmon::util::log::IdentificationTable&()> getIdTable);
3232
// disconnect any logging bridge created by pmLinkLogging_
3333
PRESENTMON_API2_EXPORT void pmUnlinkLogging_() noexcept;
3434
// function to flush the dll's log channel worker queue when before exiting

IntelPresentMon/PresentMonAPI2/PresentMonAPI.cpp

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ PRESENTMON_API2_EXPORT _CrtMemState pmCreateHeapCheckpoint_()
102102

103103
PRESENTMON_API2_EXPORT LoggingSingletons pmLinkLogging_(
104104
std::shared_ptr<pmon::util::log::IChannel> pChannel,
105-
pmon::util::log::IdentificationTableCallbacks idTableCallbacks)
105+
std::function<pmon::util::log::IdentificationTable&()> getIdTable)
106106
{
107107
using namespace util::log;
108108
// set api dll default logging channel to copy to exe logging channel
@@ -112,33 +112,27 @@ PRESENTMON_API2_EXPORT LoggingSingletons pmLinkLogging_(
112112
IdentificationTable::UnregisterSink(pLinkedIdTableSink_.get());
113113
pLinkedIdTableSink_.reset();
114114
}
115-
if (idTableCallbacks) {
115+
if (getIdTable) {
116116
class Sink : public IIdentificationSink
117117
{
118118
public:
119-
Sink(IdentificationTableCallbacks callbacks)
119+
Sink(std::function<IdentificationTable& ()> getTable)
120120
:
121-
callbacks_{ callbacks }
121+
getTable_{ std::move(getTable) }
122122
{}
123123
void AddThread(uint32_t tid, uint32_t pid, std::string name) override
124124
{
125-
if (callbacks_.addThread) {
126-
callbacks_.addThread(tid, pid, name.c_str());
127-
}
125+
getTable_().AddThread_(tid, pid, name);
128126
}
129127
void AddProcess(uint32_t pid, std::string name) override
130128
{
131-
if (callbacks_.addProcess) {
132-
callbacks_.addProcess(pid, name.c_str());
133-
}
129+
getTable_().AddProcess_(pid, name);
134130
}
135131
private:
136-
IdentificationTableCallbacks callbacks_;
132+
std::function<IdentificationTable& ()> getTable_;
137133
};
138-
pLinkedIdTableSink_ = std::make_shared<Sink>(idTableCallbacks);
139-
// hooking exe table up so that it receives updates
134+
pLinkedIdTableSink_ = std::make_shared<Sink>(getIdTable);
140135
IdentificationTable::RegisterSink(pLinkedIdTableSink_);
141-
// copying current contents of table to exe
142136
const auto bulk = IdentificationTable::GetBulk();
143137
for (auto& t : bulk.threads) {
144138
pLinkedIdTableSink_->AddThread(t.tid, t.pid, t.name);

IntelPresentMon/PresentMonAPI2Loader/Implementation.cpp

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ PM_STATUS(*pFunc_pmDiagnosticUnblockWaitingThread_)() = nullptr;
5959
// pointers to runtime-resolved internal functions
6060
_CrtMemState(*pFunc_pmCreateHeapCheckpoint__)() = nullptr;
6161
LoggingSingletons(*pFunc_pmLinkLogging__)(std::shared_ptr<pmon::util::log::IChannel>,
62-
pmon::util::log::IdentificationTableCallbacks) = nullptr;
62+
std::function<pmon::util::log::IdentificationTable&()>) = nullptr;
6363
void(*pFunc_pmUnlinkLogging__)() = nullptr;
6464
void(*pFunc_pmFlushEntryPoint__)() = nullptr;
6565
void(*pFunc_pmSetupODSLogging__)(PM_DIAGNOSTIC_LEVEL, PM_DIAGNOSTIC_LEVEL, bool) = nullptr;
@@ -79,7 +79,7 @@ bool middlewareLoadedSuccessfully_ = false;
7979

8080
// loader-internal implementation functions
8181
// inner impl of method for deriving the mangled name of a cpp-linkage function and loading it
82-
void* GetCppProcAddress_Impl_(HMODULE h,const char* name, const char* mangledEmbeddedSignature)
82+
void* GetCppProcAddress_Impl_(HMODULE h, const char* name, const char* mangledEmbeddedSignature, bool required)
8383
{
8484
// don't bother including receiving template function name
8585
std::string Signature = mangledEmbeddedSignature + 22;
@@ -92,13 +92,20 @@ void* GetCppProcAddress_Impl_(HMODULE h,const char* name, const char* mangledEmb
9292
if (auto pFunc = GetProcAddress(h, funName.c_str())) {
9393
return pFunc;
9494
}
95-
throw LoaderExcept_(PM_STATUS_MIDDLEWARE_MISSING_ENDPOINT);
95+
if (required) {
96+
throw LoaderExcept_(PM_STATUS_MIDDLEWARE_MISSING_ENDPOINT);
97+
}
98+
return nullptr;
9699
}
97100
// load a cpp linkage function from a dll module
98101
template<typename F>
99-
F GetCppProcAddress_(HMODULE h, const char* name)
102+
F GetCppProcAddress_(HMODULE h, const char* name, bool required = true)
100103
{
101-
return reinterpret_cast<F>(GetCppProcAddress_Impl_(h, name, __FUNCDNAME__));
104+
void* pFunc = GetCppProcAddress_Impl_(h, name, __FUNCDNAME__, required);
105+
if (!pFunc) {
106+
return nullptr;
107+
}
108+
return reinterpret_cast<F>(pFunc);
102109
}
103110
// load a c-linkage function
104111
FARPROC GetProcAddress_(HMODULE h, const char* name)
@@ -134,7 +141,7 @@ PRESENTMON_API2_EXPORT PM_STATUS LoadLibrary_(bool versionOnly = false)
134141
}
135142
}
136143
#define RESOLVE(f) pFunc_##f##_ = reinterpret_cast<decltype(pFunc_##f##_)>(GetProcAddress_(hMod_, #f))
137-
#define RESOLVE_CPP(f) pFunc_##f##_ = GetCppProcAddress_<decltype(pFunc_##f##_)>(hMod_, #f)
144+
#define RESOLVE_CPP_OPTIONAL(f) pFunc_##f##_ = GetCppProcAddress_<decltype(pFunc_##f##_)>(hMod_, #f, false)
138145
// resolve version endpoint first as it is needed here
139146
RESOLVE(pmGetApiVersion);
140147
// 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)
188195
RESOLVE(pmDiagnosticFreeMessage);
189196
RESOLVE(pmDiagnosticWaitForMessage);
190197
RESOLVE(pmDiagnosticUnblockWaitingThread);
191-
// internal
192-
RESOLVE_CPP(pmCreateHeapCheckpoint_);
193-
RESOLVE_CPP(pmLinkLogging_);
194-
RESOLVE_CPP(pmUnlinkLogging_);
195-
RESOLVE_CPP(pmFlushEntryPoint_);
196-
RESOLVE_CPP(pmSetupODSLogging_);
197-
RESOLVE_CPP(pmSetupFileLogging_);
198-
RESOLVE_CPP(pmStopPlayback_);
198+
// internal (optional: older middleware may omit refactored hooks)
199+
RESOLVE_CPP_OPTIONAL(pmCreateHeapCheckpoint_);
200+
RESOLVE_CPP_OPTIONAL(pmLinkLogging_);
201+
RESOLVE_CPP_OPTIONAL(pmUnlinkLogging_);
202+
RESOLVE_CPP_OPTIONAL(pmFlushEntryPoint_);
203+
RESOLVE_CPP_OPTIONAL(pmSetupODSLogging_);
204+
RESOLVE_CPP_OPTIONAL(pmSetupFileLogging_);
205+
RESOLVE_CPP_OPTIONAL(pmStopPlayback_);
199206
// if we make it here then we have succeeded
200207
middlewareLoadResult_ = PM_STATUS_SUCCESS;
201208
}
@@ -339,21 +346,27 @@ PRESENTMON_API2_EXPORT _CrtMemState pmCreateHeapCheckpoint_()
339346
throw LoaderExcept_(status);
340347
}
341348
}
349+
if (!pFunc_pmCreateHeapCheckpoint__) {
350+
throw LoaderExcept_(PM_STATUS_MIDDLEWARE_MISSING_ENDPOINT);
351+
}
342352
return pFunc_pmCreateHeapCheckpoint__();
343353
}
344354
PRESENTMON_API2_EXPORT LoggingSingletons pmLinkLogging_(std::shared_ptr<pmon::util::log::IChannel> pChannel,
345-
pmon::util::log::IdentificationTableCallbacks idTableCallbacks)
355+
std::function<pmon::util::log::IdentificationTable& ()> getIdTable)
346356
{
347357
if (!middlewareLoadedSuccessfully_) {
348358
if (auto status = LoadLibrary_(); status != PM_STATUS_SUCCESS) {
349359
throw LoaderExcept_(status);
350360
}
351361
}
352-
return pFunc_pmLinkLogging__(pChannel, idTableCallbacks);
362+
if (!pFunc_pmLinkLogging__) {
363+
return {};
364+
}
365+
return pFunc_pmLinkLogging__(pChannel, std::move(getIdTable));
353366
}
354367
PRESENTMON_API2_EXPORT void pmUnlinkLogging_() noexcept
355368
{
356-
if (middlewareLoadedSuccessfully_) {
369+
if (middlewareLoadedSuccessfully_ && pFunc_pmUnlinkLogging__) {
357370
pFunc_pmUnlinkLogging__();
358371
}
359372
}
@@ -363,7 +376,7 @@ PRESENTMON_API2_EXPORT void pmFlushEntryPoint_() noexcept
363376
// flush is called even in cases where the dll hasn't been loaded
364377
// allow it to be elided in this case since it has no effect without
365378
// other functions being called previously anyways
366-
if (middlewareLoadedSuccessfully_) {
379+
if (middlewareLoadedSuccessfully_ && pFunc_pmFlushEntryPoint__) {
367380
pFunc_pmFlushEntryPoint__();
368381
}
369382
}
@@ -375,6 +388,9 @@ PRESENTMON_API2_EXPORT void pmSetupODSLogging_(PM_DIAGNOSTIC_LEVEL logLevel,
375388
throw LoaderExcept_(status);
376389
}
377390
}
391+
if (!pFunc_pmSetupODSLogging__) {
392+
throw LoaderExcept_(PM_STATUS_MIDDLEWARE_MISSING_ENDPOINT);
393+
}
378394
pFunc_pmSetupODSLogging__(logLevel, stackTraceLevel, exceptionTrace);
379395
}
380396
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
437453
PM_DIAGNOSTIC_LEVEL stackTraceLevel, bool exceptionTrace)
438454
{
439455
LoadEndpointsIfEmpty_();
456+
if (!pFunc_pmSetupFileLogging__) {
457+
return PM_STATUS_MIDDLEWARE_MISSING_ENDPOINT;
458+
}
440459
return pFunc_pmSetupFileLogging__(file, logLevel, stackTraceLevel, exceptionTrace);
441460
}
442461

443462
PRESENTMON_API2_EXPORT PM_STATUS pmStopPlayback_(PM_SESSION_HANDLE hSession)
444463
{
445464
LoadEndpointsIfEmpty_();
465+
if (!pFunc_pmStopPlayback__) {
466+
return PM_STATUS_MIDDLEWARE_MISSING_ENDPOINT;
467+
}
446468
return pFunc_pmStopPlayback__(hSession);
447469
}
448470

IntelPresentMon/PresentMonAPI2Tests/Logging.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ namespace pmon::test
171171
if (!linkState.linked) {
172172
linkState.getters = pmLinkLogging_(
173173
pChannel,
174-
util::log::IdentificationTable::MakeForwardingCallbacks());
174+
[]() -> util::log::IdentificationTable& {
175+
return util::log::IdentificationTable::Get_(); });
175176
linkState.linked = true;
176177
}
177178
gettersCopy = linkState.getters;

IntelPresentMon/SampleClient/LogSetup.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ namespace p2sam
6464
// get the channel to work on it
6565
auto pChan = GetDefaultChannel();
6666
// connect dll channel and id table to exe, get access to global settings in dll
67-
const auto getters = pmLinkLogging_(pChan, IdentificationTable::MakeForwardingCallbacks());
67+
const auto getters = pmLinkLogging_(pChan, []() -> IdentificationTable& {
68+
return IdentificationTable::Get_(); });
6869
// shortcut for command line
6970
const auto& opt = clio::Options::Get();
7071
// configure logging based on command line

0 commit comments

Comments
 (0)