mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-03-23 18:42:45 +08:00
asyncio: Windows IoRing support, other tweaks and fixes.
This commit is contained in:
@@ -522,6 +522,7 @@
|
||||
<ClCompile Include="..\..\src\filesystem\windows\SDL_sysfsops.c" />
|
||||
<ClCompile Include="..\..\src\file\generic\SDL_asyncio_generic.c" />
|
||||
<ClCompile Include="..\..\src\file\SDL_asyncio.c" />
|
||||
<ClCompile Include="..\..\src\file\windows\SDL_asyncio_windows_ioring.c" />
|
||||
<ClCompile Include="..\..\src\main\gdk\SDL_sysmain_runapp.cpp" />
|
||||
<ClCompile Include="..\..\src\main\generic\SDL_sysmain_callbacks.c" />
|
||||
<ClCompile Include="..\..\src\main\SDL_main_callbacks.c" />
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
<ClCompile Include="..\..\src\file\SDL_asyncio.c">
|
||||
<Filter>file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\file\windows\SDL_asyncio_windows_ioring.c">
|
||||
<Filter>file\windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\render\direct3d12\SDL_render_d3d12_xbox.cpp" />
|
||||
<ClCompile Include="..\..\src\render\direct3d12\SDL_shaders_d3d12_xboxone.cpp" />
|
||||
<ClCompile Include="..\..\src\render\direct3d12\SDL_shaders_d3d12_xboxseries.cpp" />
|
||||
|
||||
@@ -415,6 +415,7 @@
|
||||
<ClCompile Include="..\..\src\dialog\SDL_dialog_utils.c" />
|
||||
<ClCompile Include="..\..\src\filesystem\SDL_filesystem.c" />
|
||||
<ClCompile Include="..\..\src\filesystem\windows\SDL_sysfsops.c" />
|
||||
<ClCompile Include="..\..\src\file\windows\SDL_asyncio_windows_ioring.c" />
|
||||
<ClCompile Include="..\..\src\gpu\SDL_gpu.c" />
|
||||
<ClCompile Include="..\..\src\gpu\d3d12\SDL_gpu_d3d12.c" />
|
||||
<ClCompile Include="..\..\src\gpu\vulkan\SDL_gpu_vulkan.c" />
|
||||
|
||||
@@ -214,6 +214,9 @@
|
||||
<Filter Include="file\generic">
|
||||
<UniqueIdentifier>{00004d6806b6238cae0ed62db5440000}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="file\windows">
|
||||
<UniqueIdentifier>{000028b2ea36d7190d13777a4dc70000}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\include\SDL3\SDL_begin_code.h">
|
||||
@@ -962,6 +965,9 @@
|
||||
<ClCompile Include="..\..\src\file\SDL_asyncio.c">
|
||||
<Filter>file</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\file\windows\SDL_asyncio_windows_ioring.c">
|
||||
<Filter>file\windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\main\generic\SDL_sysmain_callbacks.c">
|
||||
<Filter>main\generic</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -552,6 +552,7 @@
|
||||
00005081394CCF8322BE0000 /* SDL_sysasyncio.h in Headers */ = {isa = PBXBuildFile; fileRef = 0000585B2CAB450B40540000 /* SDL_sysasyncio.h */; };
|
||||
000018AF97C08F2DAFFD0000 /* SDL_asyncio.h in Headers */ = {isa = PBXBuildFile; fileRef = 00004945A946DF5B1AED0000 /* SDL_asyncio.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
00004D0B73767647AD550000 /* SDL_asyncio_generic.c in Sources */ = {isa = PBXBuildFile; fileRef = 0000FB02CDE4BE34A87E0000 /* SDL_asyncio_generic.c */; };
|
||||
0000A03C0F32C43816F40000 /* SDL_asyncio_windows_ioring.c in Sources */ = {isa = PBXBuildFile; fileRef = 000030DD21496B5C0F210000 /* SDL_asyncio_windows_ioring.c */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -1134,6 +1135,7 @@
|
||||
0000585B2CAB450B40540000 /* SDL_sysasyncio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_sysasyncio.h; path = SDL_sysasyncio.h; sourceTree = "<group>"; };
|
||||
00004945A946DF5B1AED0000 /* SDL_asyncio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_asyncio.h; path = SDL3/SDL_asyncio.h; sourceTree = "<group>"; };
|
||||
0000FB02CDE4BE34A87E0000 /* SDL_asyncio_generic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_asyncio_generic.c; path = SDL_asyncio_generic.c; sourceTree = "<group>"; };
|
||||
000030DD21496B5C0F210000 /* SDL_asyncio_windows_ioring.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_asyncio_windows_ioring.c; path = SDL_asyncio_windows_ioring.c; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -1947,6 +1949,7 @@
|
||||
0000919399B1A908267F0000 /* SDL_asyncio_c.h */,
|
||||
0000585B2CAB450B40540000 /* SDL_sysasyncio.h */,
|
||||
000013C0F2EADC24ADC10000 /* generic */,
|
||||
000064F9A2AAE947C1CD0000 /* windows */,
|
||||
);
|
||||
path = file;
|
||||
sourceTree = "<group>";
|
||||
@@ -2447,6 +2450,14 @@
|
||||
path = generic;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
000064F9A2AAE947C1CD0000 /* windows */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
000030DD21496B5C0F210000 /* SDL_asyncio_windows_ioring.c */,
|
||||
);
|
||||
path = windows;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
@@ -3073,6 +3084,7 @@
|
||||
6312C66D2B42341400A7BB00 /* SDL_murmur3.c in Sources */,
|
||||
0000AEB9AE90228CA2D60000 /* SDL_asyncio.c in Sources */,
|
||||
00004D0B73767647AD550000 /* SDL_asyncio_generic.c in Sources */,
|
||||
0000A03C0F32C43816F40000 /* SDL_asyncio_windows_ioring.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -24,11 +24,17 @@
|
||||
#ifndef SDL_sysasyncio_h_
|
||||
#define SDL_sysasyncio_h_
|
||||
|
||||
#if defined(SDL_PLATFORM_WINDOWS) && defined(NTDDI_WIN10_CO)
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && NTDDI_VERSION >= NTDDI_WIN10_CO
|
||||
#define HAVE_IORINGAPI_H
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// If your platform has an option other than the "generic" code, make sure this
|
||||
// is #defined to 0 instead and implement the SDL_SYS_* functions below in your
|
||||
// backend (having them maybe call into the SDL_SYS_*_Generic versions as a
|
||||
// fallback if the platform has functionality that isn't always available).
|
||||
#ifdef HAVE_LIBURING_H
|
||||
#if defined(HAVE_LIBURING_H) || defined(HAVE_IORINGAPI_H)
|
||||
#define SDL_ASYNCIO_ONLY_HAVE_GENERIC 0
|
||||
#else
|
||||
#define SDL_ASYNCIO_ONLY_HAVE_GENERIC 1
|
||||
|
||||
@@ -130,6 +130,7 @@ static bool LoadLibUring(void)
|
||||
result = LoadLibUringSyms();
|
||||
if (result) {
|
||||
static const int needed_ops[] = {
|
||||
IORING_OP_NOP,
|
||||
IORING_OP_FSYNC,
|
||||
IORING_OP_TIMEOUT,
|
||||
IORING_OP_CLOSE,
|
||||
@@ -193,16 +194,21 @@ static void liburing_asyncioqueue_cancel_task(void *userdata, SDL_AsyncIOTask *t
|
||||
}
|
||||
|
||||
LibUringAsyncIOQueueData *queuedata = (LibUringAsyncIOQueueData *) userdata;
|
||||
|
||||
// have to hold a lock because otherwise two threads could get_sqe and submit while one request isn't fully set up.
|
||||
SDL_LockMutex(queuedata->sqe_lock);
|
||||
struct io_uring_sqe *sqe = liburing.io_uring_get_sqe(&queuedata->ring);
|
||||
if (!sqe) {
|
||||
SDL_free(cancel_task);
|
||||
return; // oh well, the task can just finish on its own.
|
||||
SDL_UnlockMutex(queuedata->sqe_lock);
|
||||
SDL_free(cancel_task); // oh well, the task can just finish on its own.
|
||||
return;
|
||||
}
|
||||
|
||||
cancel_task->app_userdata = task;
|
||||
liburing.io_uring_prep_cancel(sqe, task, 0);
|
||||
liburing.io_uring_sqe_set_data(sqe, cancel_task);
|
||||
liburing_asyncioqueue_queue_task(userdata, task);
|
||||
SDL_UnlockMutex(queuedata->sqe_lock);
|
||||
}
|
||||
|
||||
static SDL_AsyncIOTask *ProcessCQE(LibUringAsyncIOQueueData *queuedata, struct io_uring_cqe *cqe)
|
||||
@@ -375,15 +381,15 @@ static bool liburing_asyncio_read(void *userdata, SDL_AsyncIOTask *task)
|
||||
|
||||
// have to hold a lock because otherwise two threads could get_sqe and submit while one request isn't fully set up.
|
||||
SDL_LockMutex(queuedata->sqe_lock);
|
||||
bool retval;
|
||||
struct io_uring_sqe *sqe = liburing.io_uring_get_sqe(&queuedata->ring);
|
||||
if (!sqe) {
|
||||
return SDL_SetError("io_uring: submission queue is full");
|
||||
}
|
||||
|
||||
retval = SDL_SetError("io_uring: submission queue is full");
|
||||
} else {
|
||||
liburing.io_uring_prep_read(sqe, fd, task->buffer, (unsigned) task->requested_size, task->offset);
|
||||
liburing.io_uring_sqe_set_data(sqe, task);
|
||||
|
||||
const bool retval = task->queue->iface.queue_task(task->queue->userdata, task);
|
||||
retval = task->queue->iface.queue_task(task->queue->userdata, task);
|
||||
}
|
||||
SDL_UnlockMutex(queuedata->sqe_lock);
|
||||
return retval;
|
||||
}
|
||||
@@ -401,15 +407,15 @@ static bool liburing_asyncio_write(void *userdata, SDL_AsyncIOTask *task)
|
||||
|
||||
// have to hold a lock because otherwise two threads could get_sqe and submit while one request isn't fully set up.
|
||||
SDL_LockMutex(queuedata->sqe_lock);
|
||||
bool retval;
|
||||
struct io_uring_sqe *sqe = liburing.io_uring_get_sqe(&queuedata->ring);
|
||||
if (!sqe) {
|
||||
return SDL_SetError("io_uring: submission queue is full");
|
||||
}
|
||||
|
||||
retval = SDL_SetError("io_uring: submission queue is full");
|
||||
} else {
|
||||
liburing.io_uring_prep_write(sqe, fd, task->buffer, (unsigned) task->requested_size, task->offset);
|
||||
liburing.io_uring_sqe_set_data(sqe, task);
|
||||
|
||||
const bool retval = task->queue->iface.queue_task(task->queue->userdata, task);
|
||||
retval = task->queue->iface.queue_task(task->queue->userdata, task);
|
||||
}
|
||||
SDL_UnlockMutex(queuedata->sqe_lock);
|
||||
return retval;
|
||||
}
|
||||
@@ -421,11 +427,11 @@ static bool liburing_asyncio_close(void *userdata, SDL_AsyncIOTask *task)
|
||||
|
||||
// have to hold a lock because otherwise two threads could get_sqe and submit while one request isn't fully set up.
|
||||
SDL_LockMutex(queuedata->sqe_lock);
|
||||
bool retval;
|
||||
struct io_uring_sqe *sqe = liburing.io_uring_get_sqe(&queuedata->ring);
|
||||
if (!sqe) {
|
||||
return SDL_SetError("io_uring: submission queue is full");
|
||||
}
|
||||
|
||||
retval = SDL_SetError("io_uring: submission queue is full");
|
||||
} else {
|
||||
if (task->flush) {
|
||||
struct io_uring_sqe *flush_sqe = sqe;
|
||||
sqe = liburing.io_uring_get_sqe(&queuedata->ring); // this will be our actual close task.
|
||||
@@ -433,9 +439,9 @@ static bool liburing_asyncio_close(void *userdata, SDL_AsyncIOTask *task)
|
||||
liburing.io_uring_prep_nop(flush_sqe); // we already have the first sqe, just make it a NOP.
|
||||
liburing.io_uring_sqe_set_data(flush_sqe, NULL);
|
||||
task->queue->iface.queue_task(task->queue->userdata, task);
|
||||
SDL_UnlockMutex(queuedata->sqe_lock);
|
||||
return SDL_SetError("io_uring: submission queue is full");
|
||||
}
|
||||
|
||||
liburing.io_uring_prep_fsync(flush_sqe, fd, IORING_FSYNC_DATASYNC);
|
||||
liburing.io_uring_sqe_set_data(flush_sqe, task);
|
||||
liburing.io_uring_sqe_set_flags(flush_sqe, IOSQE_IO_HARDLINK); // must complete before next sqe starts, and next sqe should run even if this fails.
|
||||
@@ -444,7 +450,8 @@ static bool liburing_asyncio_close(void *userdata, SDL_AsyncIOTask *task)
|
||||
liburing.io_uring_prep_close(sqe, fd);
|
||||
liburing.io_uring_sqe_set_data(sqe, task);
|
||||
|
||||
const bool retval = task->queue->iface.queue_task(task->queue->userdata, task);
|
||||
retval = task->queue->iface.queue_task(task->queue->userdata, task);
|
||||
}
|
||||
SDL_UnlockMutex(queuedata->sqe_lock);
|
||||
return retval;
|
||||
}
|
||||
|
||||
551
src/file/windows/SDL_asyncio_windows_ioring.c
Normal file
551
src/file/windows/SDL_asyncio_windows_ioring.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user