authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-22 13:21:59-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-29 06:20:51-07:00
log41070932f8a3a1dead7fb424f427b04824c19c72
tree3005b6e1f203c0ccdc39a7c8ef3e997c33bfe8dd
parentdf84dc18bc2fa18770591be4d1e0cabc8d4b28c2

revert adding asyncDetached

instead we will have Io.Group

1 files changed, 10 insertions(+), 104 deletions(-)

lib/std/Io/IoUring.zig+10-104
...@@ -10,12 +10,9 @@ const IoUring = std.os.linux.IoUring;...@@ -10,12 +10,9 @@ const IoUring = std.os.linux.IoUring;
1010
11/// Must be a thread-safe allocator.11/// Must be a thread-safe allocator.
12gpa: Allocator,12gpa: Allocator,
13mutex: std.Thread.Mutex,
13main_fiber_buffer: [@sizeOf(Fiber) + Fiber.max_result_size]u8 align(@alignOf(Fiber)),14main_fiber_buffer: [@sizeOf(Fiber) + Fiber.max_result_size]u8 align(@alignOf(Fiber)),
14threads: Thread.List,15threads: Thread.List,
15detached: struct {
16 mutex: std.Io.Mutex,
17 list: std.DoublyLinkedList,
18},
1916
20/// Empirically saw >128KB being used by the self-hosted backend to panic.17/// Empirically saw >128KB being used by the self-hosted backend to panic.
21const idle_stack_size = 256 * 1024;18const idle_stack_size = 256 * 1024;
...@@ -142,7 +139,6 @@ pub fn io(el: *EventLoop) Io {...@@ -142,7 +139,6 @@ pub fn io(el: *EventLoop) Io {
142 .async = async,139 .async = async,
143 .concurrent = concurrent,140 .concurrent = concurrent,
144 .await = await,141 .await = await,
145 .asyncDetached = asyncDetached,
146 .select = select,142 .select = select,
147 .cancel = cancel,143 .cancel = cancel,
148 .cancelRequested = cancelRequested,144 .cancelRequested = cancelRequested,
...@@ -172,16 +168,13 @@ pub fn init(el: *EventLoop, gpa: Allocator) !void {...@@ -172,16 +168,13 @@ pub fn init(el: *EventLoop, gpa: Allocator) !void {
172 errdefer gpa.free(allocated_slice);168 errdefer gpa.free(allocated_slice);
173 el.* = .{169 el.* = .{
174 .gpa = gpa,170 .gpa = gpa,
171 .mutex = .{},
175 .main_fiber_buffer = undefined,172 .main_fiber_buffer = undefined,
176 .threads = .{173 .threads = .{
177 .allocated = @ptrCast(allocated_slice[0..threads_size]),174 .allocated = @ptrCast(allocated_slice[0..threads_size]),
178 .reserved = 1,175 .reserved = 1,
179 .active = 1,176 .active = 1,
180 },177 },
181 .detached = .{
182 .mutex = .init,
183 .list = .{},
184 },
185 };178 };
186 const main_fiber: *Fiber = @ptrCast(&el.main_fiber_buffer);179 const main_fiber: *Fiber = @ptrCast(&el.main_fiber_buffer);
187 main_fiber.* = .{180 main_fiber.* = .{
...@@ -223,22 +216,6 @@ pub fn init(el: *EventLoop, gpa: Allocator) !void {...@@ -223,22 +216,6 @@ pub fn init(el: *EventLoop, gpa: Allocator) !void {
223}216}
224217
225pub fn deinit(el: *EventLoop) void {218pub fn deinit(el: *EventLoop) void {
226 while (true) cancel(el, detached_future: {
227 el.detached.mutex.lock(el.io()) catch |err| switch (err) {
228 error.Canceled => unreachable, // main fiber cannot be canceled
229 };
230 defer el.detached.mutex.unlock(el.io());
231 const detached: *DetachedClosure = @fieldParentPtr(
232 "detached_queue_node",
233 el.detached.list.pop() orelse break,
234 );
235 // notify the detached fiber that it is no longer allowed to recycle itself
236 detached.detached_queue_node = .{
237 .prev = &detached.detached_queue_node,
238 .next = &detached.detached_queue_node,
239 };
240 break :detached_future @ptrCast(detached.fiber);
241 }, &.{}, .@"1");
242 const active_threads = @atomicLoad(u32, &el.threads.active, .acquire);219 const active_threads = @atomicLoad(u32, &el.threads.active, .acquire);
243 for (el.threads.allocated[0..active_threads]) |*thread| {220 for (el.threads.allocated[0..active_threads]) |*thread| {
244 const ready_fiber = @atomicLoad(?*Fiber, &thread.ready_queue, .monotonic);221 const ready_fiber = @atomicLoad(?*Fiber, &thread.ready_queue, .monotonic);
...@@ -492,7 +469,7 @@ const SwitchMessage = struct {...@@ -492,7 +469,7 @@ const SwitchMessage = struct {
492 const PendingTask = union(enum) {469 const PendingTask = union(enum) {
493 nothing,470 nothing,
494 reschedule,471 reschedule,
495 recycle,472 recycle: *Fiber,
496 register_awaiter: *?*Fiber,473 register_awaiter: *?*Fiber,
497 register_select: []const *Io.AnyFuture,474 register_select: []const *Io.AnyFuture,
498 mutex_lock: struct {475 mutex_lock: struct {
...@@ -516,10 +493,8 @@ const SwitchMessage = struct {...@@ -516,10 +493,8 @@ const SwitchMessage = struct {
516 assert(prev_fiber.queue_next == null);493 assert(prev_fiber.queue_next == null);
517 el.schedule(thread, .{ .head = prev_fiber, .tail = prev_fiber });494 el.schedule(thread, .{ .head = prev_fiber, .tail = prev_fiber });
518 },495 },
519 .recycle => {496 .recycle => |fiber| {
520 const prev_fiber: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.prev));497 el.recycle(fiber);
521 assert(prev_fiber.queue_next == null);
522 el.recycle(prev_fiber);
523 },498 },
524 .register_awaiter => |awaiter| {499 .register_awaiter => |awaiter| {
525 const prev_fiber: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.prev));500 const prev_fiber: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.prev));
...@@ -829,12 +804,9 @@ fn fiberEntry() callconv(.naked) void {...@@ -829,12 +804,9 @@ fn fiberEntry() callconv(.naked) void {
829 switch (builtin.cpu.arch) {804 switch (builtin.cpu.arch) {
830 .x86_64 => asm volatile (805 .x86_64 => asm volatile (
831 \\ leaq 8(%%rsp), %%rdi806 \\ leaq 8(%%rsp), %%rdi
832 \\ jmpq *(%%rsp)807 \\ jmp %[AsyncClosure_call:P]
833 ),808 :
834 .aarch64 => asm volatile (809 : [AsyncClosure_call] "X" (&AsyncClosure.call),
835 \\ mov x0, sp
836 \\ ldr x2, [sp, #-8]
837 \\ br x2
838 ),810 ),
839 else => |arch| @compileError("unimplemented architecture: " ++ @tagName(arch)),811 else => |arch| @compileError("unimplemented architecture: " ++ @tagName(arch)),
840 }812 }
...@@ -905,18 +877,16 @@ fn concurrent(...@@ -905,18 +877,16 @@ fn concurrent(
905 std.log.debug("allocated {*}", .{fiber});877 std.log.debug("allocated {*}", .{fiber});
906878
907 const closure: *AsyncClosure = .fromFiber(fiber);879 const closure: *AsyncClosure = .fromFiber(fiber);
908 const stack_end: [*]align(16) usize = @ptrCast(@alignCast(closure));
909 (stack_end - 1)[0..1].* = .{@intFromPtr(&AsyncClosure.call)};
910 fiber.* = .{880 fiber.* = .{
911 .required_align = {},881 .required_align = {},
912 .context = switch (builtin.cpu.arch) {882 .context = switch (builtin.cpu.arch) {
913 .x86_64 => .{883 .x86_64 => .{
914 .rsp = @intFromPtr(stack_end - 1),884 .rsp = @intFromPtr(closure) - @sizeOf(usize),
915 .rbp = 0,885 .rbp = 0,
916 .rip = @intFromPtr(&fiberEntry),886 .rip = @intFromPtr(&fiberEntry),
917 },887 },
918 .aarch64 => .{888 .aarch64 => .{
919 .sp = @intFromPtr(stack_end),889 .sp = @intFromPtr(closure) - @sizeOf(usize) - 1,
920 .fp = 0,890 .fp = 0,
921 .pc = @intFromPtr(&fiberEntry),891 .pc = @intFromPtr(&fiberEntry),
922 },892 },
...@@ -968,70 +938,6 @@ const DetachedClosure = struct {...@@ -968,70 +938,6 @@ const DetachedClosure = struct {
968 }938 }
969};939};
970940
971fn asyncDetached(
972 userdata: ?*anyopaque,
973 context: []const u8,
974 context_alignment: std.mem.Alignment,
975 start: *const fn (context: *const anyopaque) void,
976) void {
977 assert(context_alignment.compare(.lte, Fiber.max_context_align)); // TODO
978 assert(context.len <= Fiber.max_context_size); // TODO
979
980 const event_loop: *EventLoop = @ptrCast(@alignCast(userdata));
981 const fiber = Fiber.allocate(event_loop) catch {
982 start(context.ptr);
983 return;
984 };
985 std.log.debug("allocated {*}", .{fiber});
986
987 const current_thread: *Thread = .current();
988 const closure: *DetachedClosure = @ptrFromInt(Fiber.max_context_align.max(.of(DetachedClosure)).backward(
989 @intFromPtr(fiber.allocatedEnd()) - Fiber.max_context_size,
990 ) - @sizeOf(DetachedClosure));
991 const stack_end: [*]align(16) usize = @ptrCast(@alignCast(closure));
992 (stack_end - 1)[0..1].* = .{@intFromPtr(&DetachedClosure.call)};
993 fiber.* = .{
994 .required_align = {},
995 .context = switch (builtin.cpu.arch) {
996 .x86_64 => .{
997 .rsp = @intFromPtr(stack_end - 1),
998 .rbp = 0,
999 .rip = @intFromPtr(&fiberEntry),
1000 },
1001 .aarch64 => .{
1002 .sp = @intFromPtr(stack_end),
1003 .fp = 0,
1004 .pc = @intFromPtr(&fiberEntry),
1005 },
1006 else => |arch| @compileError("unimplemented architecture: " ++ @tagName(arch)),
1007 },
1008 .awaiter = null,
1009 .queue_next = null,
1010 .cancel_thread = null,
1011 .awaiting_completions = .initEmpty(),
1012 };
1013 closure.* = .{
1014 .event_loop = event_loop,
1015 .fiber = fiber,
1016 .start = start,
1017 .detached_queue_node = .{},
1018 };
1019 {
1020 event_loop.detached.mutex.lock(event_loop.io()) catch |err| switch (err) {
1021 error.Canceled => {
1022 event_loop.recycle(fiber);
1023 start(context.ptr);
1024 return;
1025 },
1026 };
1027 defer event_loop.detached.mutex.unlock(event_loop.io());
1028 event_loop.detached.list.append(&closure.detached_queue_node);
1029 }
1030 @memcpy(closure.contextPointer(), context);
1031
1032 event_loop.schedule(current_thread, .{ .head = fiber, .tail = fiber });
1033}
1034
1035fn await(941fn await(
1036 userdata: ?*anyopaque,942 userdata: ?*anyopaque,
1037 any_future: *std.Io.AnyFuture,943 any_future: *std.Io.AnyFuture,