Initial commit
This commit is contained in:
116
srcs/RobotNet10/Commons/RobotNet10.Realtime/MemoryLock.cs
Normal file
116
srcs/RobotNet10/Commons/RobotNet10.Realtime/MemoryLock.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace RobotNet10.Realtime;
|
||||
|
||||
/// <summary>
|
||||
/// Provides memory locking functionality for real-time applications.
|
||||
/// Prevents memory from being swapped to disk, ensuring deterministic access times.
|
||||
/// </summary>
|
||||
public static class MemoryLock
|
||||
{
|
||||
/// <summary>
|
||||
/// Locks a specific memory region to prevent swapping.
|
||||
/// </summary>
|
||||
/// <param name="address">Pointer to the memory region</param>
|
||||
/// <param name="length">Length of the memory region in bytes</param>
|
||||
/// <exception cref="InvalidOperationException">Thrown when the operation fails.</exception>
|
||||
public static void Lock(IntPtr address, IntPtr length)
|
||||
{
|
||||
int result = LinuxNative.mlock(address, length);
|
||||
if (result != 0)
|
||||
{
|
||||
LinuxNative.ThrowLastError("mlock");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks a specific memory region.
|
||||
/// </summary>
|
||||
/// <param name="address">Pointer to the memory region</param>
|
||||
/// <param name="length">Length of the memory region in bytes</param>
|
||||
/// <exception cref="InvalidOperationException">Thrown when the operation fails.</exception>
|
||||
public static void Unlock(IntPtr address, IntPtr length)
|
||||
{
|
||||
int result = LinuxNative.munlock(address, length);
|
||||
if (result != 0)
|
||||
{
|
||||
LinuxNative.ThrowLastError("munlock");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locks all current and future memory pages for the process.
|
||||
/// </summary>
|
||||
/// <param name="flags">Lock flags (MCL_CURRENT, MCL_FUTURE, MCL_ONFAULT)</param>
|
||||
/// <exception cref="InvalidOperationException">Thrown when the operation fails.</exception>
|
||||
public static void LockAll(MemoryLockFlags flags)
|
||||
{
|
||||
int result = LinuxNative.mlockall((int)flags);
|
||||
if (result != 0)
|
||||
{
|
||||
LinuxNative.ThrowLastError("mlockall");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unlocks all memory pages for the process.
|
||||
/// </summary>
|
||||
/// <exception cref="InvalidOperationException">Thrown when the operation fails.</exception>
|
||||
public static void UnlockAll()
|
||||
{
|
||||
int result = LinuxNative.munlockall();
|
||||
if (result != 0)
|
||||
{
|
||||
LinuxNative.ThrowLastError("munlockall");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Locks a managed array to prevent swapping.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of array elements</typeparam>
|
||||
/// <param name="array">Array to lock</param>
|
||||
/// <returns>GCHandle that must be kept alive while the memory is locked</returns>
|
||||
public static GCHandle LockArray<T>(T[] array)
|
||||
{
|
||||
GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned);
|
||||
try
|
||||
{
|
||||
IntPtr address = handle.AddrOfPinnedObject();
|
||||
IntPtr length = new IntPtr(Marshal.SizeOf<T>() * array.Length);
|
||||
Lock(address, length);
|
||||
}
|
||||
catch
|
||||
{
|
||||
handle.Free();
|
||||
throw;
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Memory locking flags.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum MemoryLockFlags
|
||||
{
|
||||
/// <summary>
|
||||
/// Lock all pages currently mapped into the address space of the process.
|
||||
/// </summary>
|
||||
Current = LinuxNative.MCL_CURRENT,
|
||||
|
||||
/// <summary>
|
||||
/// Lock all pages that will become mapped into the address space of the process in the future.
|
||||
/// </summary>
|
||||
Future = LinuxNative.MCL_FUTURE,
|
||||
|
||||
/// <summary>
|
||||
/// Lock pages that are currently mapped into the address space of the process and mark all pages
|
||||
/// that will become mapped into the address space of the process in the future to be locked
|
||||
/// when they are faulted in.
|
||||
/// </summary>
|
||||
OnFault = LinuxNative.MCL_ONFAULT,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user