#pragma once #include #include #include // Forward declarations typedef struct IORING_HANDLE_REF IORING_HANDLE_REF; typedef struct IORING_BUFFER_REF IORING_BUFFER_REF; typedef void *HIORING; /* --------------------- Types declaration --------------------- */ typedef enum IORING_CREATE_ADVISORY_FLAGS { IORING_CREATE_ADVISORY_FLAGS_NONE, IORING_CREATE_SKIP_BUILDER_PARAM_CHECKS } IORING_CREATE_ADVISORY_FLAGS; // Specifies advisory flags for creating an I/O ring with a call to // CreateIoRing. typedef enum IORING_CREATE_REQUIRED_FLAGS { IORING_CREATE_REQUIRED_FLAGS_NONE } IORING_CREATE_REQUIRED_FLAGS; // Specifies required flags for creating an I/O ring with a call to // CreateIoRing. typedef enum IORING_REF_KIND { IORING_REF_RAW = 0, IORING_REF_REGISTERED = 1, } IORING_REF_KIND; // Specifies the type of an IORING_HANDLE_REF structure. typedef enum IORING_SQE_FLAGS { IOSQE_FLAGS_NONE, IOSQE_FLAGS_DRAIN_PRECEDING_OPS } IORING_SQE_FLAGS; // Specifies kernel behavior options for I/O ring submission queue entries // IORING_REGISTERED_BUFFER structure typedef struct IORING_REGISTERED_BUFFER { UINT32 Index; UINT32 Offset; } IORING_REGISTERED_BUFFER; // IORING_HANDLE_REF struct IORING_HANDLE_REF { IORING_REF_KIND Kind; union { HANDLE Handle; UINT32 Index; } HandleUnion; }; // Represents a reference to a file handle used in an I/O ring operation // IORING_BUFFER_REF struct IORING_BUFFER_REF { IORING_REF_KIND Kind; union { void *Address; IORING_REGISTERED_BUFFER IndexAndOffset; } BufferUnion; }; typedef struct IORING_BUFFER_INFO { void *Address; UINT32 Length; } IORING_BUFFER_INFO; // IORING_BUFFER_REF represents a reference to a buffer used in an I/O ring // operation // IORING_VERSION enumeration typedef enum IORING_VERSION { IORING_VERSION_INVALID = 0, IORING_VERSION_1 = 1, IORING_VERSION_2 = 2, IORING_VERSION_3 = 3, IORING_VERSION_4 = 4, } IORING_VERSION; typedef enum IORING_FEATURE_FLAGS { IORING_FEATURE_FLAGS_NONE = 0, IORING_FEATURE_UM_EMULATION = 1 } IORING_FEATURE_FLAGS; // IORING_CAPABILITIES structure typedef struct IORING_CAPABILITIES { IORING_VERSION MaxVersion; UINT32 MaxSubmissionQueueSize; UINT32 MaxCompletionQueueSize; IORING_FEATURE_FLAGS FeatureFlags; } IORING_CAPABILITIES; // Represents the IORING API capabilities. // IORING_CQE structure typedef struct IORING_CQE { UINT_PTR UserData; HRESULT ResultCode; ULONG_PTR Information; } IORING_CQE; // Represents a completed I/O ring queue entry. // IORING_CREATE_FLAGS structure typedef struct IORING_CREATE_FLAGS { IORING_CREATE_REQUIRED_FLAGS Required; IORING_CREATE_ADVISORY_FLAGS Advisory; } IORING_CREATE_FLAGS; // Specifies flags for creating an I/O ring with a call to CreateIoRing. // IORING_INFO structure typedef struct IORING_INFO { IORING_VERSION IoRingVersion; IORING_CREATE_FLAGS Flags; UINT32 SubmissionQueueSize; UINT32 CompletionQueueSize; } IORING_INFO; // Represents the shape and version information for the specified I/O ring // IORING_OP_CODE for IsIoRingOpSupported typedef enum IORING_OP_CODE { IORING_OP_NOP = 0, IORING_OP_READ = 1, IORING_OP_WRITE = 2, IORING_OP_FLUSH = 3, IORING_OP_REGISTER_BUFFERS = 4, IORING_OP_REGISTER_FILES = 5, IORING_OP_CANCEL = 6, } IORING_OP_CODE; /* --------------------- Dynamic loader --------------------- */ // Function pointer types typedef BOOL(WINAPI *IsIoRingOpSupported_t)(HIORING, IORING_OP_CODE); typedef HRESULT(WINAPI *QueryIoRingCapabilities_t)(IORING_CAPABILITIES *); typedef HRESULT(WINAPI *GetIoRingInfo_t)(HIORING, IORING_INFO *); typedef HRESULT(WINAPI *CreateIoRing_t)(IORING_VERSION, IORING_CREATE_FLAGS, UINT32, UINT32, HIORING *); typedef HRESULT(WINAPI *CloseIoRing_t)(HIORING); typedef HRESULT(WINAPI *SubmitIoRing_t)(HIORING, UINT32, UINT32, UINT32 *); typedef HRESULT(WINAPI *PopIoRingCompletion_t)(HIORING, IORING_CQE *); typedef HRESULT(WINAPI *SetIoRingCompletionEvent_t)(HIORING, HANDLE); typedef HRESULT(WINAPI *BuildIoRingCancelRequest_t)(HIORING, IORING_HANDLE_REF, UINT_PTR, UINT_PTR); typedef HRESULT(WINAPI *BuildIoRingReadFile_t)(HIORING, IORING_HANDLE_REF, IORING_BUFFER_REF, UINT32, UINT64, UINT_PTR, IORING_SQE_FLAGS); typedef HRESULT(WINAPI *BuildIoRingRegisterBuffers_t)( HIORING, UINT32, IORING_BUFFER_INFO const[], UINT_PTR); typedef HRESULT(WINAPI *BuildIoRingRegisterFileHandles_t)(HIORING, UINT32, HANDLE const[], UINT_PTR); // Core: // Queries the support of the specified operation for the specified I/O ring static IsIoRingOpSupported_t IsIoRingOpSupported = NULL; // Queries the OS for the supported capabilities for IORINGs static QueryIoRingCapabilities_t QueryIoRingCapabilities = NULL; // Gets information about the API version and queue sizes of an I/O ring static GetIoRingInfo_t GetIoRingInfo = NULL; // Creates a new instance of an I/O ring submission/completion queue pair and // returns a handle for referencing the I/O ring static CreateIoRing_t CreateIoRing = NULL; // Closes an HIORING handle that was previously opened with a call to // CreateIoRing static CloseIoRing_t CloseIoRing = NULL; // Submission / completion: // Submits all constructed but not yet submitted entries to the kernel’s queue // and optionally waits for a set of operations to complete static SubmitIoRing_t SubmitIoRing = NULL; // Pops a single entry from the completion queue, if one is available static PopIoRingCompletion_t PopIoRingCompletion = NULL; // Registers a completion queue event with an IORING static SetIoRingCompletionEvent_t SetIoRingCompletionEvent = NULL; // Operations: // Performs an asynchronous read from a file using an I/O ring static BuildIoRingReadFile_t BuildIoRingReadFile = NULL; // Attempts to cancel a previously submitted I/O ring operation static BuildIoRingCancelRequest_t BuildIoRingCancelRequest = NULL; // Registers an array of buffers with the system for future I/O ring operations static BuildIoRingRegisterBuffers_t BuildIoRingRegisterBuffers = NULL; // Registers an array of file handles with the system for future I/O ring // operations static BuildIoRingRegisterFileHandles_t BuildIoRingRegisterFileHandles = NULL; static int io_ring_loaded = 0; static int io_ring_load_functions(void) { if (io_ring_loaded) return 1; HMODULE hKernel = GetModuleHandleW(L"kernel32.dll"); if (!hKernel) return 0; IsIoRingOpSupported = (IsIoRingOpSupported_t)GetProcAddress(hKernel, "IsIoRingOpSupported"); QueryIoRingCapabilities = (QueryIoRingCapabilities_t)GetProcAddress( hKernel, "QueryIoRingCapabilities"); GetIoRingInfo = (GetIoRingInfo_t)GetProcAddress(hKernel, "GetIoRingInfo"); CreateIoRing = (CreateIoRing_t)GetProcAddress(hKernel, "CreateIoRing"); CloseIoRing = (CloseIoRing_t)GetProcAddress(hKernel, "CloseIoRing"); SubmitIoRing = (SubmitIoRing_t)GetProcAddress(hKernel, "SubmitIoRing"); PopIoRingCompletion = (PopIoRingCompletion_t)GetProcAddress(hKernel, "PopIoRingCompletion"); SetIoRingCompletionEvent = (SetIoRingCompletionEvent_t)GetProcAddress( hKernel, "SetIoRingCompletionEvent"); BuildIoRingReadFile = (BuildIoRingReadFile_t)GetProcAddress(hKernel, "BuildIoRingReadFile"); BuildIoRingCancelRequest = (BuildIoRingCancelRequest_t)GetProcAddress( hKernel, "BuildIoRingCancelRequest"); BuildIoRingRegisterBuffers = (BuildIoRingRegisterBuffers_t)GetProcAddress( hKernel, "BuildIoRingRegisterBuffers"); BuildIoRingRegisterFileHandles = (BuildIoRingRegisterFileHandles_t)GetProcAddress( hKernel, "BuildIoRingRegisterFileHandles"); io_ring_loaded = (IsIoRingOpSupported && QueryIoRingCapabilities && CreateIoRing && CloseIoRing && SubmitIoRing && PopIoRingCompletion && SetIoRingCompletionEvent && BuildIoRingReadFile && BuildIoRingCancelRequest && BuildIoRingRegisterBuffers && BuildIoRingRegisterFileHandles); if (io_ring_loaded) printf("[I/O Ring] Functions loaded\n"); else printf("[I/O Ring] Some functions not available\n"); return io_ring_loaded; } /* ------------- Standard helper functions definition ------------- */ // Creates an instance of the IORING_BUFFER_REF structure with the provided // buffer index and offset static inline IORING_BUFFER_REF IoRingBufferRefFromIndexAndOffset(UINT32 index, UINT32 offset) { IORING_BUFFER_REF ref; ref.Kind = IORING_REF_REGISTERED; ref.BufferUnion.IndexAndOffset.Index = index; ref.BufferUnion.IndexAndOffset.Offset = offset; return ref; } // Creates an instance of the IORING_BUFFER_REF structure from the provided // pointer static IORING_BUFFER_REF IoRingBufferRefFromPointer(void *addr) { IORING_BUFFER_REF ref; ref.Kind = IORING_REF_RAW; ref.BufferUnion.Address = addr; return ref; } // Creates an instance of the IORING_HANDLE_REF structure from the provided file // handle static IORING_HANDLE_REF IoRingHandleRefFromHandle(HANDLE h) { IORING_HANDLE_REF ref; ref.Kind = IORING_REF_RAW; ref.HandleUnion.Handle = h; return ref; } // Creates an instance of the IORING_HANDLE_REF structure from the provided // index static inline IORING_HANDLE_REF IoRingHandleRefFromIndex(UINT32 index) { IORING_HANDLE_REF ref; ref.Kind = IORING_REF_REGISTERED; // MUST be registered ref.HandleUnion.Index = index; return ref; } // NOTE: If you are using index-based buffers or handles, make sure you have // successfully called BuildIoRingRegisterBuffers or // BuildIoRingRegisterFileHandles first so the kernel has a valid table to look // into, otherwise the kernel will treat the index as an invalid memory // address/handle.