using System; using System.Collections.Generic; using System.Linq; namespace RobotNet10.Realtime; /// /// Provides CPU affinity management for Linux real-time applications. /// public class CpuAffinity : IDisposable { private LinuxNative.cpu_set_t _cpuSet; private bool _disposed = false; /// /// Initializes a new instance of CpuAffinity. /// public CpuAffinity() { LinuxNative.CPU_ZERO(ref _cpuSet); } /// /// Adds a CPU to the affinity set. /// /// CPU number (0-based) public void AddCpu(int cpu) { if (cpu < 0 || cpu >= LinuxNative.CPU_SETSIZE) { throw new ArgumentOutOfRangeException(nameof(cpu), $"CPU number must be between 0 and {LinuxNative.CPU_SETSIZE - 1}"); } LinuxNative.CPU_SET(cpu, ref _cpuSet); } /// /// Removes a CPU from the affinity set. /// /// CPU number (0-based) public void RemoveCpu(int cpu) { if (cpu < 0 || cpu >= LinuxNative.CPU_SETSIZE) { throw new ArgumentOutOfRangeException(nameof(cpu), $"CPU number must be between 0 and {LinuxNative.CPU_SETSIZE - 1}"); } LinuxNative.CPU_CLR(cpu, ref _cpuSet); } /// /// Checks if a CPU is in the affinity set. /// /// CPU number (0-based) /// True if CPU is in the set, false otherwise public bool IsCpuSet(int cpu) { if (cpu < 0 || cpu >= LinuxNative.CPU_SETSIZE) { return false; } return LinuxNative.CPU_ISSET(cpu, ref _cpuSet) != 0; } /// /// Gets the number of CPUs in the affinity set. /// public int CpuCount => LinuxNative.CPU_COUNT(ref _cpuSet); /// /// Gets all CPUs in the affinity set. /// /// List of CPU numbers public List GetCpus() { var cpus = new List(); for (int i = 0; i < LinuxNative.CPU_SETSIZE; i++) { if (IsCpuSet(i)) { cpus.Add(i); } } return cpus; } /// /// Sets CPU affinity for the current thread. /// /// List of CPU numbers to set public static void SetAffinity(params int[] cpus) { var affinity = new CpuAffinity(); foreach (var cpu in cpus) { affinity.AddCpu(cpu); } affinity.Apply(); } /// /// Applies the CPU affinity to the current thread. /// public void Apply() { if (_disposed) { throw new ObjectDisposedException(nameof(CpuAffinity)); } IntPtr cpusetsize = new IntPtr(LinuxNative.CPU_SETSIZE / 8); // Size in bytes int result = LinuxNative.sched_setaffinity(0, cpusetsize, ref _cpuSet); if (result != 0) { LinuxNative.ThrowLastError("sched_setaffinity"); } } /// /// Gets the current CPU affinity for the current thread. /// /// CpuAffinity object representing current affinity public static CpuAffinity GetAffinity() { var cpuSet = new LinuxNative.cpu_set_t(); IntPtr cpusetsize = new IntPtr(LinuxNative.CPU_SETSIZE / 8); int result = LinuxNative.sched_getaffinity(0, cpusetsize, ref cpuSet); if (result != 0) { LinuxNative.ThrowLastError("sched_getaffinity"); } var affinity = new CpuAffinity(); affinity._cpuSet = cpuSet; return affinity; } /// /// Clears all CPUs from the affinity set. /// public void Clear() { LinuxNative.CPU_ZERO(ref _cpuSet); } public void Dispose() { if (!_disposed) { _disposed = true; } } }