117 lines
3.8 KiB
C#
117 lines
3.8 KiB
C#
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,
|
|
}
|
|
|