authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-05 18:16:46-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-07 00:32:19-04:00
log57f36c420124b3b65d3036f10c4e8c675be29cf4
tree7dcea63ea4a766793a64d890b8a38990179bbc83
parenteb326e15530dd6dca4ccbe7dbfde7bf048de813e

std.event.Loop: use EPOLLONESHOT to save 1 syscall

when a thread pool worker accepts a coroutine to resume

1 files changed, 16 insertions(+), 8 deletions(-)

std/event.zig+16-8
......@@ -132,6 +132,7 @@ pub const Loop = struct {
132132
133133 pub const EventFd = struct {
134134 base: ResumeNode,
135 epoll_op: u32,
135136 eventfd: i32,
136137 };
137138 };
......@@ -204,6 +205,7 @@ pub const Loop = struct {
204205 .handle = undefined,
205206 },
206207 .eventfd = try std.os.linuxEventFd(1, posix.EFD_CLOEXEC | posix.EFD_NONBLOCK),
208 .epoll_op = posix.EPOLL_CTL_ADD,
207209 },
208210 .next = undefined,
209211 };
......@@ -265,15 +267,20 @@ pub const Loop = struct {
265267 errdefer {
266268 _ = @atomicRmw(usize, &self.pending_event_count, AtomicRmwOp.Sub, 1, AtomicOrder.SeqCst);
267269 }
268 try self.addFdNoCounter(fd, resume_node);
270 try self.modFd(
271 fd,
272 posix.EPOLL_CTL_ADD,
273 std.os.linux.EPOLLIN | std.os.linux.EPOLLOUT | std.os.linux.EPOLLET,
274 resume_node,
275 );
269276 }
270277
271 fn addFdNoCounter(self: *Loop, fd: i32, resume_node: *ResumeNode) !void {
278 pub fn modFd(self: *Loop, fd: i32, op: u32, events: u32, resume_node: *ResumeNode) !void {
272279 var ev = std.os.linux.epoll_event{
273 .events = std.os.linux.EPOLLIN | std.os.linux.EPOLLOUT | std.os.linux.EPOLLET,
280 .events = events,
274281 .data = std.os.linux.epoll_data{ .ptr = @ptrToInt(resume_node) },
275282 };
276 try std.os.linuxEpollCtl(self.os_data.epollfd, std.os.linux.EPOLL_CTL_ADD, fd, &ev);
283 try std.os.linuxEpollCtl(self.os_data.epollfd, op, fd, &ev);
277284 }
278285
279286 pub fn removeFd(self: *Loop, fd: i32) void {
......@@ -331,7 +338,8 @@ pub const Loop = struct {
331338 const eventfd_node = &resume_stack_node.data;
332339 eventfd_node.base.handle = handle;
333340 // the pending count is already accounted for
334 self.addFdNoCounter(eventfd_node.eventfd, &eventfd_node.base) catch |_| {
341 const epoll_events = posix.EPOLLONESHOT | std.os.linux.EPOLLIN | std.os.linux.EPOLLOUT | std.os.linux.EPOLLET;
342 self.modFd(eventfd_node.eventfd, eventfd_node.epoll_op, epoll_events, &eventfd_node.base) catch |_| {
335343 // fine, we didn't need it anyway
336344 _ = @atomicRmw(u8, &self.dispatch_lock, AtomicRmwOp.Xchg, 0, AtomicOrder.SeqCst);
337345 self.os_data.available_eventfd_resume_nodes.push(resume_stack_node);
......@@ -371,7 +379,7 @@ pub const Loop = struct {
371379 ResumeNode.Id.Stop => return,
372380 ResumeNode.Id.EventFd => {
373381 const event_fd_node = @fieldParentPtr(ResumeNode.EventFd, "base", resume_node);
374 self.removeFdNoCounter(event_fd_node.eventfd);
382 event_fd_node.epoll_op = posix.EPOLL_CTL_MOD;
375383 const stack_node = @fieldParentPtr(std.atomic.Stack(ResumeNode.EventFd).Node, "data", event_fd_node);
376384 self.os_data.available_eventfd_resume_nodes.push(stack_node);
377385 },
......@@ -902,7 +910,7 @@ test "std.event.Lock" {
902910 defer cancel handle;
903911 loop.run();
904912
905 assert(mem.eql(i32, shared_test_data, [1]i32{3 * 10} ** 10));
913 assert(mem.eql(i32, shared_test_data, [1]i32{3 * @intCast(i32, shared_test_data.len)} ** shared_test_data.len));
906914}
907915
908916async fn testLock(loop: *Loop, lock: *Lock) void {
......@@ -945,7 +953,7 @@ async fn lockRunner(lock: *Lock) void {
945953 suspend; // resumed by onNextTick
946954
947955 var i: usize = 0;
948 while (i < 10) : (i += 1) {
956 while (i < shared_test_data.len) : (i += 1) {
949957 const handle = await (async lock.acquire() catch @panic("out of memory"));
950958 defer handle.release();
951959