| ... | @@ -44,6 +44,14 @@ const timestampFromPosix = Io.Threaded.timestampFromPosix; | ... | @@ -44,6 +44,14 @@ const timestampFromPosix = Io.Threaded.timestampFromPosix; |
| 44 | const unexpectedErrno = std.posix.unexpectedErrno; | 44 | const unexpectedErrno = std.posix.unexpectedErrno; |
| 45 | const winsize = std.posix.winsize; | 45 | const winsize = std.posix.winsize; |
| 46 | | 46 | |
| | 47 | const tracy = if (@hasDecl(@import("root"), "tracy")) @import("root").tracy else struct { |
| | 48 | const enable = false; |
| | 49 | inline fn fiberEnter(fiber: [*:0]const u8) void { |
| | 50 | _ = fiber; |
| | 51 | } |
| | 52 | inline fn fiberLeave() void {} |
| | 53 | }; |
| | 54 | |
| 47 | backing_allocator_needs_mutex: bool, | 55 | backing_allocator_needs_mutex: bool, |
| 48 | backing_allocator_mutex: Io.Mutex, | 56 | backing_allocator_mutex: Io.Mutex, |
| 49 | /// Does not need to be thread-safe if not used elsewhere. | 57 | /// Does not need to be thread-safe if not used elsewhere. |
| ... | @@ -90,6 +98,7 @@ const Thread = struct { | ... | @@ -90,6 +98,7 @@ const Thread = struct { |
| 90 | io_uring: IoUring, | 98 | io_uring: IoUring, |
| 91 | idle_search_index: u32, | 99 | idle_search_index: u32, |
| 92 | steal_ready_search_index: u32, | 100 | steal_ready_search_index: u32, |
| | 101 | name_arena: if (tracy.enable) std.heap.ArenaAllocator.State else struct {}, |
| 93 | csprng: Csprng, | 102 | csprng: Csprng, |
| 94 | | 103 | |
| 95 | threadlocal var self: ?*Thread = null; | 104 | threadlocal var self: ?*Thread = null; |
| ... | @@ -138,6 +147,9 @@ const Fiber = struct { | ... | @@ -138,6 +147,9 @@ const Fiber = struct { |
| 138 | }, | 147 | }, |
| 139 | cancel_status: CancelStatus, | 148 | cancel_status: CancelStatus, |
| 140 | cancel_protection: CancelProtection, | 149 | cancel_protection: CancelProtection, |
| | 150 | name: if (tracy.enable) [*:0]const u8 else void, |
| | 151 | |
| | 152 | var next_name: u64 = 0; |
| 141 | | 153 | |
| 142 | const CancelStatus = packed struct(u32) { | 154 | const CancelStatus = packed struct(u32) { |
| 143 | requested: bool, | 155 | requested: bool, |
| ... | @@ -772,6 +784,7 @@ pub fn init(ev: *Evented, backing_allocator: Allocator, options: InitOptions) !v | ... | @@ -772,6 +784,7 @@ pub fn init(ev: *Evented, backing_allocator: Allocator, options: InitOptions) !v |
| 772 | .status = .{ .queue_next = null }, | 784 | .status = .{ .queue_next = null }, |
| 773 | .cancel_status = .unrequested, | 785 | .cancel_status = .unrequested, |
| 774 | .cancel_protection = .unblocked, | 786 | .cancel_protection = .unblocked, |
| | 787 | .name = if (tracy.enable) "main task", |
| 775 | }; | 788 | }; |
| 776 | const main_thread = &ev.threads.allocated[0]; | 789 | const main_thread = &ev.threads.allocated[0]; |
| 777 | Thread.self = main_thread; | 790 | Thread.self = main_thread; |
| ... | @@ -802,11 +815,13 @@ pub fn init(ev: *Evented, backing_allocator: Allocator, options: InitOptions) !v | ... | @@ -802,11 +815,13 @@ pub fn init(ev: *Evented, backing_allocator: Allocator, options: InitOptions) !v |
| 802 | ), | 815 | ), |
| 803 | .idle_search_index = 1, | 816 | .idle_search_index = 1, |
| 804 | .steal_ready_search_index = 1, | 817 | .steal_ready_search_index = 1, |
| | 818 | .name_arena = .{}, |
| 805 | .csprng = .uninitialized, | 819 | .csprng = .uninitialized, |
| 806 | }; | 820 | }; |
| 807 | errdefer main_thread.io_uring.deinit(); | 821 | errdefer main_thread.io_uring.deinit(); |
| 808 | log.debug("created main idle {*}", .{&main_thread.idle_context}); | 822 | log.debug("created main idle {*}", .{&main_thread.idle_context}); |
| 809 | log.debug("created main {*}", .{main_fiber}); | 823 | log.debug("created main {*}", .{main_fiber}); |
| | 824 | if (tracy.enable) tracy.fiberEnter(main_fiber.name); |
| 810 | } | 825 | } |
| 811 | | 826 | |
| 812 | pub fn deinit(ev: *Evented) void { | 827 | pub fn deinit(ev: *Evented) void { |
| ... | @@ -958,6 +973,7 @@ fn schedule(ev: *Evented, thread: *Thread, ready_queue: Fiber.Queue) bool { | ... | @@ -958,6 +973,7 @@ fn schedule(ev: *Evented, thread: *Thread, ready_queue: Fiber.Queue) bool { |
| 958 | }, | 973 | }, |
| 959 | .idle_search_index = 0, | 974 | .idle_search_index = 0, |
| 960 | .steal_ready_search_index = 0, | 975 | .steal_ready_search_index = 0, |
| | 976 | .name_arena = .{}, |
| 961 | .csprng = .uninitialized, | 977 | .csprng = .uninitialized, |
| 962 | }; | 978 | }; |
| 963 | new_thread.thread = std.Thread.spawn(.{ | 979 | new_thread.thread = std.Thread.spawn(.{ |
| ... | @@ -1160,6 +1176,12 @@ const SwitchMessage = struct { | ... | @@ -1160,6 +1176,12 @@ const SwitchMessage = struct { |
| 1160 | fn handle(message: *const SwitchMessage, ev: *Evented) void { | 1176 | fn handle(message: *const SwitchMessage, ev: *Evented) void { |
| 1161 | const thread: *Thread = .current(); | 1177 | const thread: *Thread = .current(); |
| 1162 | thread.current_context = message.contexts.ready; | 1178 | thread.current_context = message.contexts.ready; |
| | 1179 | if (tracy.enable) { |
| | 1180 | if (message.contexts.ready != &thread.idle_context) { |
| | 1181 | const fiber: *Fiber = @alignCast(@fieldParentPtr("context", message.contexts.ready)); |
| | 1182 | tracy.fiberEnter(fiber.name); |
| | 1183 | } else tracy.fiberLeave(); |
| | 1184 | } |
| 1163 | switch (message.pending_task) { | 1185 | switch (message.pending_task) { |
| 1164 | .nothing => {}, | 1186 | .nothing => {}, |
| 1165 | .reschedule => if (message.contexts.prev != &thread.idle_context) { | 1187 | .reschedule => if (message.contexts.prev != &thread.idle_context) { |
| ... | @@ -1543,6 +1565,17 @@ fn concurrent( | ... | @@ -1543,6 +1565,17 @@ fn concurrent( |
| 1543 | .status = .{ .queue_next = null }, | 1565 | .status = .{ .queue_next = null }, |
| 1544 | .cancel_status = .unrequested, | 1566 | .cancel_status = .unrequested, |
| 1545 | .cancel_protection = .unblocked, | 1567 | .cancel_protection = .unblocked, |
| | 1568 | .name = if (tracy.enable) name: { |
| | 1569 | const thread: *Thread = .current(); |
| | 1570 | var name_arena = thread.name_arena.promote(std.heap.page_allocator); |
| | 1571 | defer thread.name_arena = name_arena.state; |
| | 1572 | break :name std.fmt.allocPrintSentinel( |
| | 1573 | name_arena.allocator(), |
| | 1574 | "task {d}", |
| | 1575 | .{@atomicRmw(u64, &Fiber.next_name, .Add, 1, .monotonic)}, |
| | 1576 | 0, |
| | 1577 | ) catch return error.ConcurrencyUnavailable; |
| | 1578 | }, |
| 1546 | }; | 1579 | }; |
| 1547 | closure.* = .{ | 1580 | closure.* = .{ |
| 1548 | .ev = ev, | 1581 | .ev = ev, |
| ... | @@ -1920,6 +1953,17 @@ fn groupConcurrent( | ... | @@ -1920,6 +1953,17 @@ fn groupConcurrent( |
| 1920 | .status = .{ .queue_next = null }, | 1953 | .status = .{ .queue_next = null }, |
| 1921 | .cancel_status = .unrequested, | 1954 | .cancel_status = .unrequested, |
| 1922 | .cancel_protection = .unblocked, | 1955 | .cancel_protection = .unblocked, |
| | 1956 | .name = if (tracy.enable) name: { |
| | 1957 | const thread: *Thread = .current(); |
| | 1958 | var name_arena = thread.name_arena.promote(std.heap.page_allocator); |
| | 1959 | defer thread.name_arena = name_arena.state; |
| | 1960 | break :name std.fmt.allocPrintSentinel( |
| | 1961 | name_arena.allocator(), |
| | 1962 | "group task {d}", |
| | 1963 | .{@atomicRmw(u64, &Fiber.next_name, .Add, 1, .monotonic)}, |
| | 1964 | 0, |
| | 1965 | ) catch return error.ConcurrencyUnavailable; |
| | 1966 | }, |
| 1923 | }; | 1967 | }; |
| 1924 | closure.* = .{ | 1968 | closure.* = .{ |
| 1925 | .ev = ev, | 1969 | .ev = ev, |