@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Runtime.CompilerServices ;
using System.Runtime.CompilerServices ;
using System.Runtime.InteropServices ;
using System.Runtime.InteropServices ;
using System.Threading ;
using System.Threading ;
using Avalonia.Compatibility ;
namespace Avalonia.Platform.Internal ;
namespace Avalonia.Platform.Internal ;
@ -108,21 +109,15 @@ internal class UnmanagedBlob : IDisposable
public int Size { get ; private set ; }
public int Size { get ; private set ; }
public bool IsDisposed { get ; private set ; }
public bool IsDisposed { get ; private set ; }
[DllImport("libc", SetLastError = true )]
[DllImport("libc")]
private static extern IntPtr mmap ( IntPtr addr , IntPtr length , int prot , int flags , int fd , IntPtr offset ) ;
private static extern IntPtr mmap ( IntPtr addr , IntPtr length , int prot , int flags , int fd , IntPtr offset ) ;
[DllImport("libc", SetLastError = true )]
[DllImport("libc")]
private static extern int munmap ( IntPtr addr , IntPtr length ) ;
private static extern int munmap ( IntPtr addr , IntPtr length ) ;
[DllImport("libc", SetLastError = true)]
private static extern long sysconf ( int name ) ;
private bool? _ useMmap ;
private bool UseMmap
= > _ useMmap ? ? ( ( _ useMmap = RuntimeInformation . IsOSPlatform ( OSPlatform . Linux ) ) . Value ) ;
// Could be replaced with https://github.com/dotnet/runtime/issues/40892 when it will be available.
// Could be replaced with https://github.com/dotnet/runtime/issues/40892 when it will be available.
private IntPtr Alloc ( int size )
private IntPtr Alloc ( int size )
{
{
if ( ! UseMmap )
if ( ! OperatingSystemEx . IsLinux ( ) )
{
{
return Marshal . AllocHGlobal ( size ) ;
return Marshal . AllocHGlobal ( size ) ;
}
}
@ -131,8 +126,12 @@ internal class UnmanagedBlob : IDisposable
var rv = mmap ( IntPtr . Zero , new IntPtr ( size ) , 3 , 0x22 , - 1 , IntPtr . Zero ) ;
var rv = mmap ( IntPtr . Zero , new IntPtr ( size ) , 3 , 0x22 , - 1 , IntPtr . Zero ) ;
if ( rv . ToInt64 ( ) = = - 1 | | ( ulong ) rv . ToInt64 ( ) = = 0xffffffff )
if ( rv . ToInt64 ( ) = = - 1 | | ( ulong ) rv . ToInt64 ( ) = = 0xffffffff )
{
{
var errno = Marshal . GetLastWin32Error ( ) ;
#if NET6_0_OR_GREATER
var errno = Marshal . GetLastSystemError ( ) ;
throw new Exception ( "Unable to allocate memory: " + errno ) ;
throw new Exception ( "Unable to allocate memory: " + errno ) ;
#else
throw new Exception ( "Unable to allocate memory" ) ;
#endif
}
}
return rv ;
return rv ;
}
}
@ -140,7 +139,7 @@ internal class UnmanagedBlob : IDisposable
private void Free ( IntPtr ptr , int len )
private void Free ( IntPtr ptr , int len )
{
{
if ( ! UseMmap )
if ( ! OperatingSystemEx . IsLinux ( ) )
{
{
Marshal . FreeHGlobal ( ptr ) ;
Marshal . FreeHGlobal ( ptr ) ;
}
}
@ -148,8 +147,12 @@ internal class UnmanagedBlob : IDisposable
{
{
if ( munmap ( ptr , new IntPtr ( len ) ) = = - 1 )
if ( munmap ( ptr , new IntPtr ( len ) ) = = - 1 )
{
{
var errno = Marshal . GetLastWin32Error ( ) ;
#if NET6_0_OR_GREATER
var errno = Marshal . GetLastSystemError ( ) ;
throw new Exception ( "Unable to free memory: " + errno ) ;
throw new Exception ( "Unable to free memory: " + errno ) ;
#else
throw new Exception ( "Unable to free memory" ) ;
#endif
}
}
}
}
}
}