-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AIO #1
AIO #1
Changes from all commits
5650f77
51b6a36
6cd0d74
08181a9
656c4c7
6d5bffc
f9d4de7
f6f219f
13a95bc
771a169
f652825
f5a6acb
bfad248
f16c0af
a446329
0ba4dec
8e4ed97
7352277
fb60f59
9cf5405
98214a1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
// See the LICENSE file in the project root for more information. | ||
|
||
using System; | ||
using System.Runtime.InteropServices; | ||
|
||
internal static partial class Interop | ||
{ | ||
internal static partial class Sys | ||
{ | ||
[StructLayout(LayoutKind.Sequential)] | ||
internal struct IoEvent | ||
{ | ||
internal ulong Data; | ||
internal ulong Obj; | ||
internal long Res; | ||
internal long Res2; | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential)] | ||
internal struct IoControlBlock | ||
{ | ||
internal ulong AioData; | ||
|
||
// these fields swap for big endian | ||
// https://github.com/torvalds/linux/blob/0a679e13ea30f85a1aef0669ee0c5a9fd7860b34/include/uapi/linux/aio_abi.h#L77-L83 | ||
private uint _swappedField_1; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is a little bit tricky: Linux Kernel has different order of these two fields depending on the endianess... I've encapsulated that my making them private and adding internal properties with some simple logic that handles the endianess There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wouldn't bother too much for fields that aren't used. |
||
private uint _swappedField_2; | ||
|
||
internal ushort AioLioOpcode; | ||
internal short AioReqprio; | ||
internal uint AioFildes; | ||
|
||
internal ulong AioBuf; | ||
internal ulong AioNbytes; | ||
internal long AioOffset; | ||
|
||
internal ulong AioReserved2; | ||
|
||
internal uint AioFlags; | ||
internal uint AioResfd; | ||
|
||
internal uint AioKey | ||
{ | ||
get => BitConverter.IsLittleEndian ? _swappedField_1 : _swappedField_2; | ||
set | ||
{ | ||
if (BitConverter.IsLittleEndian) | ||
{ | ||
_swappedField_1 = value; | ||
} | ||
else | ||
{ | ||
_swappedField_2 = value; | ||
} | ||
} | ||
} | ||
internal int AioRwFlags | ||
{ | ||
get => BitConverter.IsLittleEndian ? (int)_swappedField_2 : (int)_swappedField_1; | ||
set | ||
{ | ||
if (BitConverter.IsLittleEndian) | ||
{ | ||
_swappedField_2 = (uint)value; | ||
} | ||
else | ||
{ | ||
_swappedField_1 = (uint)value; | ||
} | ||
} | ||
} | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential)] | ||
internal struct AioRing | ||
{ | ||
internal uint Id; | ||
internal uint Nr; | ||
internal uint Head; | ||
internal uint Tail; | ||
internal uint Magic; | ||
internal uint CompatFeatures; | ||
internal uint IncompatFeatures; | ||
internal uint HeaderLength; | ||
|
||
internal static unsafe IoEvent* IoEvents(AioRing* ring, int idx) | ||
{ | ||
IoEvent* ev = (IoEvent*)(ring + 1); | ||
return ev + idx; | ||
} | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential)] | ||
internal struct AioContext | ||
{ | ||
internal unsafe AioRing* Ring; | ||
} | ||
|
||
internal static class IoControlBlockFlags | ||
{ | ||
internal const int IOCB_CMD_PREAD = 0; | ||
internal const int IOCB_CMD_PWRITE = 1; | ||
internal const int IOCB_CMD_FSYNC = 2; | ||
internal const int IOCB_CMD_FDSYNC = 3; | ||
// 4 was the experimental IOCB_CMD_PREADX | ||
internal const int IOCB_CMD_POLL = 5; | ||
internal const int IOCB_CMD_NOOP = 6; | ||
internal const int IOCB_CMD_PREADV = 7; | ||
internal const int IOCB_CMD_PWRITEV = 8; | ||
} | ||
|
||
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_IsAioSupported")] | ||
internal static extern bool IsAioSupported(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can be implicitly done based on IoSetup return value. |
||
|
||
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_IoSetup", SetLastError = true)] | ||
internal static extern unsafe int IoSetup(uint eventsCount, AioContext* context); | ||
|
||
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_IoDestroy", SetLastError = true)] | ||
internal static extern unsafe int IoDestroy(AioRing* ring); | ||
|
||
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_IoSubmit", SetLastError = true)] | ||
internal static extern unsafe int IoSubmit(AioRing* ring, long controlBlocksCount, IoControlBlock** ioControlBlocks); | ||
|
||
[DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_IoGetEvents", SetLastError = true)] | ||
internal static extern unsafe int IoGetEvents(AioRing* ring, long minimumEventsCount, long maximumEventsCount, IoEvent* ioEvents); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,10 @@ | |
#if HAVE_LINUX_CAN_H | ||
#include <linux/can.h> | ||
#endif | ||
#if HAVE_LINUX_AIO | ||
#include <linux/aio_abi.h> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. important: the AIO is available on Linux, but not on all Unixes (like MacOS), hence I needed this switch There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AIO is Linux only. No other OS will have this. Using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess we do not support kernels where |
||
#include <sys/syscall.h> | ||
#endif | ||
#if HAVE_KQUEUE | ||
#if KEVENT_HAS_VOID_UDATA | ||
static void* GetKeventUdata(uintptr_t udata) | ||
|
@@ -2879,3 +2883,52 @@ uint32_t SystemNative_InterfaceNameToIndex(char* interfaceName) | |
interfaceName++; | ||
return if_nametoindex(interfaceName); | ||
} | ||
|
||
int32_t SystemNative_IsAioSupported(void) | ||
{ | ||
#if HAVE_LINUX_AIO | ||
return true; | ||
#else | ||
return false; | ||
#endif | ||
} | ||
|
||
int32_t SystemNative_IoSetup(uint32_t eventsCount, AioContext* context) | ||
{ | ||
#if HAVE_LINUX_AIO | ||
return (int32_t)syscall(__NR_io_setup, eventsCount, context); | ||
#else | ||
errno = ENOTSUP; | ||
return -1; | ||
#endif | ||
} | ||
|
||
int32_t SystemNative_IoDestroy(AioRing* ring) | ||
{ | ||
#if HAVE_LINUX_AIO | ||
return (int32_t)syscall(__NR_io_destroy, ring); | ||
#else | ||
errno = ENOTSUP; | ||
return -1; | ||
#endif | ||
} | ||
|
||
int32_t SystemNative_IoSubmit(AioRing* ring, int64_t controlBlocksCount, IoControlBlock** ioControlBlocks) | ||
{ | ||
#if HAVE_LINUX_AIO | ||
return (int32_t)syscall(__NR_io_submit, ring, controlBlocksCount, ioControlBlocks); | ||
#else | ||
errno = ENOTSUP; | ||
return -1; | ||
#endif | ||
} | ||
|
||
int32_t SystemNative_IoGetEvents(AioRing* ring, int64_t minEventsCount, int64_t maxEventsCount, IoEvent* ioEvents) | ||
{ | ||
#if HAVE_LINUX_AIO | ||
return (int32_t)syscall(__NR_io_getevents, ring, minEventsCount, maxEventsCount, ioEvents, NULL); // NULL is the timeout | ||
#else | ||
errno = ENOTSUP; | ||
return -1; | ||
#endif | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you add structs that exactly match native structs, it would be nice to validate this with a shim struct and some asserts.
like is done here: https://github.com/dotnet/runtime/blob/6e83eafe49ce3c55e9f68ae669f24957e5b482f8/src/libraries/Native/Unix/System.Native/pal_networking.h#L290-L296, https://github.com/dotnet/runtime/blob/6e83eafe49ce3c55e9f68ae669f24957e5b482f8/src/libraries/Native/Unix/System.Native/pal_networking.c#L160-L165
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tmds you rather mean the C struct here I guess?