Skip to content

Commit 067811e

Browse files
committed
Externalize UCI SDK payload
1 parent f73059c commit 067811e

10 files changed

Lines changed: 227 additions & 22 deletions

File tree

IntelPresentMon/Common.props

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77
<OutDir>$(SolutionDir)build\$(Configuration)\</OutDir>
88
<IntDir>$(SolutionDir)build\obj\$(ProjectName)-$(Platform)-$(Configuration)\</IntDir>
99
<LocalDebuggerWorkingDirectory>$(OutDir)</LocalDebuggerWorkingDirectory>
10+
<UciSdkDir Condition="'$(PMON_UCI_SDK_DIR)'!=''">$(PMON_UCI_SDK_DIR)</UciSdkDir>
11+
<UciSdkDir Condition="'$(UciSdkDir)'==''">$(MSBuildThisFileDirectory)ControlLib\uci\external</UciSdkDir>
12+
<UciSdkIncludeDir>$(UciSdkDir)\include</UciSdkIncludeDir>
13+
<UciSdkBinDir>$(UciSdkDir)\bin</UciSdkBinDir>
1014
</PropertyGroup>
1115
<ItemDefinitionGroup>
1216
<ClCompile />

IntelPresentMon/ControlLib/ControlLib.vcxproj

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,14 @@
7373
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
7474
<LanguageStandard>stdcpplatest</LanguageStandard>
7575
<UseStandardPreprocessor>true</UseStandardPreprocessor>
76-
<AdditionalIncludeDirectories>uci\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
76+
<AdditionalIncludeDirectories>$(UciSdkIncludeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
7777
</ClCompile>
7878
<Link>
7979
<SubSystem>Console</SubSystem>
8080
<GenerateDebugInformation>true</GenerateDebugInformation>
8181
</Link>
8282
<Lib>
83-
<AdditionalDependencies>wbemuuid.lib;unified-collector-interface.lib;%(AdditionalDependencies)</AdditionalDependencies>
83+
<AdditionalDependencies>wbemuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
8484
</Lib>
8585
</ItemDefinitionGroup>
8686
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@@ -96,7 +96,7 @@
9696
<UseStandardPreprocessor>true</UseStandardPreprocessor>
9797
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
9898
<ControlFlowGuard>Guard</ControlFlowGuard>
99-
<AdditionalIncludeDirectories>uci\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
99+
<AdditionalIncludeDirectories>$(UciSdkIncludeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
100100
</ClCompile>
101101
<Link>
102102
<SubSystem>Console</SubSystem>
@@ -105,7 +105,7 @@
105105
<GenerateDebugInformation>true</GenerateDebugInformation>
106106
</Link>
107107
<Lib>
108-
<AdditionalDependencies>wbemuuid.lib;unified-collector-interface.lib;%(AdditionalDependencies)</AdditionalDependencies>
108+
<AdditionalDependencies>wbemuuid.lib;%(AdditionalDependencies)</AdditionalDependencies>
109109
</Lib>
110110
</ItemDefinitionGroup>
111111
<ItemGroup>
@@ -132,6 +132,7 @@
132132
<ClInclude Include="TelemetryCoordinator.h" />
133133
<ClInclude Include="TelemetryDeviceFingerprint.h" />
134134
<ClInclude Include="TelemetryProvider.h" />
135+
<ClInclude Include="uci\UciSdk.h" />
135136
<ClInclude Include="uci\UciTelemetryProvider.h" />
136137
<ClInclude Include="wmi\WmiTelemetryProvider.h" />
137138
</ItemGroup>

IntelPresentMon/ControlLib/ControlLib.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@
8585
<ClInclude Include="uci\UciTelemetryProvider.h">
8686
<Filter>Uci</Filter>
8787
</ClInclude>
88+
<ClInclude Include="uci\UciSdk.h">
89+
<Filter>Uci</Filter>
90+
</ClInclude>
8891
</ItemGroup>
8992
<ItemGroup>
9093
<ClCompile Include="nvapi\NvapiWrapper.cpp">
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
dist/
1+
dist/
2+
external/
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright (C) 2026 Intel Corporation
2+
// SPDX-License-Identifier: MIT
3+
#pragma once
4+
5+
#if __has_include(<uci/uci.h>) && __has_include(<uci/uci-data-records.h>) && __has_include(<uci/uci-versions.h>)
6+
#define PMON_HAS_UCI_SDK 1
7+
#include <uci/uci-data-records.h>
8+
#include <uci/uci.h>
9+
#else
10+
#define PMON_HAS_UCI_SDK 0
11+
#endif

IntelPresentMon/ControlLib/uci/UciTelemetryProvider.cpp

Lines changed: 177 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
#include "../../CommonUtilities/str/String.h"
1010
#include "../../CommonUtilities/win/Privileges.h"
1111

12-
#include "inc/uci/uci-versions.h"
13-
1412
#include <algorithm>
1513
#include <exception>
1614
#include <format>
@@ -22,12 +20,140 @@
2220
using namespace pmon;
2321
using namespace std::literals;
2422

23+
#if PMON_HAS_UCI_SDK
24+
25+
#include <uci/uci-versions.h>
26+
2527
namespace pmon::tel::uci
2628
{
2729
namespace
2830
{
2931
using v = util::log::V;
3032

33+
struct UciApi_
34+
{
35+
HMODULE module = nullptr;
36+
decltype(&::uciGetCollectorFromIdentifier) uciGetCollectorFromIdentifier = nullptr;
37+
decltype(&::uciInitialize) uciInitialize = nullptr;
38+
decltype(&::uciDestroy) uciDestroy = nullptr;
39+
decltype(&::uciEnumerateMetrics) uciEnumerateMetrics = nullptr;
40+
decltype(&::uciGetMetricContainerMetrics) uciGetMetricContainerMetrics = nullptr;
41+
decltype(&::uciGetMetricId) uciGetMetricId = nullptr;
42+
decltype(&::uciGetMetricName) uciGetMetricName = nullptr;
43+
decltype(&::uciGetMetricDescription) uciGetMetricDescription = nullptr;
44+
decltype(&::uciGetMetricEvents) uciGetMetricEvents = nullptr;
45+
decltype(&::uciGetEventId) uciGetEventId = nullptr;
46+
decltype(&::uciGetMetricEventName) uciGetMetricEventName = nullptr;
47+
decltype(&::uciGetMetricEventDescription) uciGetMetricEventDescription = nullptr;
48+
decltype(&::uciGetMetricContainerGroups) uciGetMetricContainerGroups = nullptr;
49+
decltype(&::uciGetMetricGroupId) uciGetMetricGroupId = nullptr;
50+
decltype(&::uciGetMetricGroupName) uciGetMetricGroupName = nullptr;
51+
decltype(&::uciGetMetricGroupDescription) uciGetMetricGroupDescription = nullptr;
52+
decltype(&::uciGetMetricsInGroup) uciGetMetricsInGroup = nullptr;
53+
decltype(&::uciGetMetricContainerEvents) uciGetMetricContainerEvents = nullptr;
54+
decltype(&::uciFreeMetricContainer) uciFreeMetricContainer = nullptr;
55+
decltype(&::uciMetricRecordGetMetricName) uciMetricRecordGetMetricName = nullptr;
56+
decltype(&::uciMetricRecordGetEntity) uciMetricRecordGetEntity = nullptr;
57+
decltype(&::uciMetricRecordGetDescriptor) uciMetricRecordGetDescriptor = nullptr;
58+
decltype(&::uciMetricRecordGetUnit) uciMetricRecordGetUnit = nullptr;
59+
decltype(&::uciMetricRecordGetSample) uciMetricRecordGetSample = nullptr;
60+
decltype(&::uciMetricRecordGetRecordTimestamp) uciMetricRecordGetRecordTimestamp = nullptr;
61+
decltype(&::uciMetricRecordGetRecordDuration) uciMetricRecordGetRecordDuration = nullptr;
62+
decltype(&::uciConfigureCollection) uciConfigureCollection = nullptr;
63+
decltype(&::uciSetDataCallback) uciSetDataCallback = nullptr;
64+
decltype(&::uciStartCollection) uciStartCollection = nullptr;
65+
decltype(&::uciStopCollection) uciStopCollection = nullptr;
66+
67+
UciApi_()
68+
{
69+
module = LoadLibraryW(L"unified-collector-interface.dll");
70+
if (module == nullptr) {
71+
throw Except<TelemetrySubsystemAbsent>(std::format(
72+
"UCI telemetry provider unavailable because unified-collector-interface.dll is not present; error={}",
73+
GetLastError()));
74+
}
75+
76+
LoadProc_(uciGetCollectorFromIdentifier, "uciGetCollectorFromIdentifier");
77+
LoadProc_(uciInitialize, "uciInitialize");
78+
LoadProc_(uciDestroy, "uciDestroy");
79+
LoadProc_(uciEnumerateMetrics, "uciEnumerateMetrics");
80+
LoadProc_(uciGetMetricContainerMetrics, "uciGetMetricContainerMetrics");
81+
LoadProc_(uciGetMetricId, "uciGetMetricId");
82+
LoadProc_(uciGetMetricName, "uciGetMetricName");
83+
LoadProc_(uciGetMetricDescription, "uciGetMetricDescription");
84+
LoadProc_(uciGetMetricEvents, "uciGetMetricEvents");
85+
LoadProc_(uciGetEventId, "uciGetEventId");
86+
LoadProc_(uciGetMetricEventName, "uciGetMetricEventName");
87+
LoadProc_(uciGetMetricEventDescription, "uciGetMetricEventDescription");
88+
LoadProc_(uciGetMetricContainerGroups, "uciGetMetricContainerGroups");
89+
LoadProc_(uciGetMetricGroupId, "uciGetMetricGroupId");
90+
LoadProc_(uciGetMetricGroupName, "uciGetMetricGroupName");
91+
LoadProc_(uciGetMetricGroupDescription, "uciGetMetricGroupDescription");
92+
LoadProc_(uciGetMetricsInGroup, "uciGetMetricsInGroup");
93+
LoadProc_(uciGetMetricContainerEvents, "uciGetMetricContainerEvents");
94+
LoadProc_(uciFreeMetricContainer, "uciFreeMetricContainer");
95+
LoadProc_(uciMetricRecordGetMetricName, "uciMetricRecordGetMetricName");
96+
LoadProc_(uciMetricRecordGetEntity, "uciMetricRecordGetEntity");
97+
LoadProc_(uciMetricRecordGetDescriptor, "uciMetricRecordGetDescriptor");
98+
LoadProc_(uciMetricRecordGetUnit, "uciMetricRecordGetUnit");
99+
LoadProc_(uciMetricRecordGetSample, "uciMetricRecordGetSample");
100+
LoadProc_(uciMetricRecordGetRecordTimestamp, "uciMetricRecordGetRecordTimestamp");
101+
LoadProc_(uciMetricRecordGetRecordDuration, "uciMetricRecordGetRecordDuration");
102+
LoadProc_(uciConfigureCollection, "uciConfigureCollection");
103+
LoadProc_(uciSetDataCallback, "uciSetDataCallback");
104+
LoadProc_(uciStartCollection, "uciStartCollection");
105+
LoadProc_(uciStopCollection, "uciStopCollection");
106+
}
107+
108+
template<class T>
109+
void LoadProc_(T& proc, const char* name)
110+
{
111+
proc = reinterpret_cast<T>(GetProcAddress(module, name));
112+
if (proc == nullptr) {
113+
throw Except<TelemetrySubsystemAbsent>(std::format(
114+
"UCI telemetry provider unavailable because {} is missing from unified-collector-interface.dll",
115+
name));
116+
}
117+
}
118+
};
119+
120+
UciApi_& Api_()
121+
{
122+
static UciApi_ api;
123+
return api;
124+
}
125+
126+
#define uciConfigureCollection Api_().uciConfigureCollection
127+
#define uciDestroy Api_().uciDestroy
128+
#define uciEnumerateMetrics Api_().uciEnumerateMetrics
129+
#define uciFreeMetricContainer Api_().uciFreeMetricContainer
130+
#define uciGetCollectorFromIdentifier Api_().uciGetCollectorFromIdentifier
131+
#define uciGetEventId Api_().uciGetEventId
132+
#define uciGetMetricContainerEvents Api_().uciGetMetricContainerEvents
133+
#define uciGetMetricContainerGroups Api_().uciGetMetricContainerGroups
134+
#define uciGetMetricContainerMetrics Api_().uciGetMetricContainerMetrics
135+
#define uciGetMetricDescription Api_().uciGetMetricDescription
136+
#define uciGetMetricEventDescription Api_().uciGetMetricEventDescription
137+
#define uciGetMetricEventName Api_().uciGetMetricEventName
138+
#define uciGetMetricEvents Api_().uciGetMetricEvents
139+
#define uciGetMetricGroupDescription Api_().uciGetMetricGroupDescription
140+
#define uciGetMetricGroupId Api_().uciGetMetricGroupId
141+
#define uciGetMetricGroupName Api_().uciGetMetricGroupName
142+
#define uciGetMetricId Api_().uciGetMetricId
143+
#define uciGetMetricName Api_().uciGetMetricName
144+
#define uciGetMetricsInGroup Api_().uciGetMetricsInGroup
145+
#define uciInitialize Api_().uciInitialize
146+
#define uciMetricRecordGetDescriptor Api_().uciMetricRecordGetDescriptor
147+
#define uciMetricRecordGetEntity Api_().uciMetricRecordGetEntity
148+
#define uciMetricRecordGetMetricName Api_().uciMetricRecordGetMetricName
149+
#define uciMetricRecordGetRecordDuration Api_().uciMetricRecordGetRecordDuration
150+
#define uciMetricRecordGetRecordTimestamp Api_().uciMetricRecordGetRecordTimestamp
151+
#define uciMetricRecordGetSample Api_().uciMetricRecordGetSample
152+
#define uciMetricRecordGetUnit Api_().uciMetricRecordGetUnit
153+
#define uciSetDataCallback Api_().uciSetDataCallback
154+
#define uciStartCollection Api_().uciStartCollection
155+
#define uciStopCollection Api_().uciStopCollection
156+
31157
constexpr std::string_view kCpuPowerMetricName_ = "pkg-pwr";
32158
constexpr std::string_view kCpuTemperatureMetricName_ = "core-temp";
33159
constexpr std::string_view kCpuPowerRecordMetricName_ = "PKG-PWR";
@@ -183,12 +309,6 @@ namespace pmon::tel::uci
183309
throw Except<TelemetrySubsystemAbsent>("UCI telemetry provider disabled because service is not elevated");
184310
}
185311

186-
if (LoadLibraryW(L"unified-collector-interface.dll") == nullptr) {
187-
throw Except<TelemetrySubsystemAbsent>(std::format(
188-
"UCI telemetry provider unavailable because unified-collector-interface.dll is not present; error={}",
189-
GetLastError()));
190-
}
191-
192312
CheckUciCall_(
193313
uciGetCollectorFromIdentifier(SoCWatchIdentifier, &collector_),
194314
"uciGetCollectorFromIdentifier",
@@ -737,3 +857,52 @@ namespace pmon::tel::uci
737857
collectionStarted_ = false;
738858
}
739859
}
860+
861+
#else
862+
863+
namespace pmon::tel::uci
864+
{
865+
UciTelemetryProvider::UciTelemetryProvider()
866+
{
867+
throw Except<TelemetrySubsystemAbsent>("UCI telemetry provider unavailable because service was built without UCI dependency present.");
868+
}
869+
870+
UciTelemetryProvider::~UciTelemetryProvider() = default;
871+
872+
ProviderCapabilityMap UciTelemetryProvider::GetCaps()
873+
{
874+
return {};
875+
}
876+
877+
const TelemetryDeviceFingerprint& UciTelemetryProvider::GetFingerPrint(
878+
ProviderDeviceId providerDeviceId) const
879+
{
880+
(void)providerDeviceId;
881+
throw Except<UciException>("UCI provider device not found");
882+
}
883+
884+
TelemetryMetricValue UciTelemetryProvider::PollMetric(
885+
ProviderDeviceId providerDeviceId,
886+
PM_METRIC metricId,
887+
uint32_t arrayIndex,
888+
int64_t requestQpc)
889+
{
890+
(void)providerDeviceId;
891+
(void)metricId;
892+
(void)arrayIndex;
893+
(void)requestQpc;
894+
throw Except<UciException>("UCI provider unavailable");
895+
}
896+
897+
void UciTelemetryProvider::SetPollRate(uint32_t pollRateMs)
898+
{
899+
(void)pollRateMs;
900+
}
901+
902+
void UciTelemetryProvider::SetMetricUse(const svc::DeviceMetricUse& metricUse)
903+
{
904+
(void)metricUse;
905+
}
906+
}
907+
908+
#endif

IntelPresentMon/ControlLib/uci/UciTelemetryProvider.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
#include "../../CommonUtilities/win/WinAPI.h"
66
#include "../../Interprocess/source/SystemDeviceId.h"
77
#include "../TelemetryProvider.h"
8-
#include "inc/uci/uci-data-records.h"
9-
#include "inc/uci/uci.h"
8+
#include "UciSdk.h"
109

1110
#include <atomic>
1211
#include <cstdint>
@@ -44,7 +43,6 @@ namespace pmon::tel::uci
4443
std::vector<std::optional<double>> cpuCoreTemperaturesSample{};
4544
};
4645

47-
static void StaticDataCallback_(uciDataBundle* dataBundle);
4846
static uint32_t CountPhysicalCores_();
4947
static std::optional<double> ComputeAverageCpuTemperature_(const DeviceState_& device);
5048
static void ValidateMetricIndex_(const DeviceState_& device, PM_METRIC metricId, uint32_t arrayIndex);
@@ -53,16 +51,21 @@ namespace pmon::tel::uci
5351
const std::unordered_set<std::string>& enumeratedMetricNames,
5452
uint32_t physicalCoreCount);
5553

54+
#if PMON_HAS_UCI_SDK
55+
static void StaticDataCallback_(uciDataBundle* dataBundle);
5656
void OnDataCallback_(uciDataBundle* dataBundle);
5757
void ApplyMetricRecord_(DeviceState_& device, void* recordHandle);
5858
std::unordered_set<std::string> EnumerateMetrics_();
5959
void DumpMetricEnumeration_(uciMetricContainerHandle metricContainer) const;
6060
void ReconfigureCollection_();
6161
void StopCollection_() noexcept;
62+
#endif
6263

6364
private:
6465
static constexpr ProviderDeviceId kProviderDeviceId_ = 1;
66+
#if PMON_HAS_UCI_SDK
6567
uciCollectorHandle collector_ = nullptr;
68+
#endif
6669
DeviceState_ systemDevice_{};
6770
std::mutex configMutex_{};
6871
std::mutex dataMutex_{};
@@ -72,6 +75,8 @@ namespace pmon::tel::uci
7275
bool wantsCpuTemperature_ = false;
7376
bool wantsCpuCoreTemperature_ = false;
7477

78+
#if PMON_HAS_UCI_SDK
7579
static std::atomic<UciTelemetryProvider*> activeProvider_;
80+
#endif
7681
};
7782
}

IntelPresentMon/PMInstallerLib/PMInstallerLib.wixproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
<OutputName>PMInstallerLib</OutputName>
66
<IntermediateOutputPath>$(SolutionDir)build\obj\$(MSBuildProjectName)-$(Platform)-$(Configuration)</IntermediateOutputPath>
77
<OutputPath>$(SolutionDir)build\$(Configuration)</OutputPath>
8-
<DefineConstants>$(DefineConstants);UciDistDir=$(MSBuildProjectDirectory)\..\ControlLib\uci\dist</DefineConstants>
8+
<UciSdkDir Condition="'$(PMON_UCI_SDK_DIR)'!=''">$(PMON_UCI_SDK_DIR)</UciSdkDir>
9+
<UciSdkDir Condition="'$(UciSdkDir)'==''">$(MSBuildProjectDirectory)\..\ControlLib\uci\external</UciSdkDir>
10+
<DefineConstants>$(DefineConstants);UciDistDir=$(UciSdkDir)\bin</DefineConstants>
911
<!-- Point these at YOUR WiX 3.x install -->
1012
<WixToolPath>$(WIX)bin\</WixToolPath>
1113
<WixTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>

IntelPresentMon/PMInstallerLib/wix-uci-dist.ps1

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,12 @@ function Write-EmptyUciDistFragment {
5252

5353
Push-Location $PSScriptRoot
5454

55-
$distPath = '..\ControlLib\uci\dist'
55+
$uciSdkDir = $env:PMON_UCI_SDK_DIR
56+
if ([string]::IsNullOrWhiteSpace($uciSdkDir)) {
57+
$uciSdkDir = '..\ControlLib\uci\external'
58+
}
59+
60+
$distPath = Join-Path $uciSdkDir 'bin'
5661
$outPath = 'UciDist.wxs'
5762

5863
if (-not (Test-Path $distPath -PathType Container)) {

0 commit comments

Comments
 (0)