CPUAffinity¶
CPUAffinity.cpp demonstrates CPU affinity node access checks and status inspection through GenTL nodes.
//=============================================================================
// Copyright (c) 2026 FLIR Integrated Imaging Solutions, Inc. All Rights Reserved.
//
// This software is the confidential and proprietary information of FLIR
// Integrated Imaging Solutions, Inc. ("Confidential Information"). You
// shall not disclose such Confidential Information and shall use it only in
// accordance with the terms of the license agreement you entered into
// with FLIR Integrated Imaging Solutions, Inc. (FLIR).
//
// FLIR MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
// SOFTWARE, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE, OR NON-INFRINGEMENT. FLIR SHALL NOT BE LIABLE FOR ANY DAMAGES
// SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
// THIS SOFTWARE OR ITS DERIVATIVES.
//=============================================================================
/**
* @example CPUAffinity.cpp
*
* @brief CPUAffinity.cpp demonstrates CPU affinity node access checks and
* status inspection through GenTL nodes.
*
* This example shows how to:
* - Access system-level CPU affinity nodes
* - Read CPU affinity privilege and service status
* - Check access to CPU affinity service control commands (start/stop)
* - Enumerate interfaces and inspect interface-level CPU affinity nodes
* - Check write access for interface CPU affinity control nodes
*
* Note: This example is Windows-only and may require elevated privileges to
* access some CPU affinity-related nodes.
*/
#include "Spinnaker.h"
#include "SpinGenApi/SpinnakerGenApi.h"
#include <iostream>
using namespace Spinnaker;
using namespace Spinnaker::GenApi;
using namespace Spinnaker::GenICam;
using namespace std;
namespace
{
// Set to true to enable the optional CPU affinity configuration step.
//
// *** NOTES ***
// When enabled, the example will attempt to write CPUAffinityEnable on each
// GigE interface. This requires admin privileges and will modify the CPU
// affinity configuration on the system. Leave as false to run in read-only
// inspection mode.
constexpr bool configureCpuAffinity = false;
// Core list to apply to the selected GigE interface when configureCpuAffinity
// is enabled. Use a comma-separated list (e.g. "1,2,3").
const std::string reservedCoresToSet = "2,3,4,5";
// Exact interface index to target for CPU affinity configuration.
// No fallback search is performed.
const int interfaceIndexToSet = 1;
// Print privilege level value
void PrintPrivilegeLevel(const std::string& label, const int64_t privilegeLevel)
{
cout << label << privilegeLevel;
if (privilegeLevel == 1)
{
cout << " (No Admin Rights)" << endl;
}
else if (privilegeLevel == 2)
{
cout << " (Admin Rights Available)" << endl;
}
else
{
cout << " (Unknown)" << endl;
}
}
// Print CPU affinity service status
void PrintCpuAffinityServiceStatus(const int64_t serviceStatus)
{
cout << "CPU Affinity Service Status: " << serviceStatus;
if (serviceStatus == 0)
{
cout << " (Stopped)" << endl;
}
else if (serviceStatus == 1)
{
cout << " (Running)" << endl;
}
else
{
cout << " (Unknown)" << endl;
}
}
// Print media optimization status/enable (Boolean node)
void PrintMediaOptimizationEnable(const bool mediaOptimizationEnable)
{
cout << "Media Optimization Enable: " << (mediaOptimizationEnable ? "1 (Enabled)" : "0 (Disabled)") << endl;
}
// Read and print CPU affinity information from system-level GenTL nodes
int ReadCpuAffinitySystemNodes(INodeMap& systemTLNodeMap)
{
cout << "*** SYSTEM CPU AFFINITY INFORMATION ***" << endl << endl;
try
{
CEnumerationPtr pPrivilege = systemTLNodeMap.GetNode("CpuAffinityPrivilege");
if (IsReadable(pPrivilege))
{
PrintPrivilegeLevel("CPU Affinity Privilege Level: ", pPrivilege->GetIntValue());
}
else
{
cout << "CPU Affinity Privilege node not available on this system" << endl;
}
}
catch (Spinnaker::Exception& e)
{
cout << "CPU Affinity Privilege node not available on this system: " << e.what() << endl;
}
try
{
CEnumerationPtr pServiceStatus = systemTLNodeMap.GetNode("CpuAffinityServiceStatus");
if (IsReadable(pServiceStatus))
{
PrintCpuAffinityServiceStatus(pServiceStatus->GetIntValue());
}
else
{
cout << "CPU Affinity Service Status node not available on this system" << endl;
}
}
catch (Spinnaker::Exception& e)
{
cout << "CPU Affinity Service Status node not available on this system: " << e.what() << endl;
}
try
{
CIntegerPtr pAvailableCores = systemTLNodeMap.GetNode("CpuAffinityAvailableCores");
if (IsReadable(pAvailableCores))
{
cout << "Available CPU Cores: " << pAvailableCores->GetValue() << endl;
}
else
{
cout << "Available CPU Cores node not available on this system" << endl;
}
}
catch (Spinnaker::Exception& e)
{
cout << "Available CPU Cores node not available on this system: " << e.what() << endl;
}
cout << endl;
return 0;
}
// Show access state of system-level CPU affinity service control commands
int ShowCpuAffinityControlNodes(INodeMap& systemTLNodeMap)
{
try
{
CCommandPtr pStartService = systemTLNodeMap.GetNode("CpuAffinityServiceStart");
if (IsWritable(pStartService))
{
cout << "CPU Affinity Service Start command available (write access granted)" << endl;
// Note: Actual execution would require admin privileges
// pStartService->Execute();
}
else
{
cout << "CPU Affinity Service Start command not writable (may require admin privileges)" << endl;
}
}
catch (Spinnaker::Exception& e)
{
cout << "CPU Affinity Service Start command not available on this system: " << e.what() << endl;
}
try
{
CCommandPtr pStopService = systemTLNodeMap.GetNode("CpuAffinityServiceStop");
if (IsWritable(pStopService))
{
cout << "CPU Affinity Service Stop command available (write access granted)" << endl;
// Note: Actual execution would require admin privileges
// pStopService->Execute();
}
else
{
cout << "CPU Affinity Service Stop command not writable (may require admin privileges)" << endl;
}
}
catch (Spinnaker::Exception& e)
{
cout << "CPU Affinity Service Stop command not available on this system: " << e.what() << endl;
}
return 0;
}
// Read and print media optimization information from system-level GenTL nodes.
int ReadMediaOptimizationSystemNodes(INodeMap& systemTLNodeMap)
{
cout << endl << "*** SYSTEM MEDIA OPTIMIZATION INFORMATION ***" << endl << endl;
try
{
CEnumerationPtr pMediaOptimizationPrivilege = systemTLNodeMap.GetNode("MediaOptimizationPrivilege");
if (IsReadable(pMediaOptimizationPrivilege))
{
PrintPrivilegeLevel("Media Optimization Privilege Level: ", pMediaOptimizationPrivilege->GetIntValue());
}
else
{
cout << "Media Optimization Privilege node not available on this system" << endl;
}
}
catch (Spinnaker::Exception& e)
{
cout << "Media Optimization Privilege node not available on this system: " << e.what() << endl;
}
try
{
CBooleanPtr pMediaOptimizationEnable = systemTLNodeMap.GetNode("MediaOptimizationEnable");
if (IsReadable(pMediaOptimizationEnable))
{
PrintMediaOptimizationEnable(pMediaOptimizationEnable->GetValue());
}
else
{
cout << "Media Optimization Enable node not available on this system" << endl;
}
}
catch (Spinnaker::Exception& e)
{
cout << "Media Optimization Enable node not available on this system: " << e.what() << endl;
}
cout << endl;
return 0;
}
// Show read/write access for media optimization control nodes.
int ShowMediaOptimizationControlNodes(INodeMap& systemTLNodeMap)
{
try
{
CBooleanPtr pMediaOptimizationEnable = systemTLNodeMap.GetNode("MediaOptimizationEnable");
if (IsReadable(pMediaOptimizationEnable))
{
PrintMediaOptimizationEnable(pMediaOptimizationEnable->GetValue());
}
else
{
cout << "Media Optimization Enable node not available on this system" << endl;
}
if (IsWritable(pMediaOptimizationEnable))
{
cout << "Media Optimization Enable node is writable" << endl;
// Note: Actual execution would require admin privileges
// pMediaOptimizationEnable->SetValue(!pMediaOptimizationEnable->GetValue());
}
else
{
cout << "Media Optimization Enable node is not writable (may require admin privileges)" << endl;
}
}
catch (Spinnaker::Exception& e)
{
cout << "Media Optimization Enable node not available on this system: " << e.what() << endl;
}
return 0;
}
// Configure reserved cores and enable CPU affinity enforcement.
//
// Writing CPUAffinityEnable = true pins RSS queues to the reserved CPU cores
// defined in the CPU affinity config file. If no cores have been configured
// yet, a default core assignment is applied automatically.
//
// Requires admin privileges. Targets a specified GigE interface index.
int ConfigureInterfaceCpuAffinity(SystemPtr system)
{
int result = 0;
bool settingsChanged = false;
bool hasOriginalReservedCores = false;
bool hasOriginalEnable = false;
std::string originalReservedCores;
bool originalCpuAffinityEnable = false;
cout << endl << "*** CONFIGURING INTERFACE CPU AFFINITY ***" << endl << endl;
InterfaceList interfaceList = system->GetInterfaces();
const unsigned int numInterfaces = interfaceList.GetSize();
// Find the GigE interface
InterfacePtr pTargetInterface = nullptr;
std::string targetInterfaceName;
if (interfaceIndexToSet < 0 || static_cast<unsigned int>(interfaceIndexToSet) >= numInterfaces)
{
cout << "Interface index " << interfaceIndexToSet << " is out of range (0-"
<< (numInterfaces == 0 ? 0 : numInterfaces - 1) << ")." << endl;
interfaceList.Clear();
return -1;
}
try
{
pTargetInterface = interfaceList.GetByIndex(static_cast<unsigned int>(interfaceIndexToSet));
INodeMap& interfaceTLNodeMap = pTargetInterface->GetTLNodeMap();
CBooleanPtr pCPUAffinityEnable = interfaceTLNodeMap.GetNode("CPUAffinityEnable");
if (!IsAvailable(pCPUAffinityEnable))
{
cout << "Interface " << interfaceIndexToSet
<< " does not expose CPUAffinityEnable (likely not a configurable GigE interface)." << endl;
interfaceList.Clear();
return -1;
}
CStringPtr pDisplayName = interfaceTLNodeMap.GetNode("InterfaceDisplayName");
if (IsReadable(pDisplayName))
{
targetInterfaceName = std::string(pDisplayName->GetValue());
}
else
{
targetInterfaceName = "Interface " + std::to_string(interfaceIndexToSet);
}
}
catch (Spinnaker::Exception& e)
{
cout << "Error accessing interface " << interfaceIndexToSet << ": " << e.what() << endl;
interfaceList.Clear();
return -1;
}
cout << "Configuring: " << targetInterfaceName << endl;
try
{
INodeMap& interfaceTLNodeMap = pTargetInterface->GetTLNodeMap();
CStringPtr pReservedCores = interfaceTLNodeMap.GetNode("ReceiveSideScalingReservedCores");
CBooleanPtr pCPUAffinityEnable = interfaceTLNodeMap.GetNode("CPUAffinityEnable");
if (!IsWritable(pReservedCores) || !IsWritable(pCPUAffinityEnable))
{
cout << " CPU affinity cannot be configured (admin privileges required)" << endl;
interfaceList.Clear();
return -1;
}
// Save current values so this example can restore them before exit.
if (IsReadable(pReservedCores))
{
originalReservedCores = std::string(pReservedCores->GetValue());
hasOriginalReservedCores = true;
}
if (IsReadable(pCPUAffinityEnable))
{
originalCpuAffinityEnable = pCPUAffinityEnable->GetValue();
hasOriginalEnable = true;
}
cout << " Original Reserved CPU cores: "
<< (originalReservedCores.empty() ? "(none)" : originalReservedCores) << endl;
if (hasOriginalEnable)
{
cout << " Original CPU affinity enable: " << (originalCpuAffinityEnable ? "true" : "false") << endl;
}
//
// Set reserved cores on the selected interface
//
// *** NOTES ***
// ReceiveSideScalingReservedCores expects a comma-separated core list.
// CPU 0 is reserved for system use.
//
pReservedCores->SetValue(reservedCoresToSet.c_str());
settingsChanged = true;
cout << " Reserved CPU cores set to: " << reservedCoresToSet << endl;
//
// Enable CPU affinity on the selected interface
//
// *** NOTES ***
// If no cores are currently reserved for this interface, a default
// core assignment is applied by the GenTL layer. Use SpinView or
// the CPU affinity config file to specify explicit core assignments
// before enabling.
//
pCPUAffinityEnable->SetValue(true);
cout << " CPU affinity enabled" << endl;
// Read back the resulting core assignment to confirm
CIntegerPtr pCoreCount = interfaceTLNodeMap.GetNode("ReceiveSideScalingReservedCoresCount");
bool hasReservedCoreCount = false;
int64_t reservedCoreCount = 0;
if (IsReadable(pCoreCount))
{
reservedCoreCount = pCoreCount->GetValue();
hasReservedCoreCount = true;
cout << " Reserved CPU core count: " << reservedCoreCount << endl;
}
CStringPtr pCores = interfaceTLNodeMap.GetNode("ReceiveSideScalingReservedCores");
if (IsReadable(pCores))
{
if (hasReservedCoreCount && reservedCoreCount == 0)
{
cout << " Reserved CPU cores: None" << endl;
}
else
{
const std::string coreList = std::string(pCores->GetValue());
if (coreList.empty() || coreList == "false" || coreList == "False" || coreList == "FALSE")
{
cout << " Reserved CPU cores: None" << endl;
}
else
{
cout << " Reserved CPU cores: " << coreList << endl;
}
}
}
}
catch (Spinnaker::Exception& e)
{
cout << "Error configuring " << targetInterfaceName << ": " << e.what() << endl;
result = -1;
}
if (settingsChanged)
{
try
{
INodeMap& interfaceTLNodeMap = pTargetInterface->GetTLNodeMap();
CStringPtr pReservedCores = interfaceTLNodeMap.GetNode("ReceiveSideScalingReservedCores");
CBooleanPtr pCPUAffinityEnable = interfaceTLNodeMap.GetNode("CPUAffinityEnable");
if (IsWritable(pReservedCores))
{
if (hasOriginalReservedCores)
{
pReservedCores->SetValue(originalReservedCores.c_str());
}
}
if (hasOriginalEnable && IsWritable(pCPUAffinityEnable))
{
pCPUAffinityEnable->SetValue(originalCpuAffinityEnable);
}
cout << " Original CPU affinity settings restored" << endl;
}
catch (Spinnaker::Exception& e)
{
cout << "Error restoring original settings for " << targetInterfaceName << ": " << e.what() << endl;
result = -1;
}
}
interfaceList.Clear();
return result;
}
// Read and print interface-level CPU affinity nodes for all interfaces.
int ReadInterfaceCpuAffinityNodes(SystemPtr system)
{
int result = 0;
cout << endl << "*** INTERFACE CPU AFFINITY INFORMATION ***" << endl << endl;
InterfaceList interfaceList = system->GetInterfaces();
const unsigned int numInterfaces = interfaceList.GetSize();
cout << "Number of interfaces detected: " << numInterfaces << endl << endl;
for (unsigned int i = 0; i < numInterfaces; i++)
{
try
{
InterfacePtr pInterface = interfaceList.GetByIndex(i);
INodeMap& interfaceTLNodeMap = pInterface->GetTLNodeMap();
try
{
CStringPtr pInterfaceDisplayName = interfaceTLNodeMap.GetNode("InterfaceDisplayName");
if (IsReadable(pInterfaceDisplayName))
{
cout << "Interface " << i << ": " << pInterfaceDisplayName->GetValue() << endl;
}
}
catch (Spinnaker::Exception&)
{
cout << "Interface " << i << ": (name not available)" << endl;
}
bool hasReservedCoreCount = false;
int64_t reservedCoreCount = 0;
try
{
CIntegerPtr pReservedCoreCount = interfaceTLNodeMap.GetNode("ReceiveSideScalingReservedCoresCount");
if (IsReadable(pReservedCoreCount))
{
reservedCoreCount = pReservedCoreCount->GetValue();
hasReservedCoreCount = true;
cout << " Reserved CPU Core Count: " << reservedCoreCount << endl;
}
else
{
cout << " Reserved CPU Core Count: (not available on this interface)" << endl;
}
}
catch (Spinnaker::Exception&)
{
cout << " Reserved CPU Core Count: (not available on this interface)" << endl;
}
try
{
CStringPtr pReservedCores = interfaceTLNodeMap.GetNode("ReceiveSideScalingReservedCores");
if (IsReadable(pReservedCores))
{
if (hasReservedCoreCount && reservedCoreCount == 0)
{
cout << " Reserved CPU Cores: None" << endl;
}
else
{
cout << " Reserved CPU Cores: " << pReservedCores->GetValue() << endl;
}
}
else
{
cout << " Reserved CPU Cores: (not available on this interface)" << endl;
}
}
catch (Spinnaker::Exception&)
{
cout << " Reserved CPU Cores: (not available on this interface)" << endl;
}
try
{
CBooleanPtr pCPUAffinityEnable = interfaceTLNodeMap.GetNode("CPUAffinityEnable");
if (IsAvailable(pCPUAffinityEnable))
{
if (IsReadable(pCPUAffinityEnable))
{
cout << " CPU Affinity Enable: " << (pCPUAffinityEnable->GetValue() ? "true" : "false")
<< endl;
}
if (IsWritable(pCPUAffinityEnable))
{
cout << " CPU Affinity Enable node is writable" << endl;
}
else
{
cout << " CPU Affinity Enable node is not writable (may require admin privileges)" << endl;
}
}
else
{
cout << " CPU Affinity Enable: (not available on this interface)" << endl;
}
}
catch (Spinnaker::Exception&)
{
cout << " CPU Affinity Enable: (not available on this interface)" << endl;
}
cout << endl;
}
catch (Spinnaker::Exception& e)
{
cout << "Error accessing interface " << i << ": " << e.what() << endl;
result = -1;
}
}
interfaceList.Clear();
return result;
}
} // namespace
int main(int /*argc*/, char** /*argv*/)
{
#if !defined(_WIN32) && !defined(_WIN64)
cout << "CPUAffinity example is supported on Windows only." << endl;
return 0;
#else
int result = 0;
// Print application build information
cout << "Application build date: " << __DATE__ << " " << __TIME__ << endl << endl;
// Retrieve singleton reference to system object
SystemPtr system = System::GetInstance();
// Print out current library version
const LibraryVersion spinnakerLibraryVersion = system->GetLibraryVersion();
cout << "Spinnaker library version: " << spinnakerLibraryVersion.major << "." << spinnakerLibraryVersion.minor
<< "." << spinnakerLibraryVersion.type << "." << spinnakerLibraryVersion.build << endl
<< endl;
INodeMap& systemTLNodeMap = system->GetTLNodeMap();
//
// Read GenTL system nodes related to CPU affinity.
//
// *** NOTES ***
// These nodes report privilege level, service status, and available CPU cores.
//
result = result | ReadCpuAffinitySystemNodes(systemTLNodeMap);
//
// Inspect CPU affinity service control command availability.
//
// *** NOTES ***
// Start/stop command nodes may be present but writable only with admin privileges.
//
result = result | ShowCpuAffinityControlNodes(systemTLNodeMap);
//
// Read GenTL system nodes related to media optimization.
//
// *** NOTES ***
// These nodes report privilege level and whether media optimization is enabled.
//
result = result | ReadMediaOptimizationSystemNodes(systemTLNodeMap);
//
// Inspect media optimization control node access.
//
// *** NOTES ***
// The enable node may be readable but not writable without elevated permissions.
//
result = result | ShowMediaOptimizationControlNodes(systemTLNodeMap);
//
// Read interface-level CPU affinity nodes.
//
// *** NOTES ***
// This checks reserved core settings and command access for each detected interface.
//
result = result | ReadInterfaceCpuAffinityNodes(system);
//
// Optionally enable CPU affinity on GigE interfaces.
//
// *** NOTES ***
// This step is disabled by default. Set configureCpuAffinity = true at the
// top of this file to enable it. Update reservedCoresToSet above to choose
// which cores to reserve for the selected interface. Admin privileges are
// required to write both ReceiveSideScalingReservedCores and CPUAffinityEnable.
//
if (configureCpuAffinity)
{
result = result | ConfigureInterfaceCpuAffinity(system);
}
//
// Release system
//
// *** NOTES ***
// The system should be released when no longer needed. If not released
// explicitly, it will clean up automatically when all SystemPtr objects
// go out of scope.
//
system->ReleaseInstance();
cout << endl << "CPU Affinity example complete." << endl;
cout << "Done! Press Enter to exit..." << endl;
getchar();
return result;
#endif
}