diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 999d7b93f503729e0f83f4c890ce6d809da5b21d..53d03354518e8bef833c8b248de7a1f23a402cc7 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -695,38 +695,38 @@ fn groupAsync( t.mutex.lock(); + if (t.available_thread_count == 0) { + if (t.cpu_count != 0 and t.threads.items.len >= t.cpu_count) { + t.mutex.unlock(); + gc.deinit(gpa); + return start(group, context.ptr); + } + + t.threads.ensureUnusedCapacity(gpa, 1) catch { + t.mutex.unlock(); + gc.deinit(gpa); + return start(group, context.ptr); + }; + + const thread = std.Thread.spawn( + .{ .stack_size = t.stack_size }, + worker, + .{t}, + ) catch { + t.mutex.unlock(); + gc.deinit(gpa); + return start(group, context.ptr); + }; + + t.threads.appendAssumeCapacity(thread); + } else { + t.available_thread_count -= 1; + } + // Append to the group linked list inside the mutex to make `Io.Group.async` thread-safe. gc.node = .{ .next = @ptrCast(@alignCast(group.token)) }; group.token = &gc.node; - if (t.available_thread_count == 0) { - if (t.cpu_count != 0 and t.threads.items.len >= t.cpu_count) { - t.mutex.unlock(); - gc.deinit(gpa); - return start(group, context.ptr); - } - - t.threads.ensureUnusedCapacity(gpa, 1) catch { - t.mutex.unlock(); - gc.deinit(gpa); - return start(group, context.ptr); - }; - - const thread = std.Thread.spawn( - .{ .stack_size = t.stack_size }, - worker, - .{t}, - ) catch { - t.mutex.unlock(); - gc.deinit(gpa); - return start(group, context.ptr); - }; - - t.threads.appendAssumeCapacity(thread); - } else { - t.available_thread_count -= 1; - } - t.run_queue.prepend(&gc.closure.node); // This needs to be done before unlocking the mutex to avoid a race with