Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions lib/std/buffer.zig
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,11 @@ pub const Buffer = struct {
self.list.deinit();
}

pub fn toSlice(self: *const Buffer) []u8 {
pub fn toSlice(self: Buffer) []u8 {
return self.list.toSlice()[0..self.len()];
}

pub fn toSliceConst(self: *const Buffer) []const u8 {
pub fn toSliceConst(self: Buffer) []const u8 {
return self.list.toSliceConst()[0..self.len()];
}

Expand All @@ -91,11 +91,11 @@ pub const Buffer = struct {
self.list.items[self.len()] = 0;
}

pub fn isNull(self: *const Buffer) bool {
pub fn isNull(self: Buffer) bool {
return self.list.len == 0;
}

pub fn len(self: *const Buffer) usize {
pub fn len(self: Buffer) usize {
return self.list.len - 1;
}

Expand All @@ -111,16 +111,16 @@ pub const Buffer = struct {
self.list.toSlice()[old_len] = byte;
}

pub fn eql(self: *const Buffer, m: []const u8) bool {
pub fn eql(self: Buffer, m: []const u8) bool {
return mem.eql(u8, self.toSliceConst(), m);
}

pub fn startsWith(self: *const Buffer, m: []const u8) bool {
pub fn startsWith(self: Buffer, m: []const u8) bool {
if (self.len() < m.len) return false;
return mem.eql(u8, self.list.items[0..m.len], m);
}

pub fn endsWith(self: *const Buffer, m: []const u8) bool {
pub fn endsWith(self: Buffer, m: []const u8) bool {
const l = self.len();
if (l < m.len) return false;
const start = l - m.len;
Expand All @@ -133,7 +133,7 @@ pub const Buffer = struct {
}

/// For passing to C functions.
pub fn ptr(self: *const Buffer) [*]u8 {
pub fn ptr(self: Buffer) [*]u8 {
return self.list.items.ptr;
}
};
Expand Down
51 changes: 51 additions & 0 deletions lib/std/c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,26 @@ pub extern "c" fn getsockname(sockfd: fd_t, noalias addr: *sockaddr, noalias add
pub extern "c" fn connect(sockfd: fd_t, sock_addr: *const sockaddr, addrlen: socklen_t) c_int;
pub extern "c" fn accept4(sockfd: fd_t, addr: *sockaddr, addrlen: *socklen_t, flags: c_uint) c_int;
pub extern "c" fn getsockopt(sockfd: fd_t, level: c_int, optname: c_int, optval: *c_void, optlen: *socklen_t) c_int;
pub extern "c" fn send(sockfd: fd_t, buf: *const c_void, len: usize, flags: u32) isize;
pub extern "c" fn sendto(
sockfd: fd_t,
buf: *const c_void,
len: usize,
flags: u32,
dest_addr: *const sockaddr,
addrlen: socklen_t,
) isize;

pub extern fn recv(sockfd: fd_t, arg1: ?*c_void, arg2: usize, arg3: c_int) isize;
pub extern fn recvfrom(
sockfd: fd_t,
noalias buf: *c_void,
len: usize,
flags: u32,
noalias src_addr: ?*sockaddr,
noalias addrlen: ?*socklen_t,
) isize;

pub extern "c" fn kill(pid: pid_t, sig: c_int) c_int;
pub extern "c" fn getdirentries(fd: fd_t, buf_ptr: [*]u8, nbytes: usize, basep: *i64) isize;
pub extern "c" fn setgid(ruid: c_uint, euid: c_uint) c_int;
Expand Down Expand Up @@ -148,3 +168,34 @@ pub extern "c" fn kevent(
nevents: c_int,
timeout: ?*const timespec,
) c_int;

pub extern "c" fn getaddrinfo(
noalias node: [*]const u8,
noalias service: [*]const u8,
noalias hints: *const addrinfo,
noalias res: **addrinfo,
) c_int;

pub extern "c" fn freeaddrinfo(res: *addrinfo) void;

pub extern "c" fn getnameinfo(
noalias addr: *const sockaddr,
addrlen: socklen_t,
noalias host: [*]u8,
hostlen: socklen_t,
noalias serv: [*]u8,
servlen: socklen_t,
flags: u32,
) c_int;

pub extern "c" fn gai_strerror(errcode: c_int) [*]const u8;

pub extern "c" fn poll(fds: [*]pollfd, nfds: nfds_t, timeout: c_int) c_int;

pub extern "c" fn dn_expand(
msg: [*]const u8,
eomorig: [*]const u8,
comp_dn: [*]const u8,
exp_dn: [*]u8,
length: c_int,
) c_int;
55 changes: 55 additions & 0 deletions lib/std/c/darwin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,58 @@ pub fn sigaddset(set: *sigset_t, signo: u5) void {
}

pub extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;

/// get address to use bind()
pub const AI_PASSIVE = 0x00000001;

/// fill ai_canonname
pub const AI_CANONNAME = 0x00000002;

/// prevent host name resolution
pub const AI_NUMERICHOST = 0x00000004;

/// prevent service name resolution
pub const AI_NUMERICSERV = 0x00001000;

/// address family for hostname not supported
pub const EAI_ADDRFAMILY = 1;

/// temporary failure in name resolution
pub const EAI_AGAIN = 2;

/// invalid value for ai_flags
pub const EAI_BADFLAGS = 3;

/// non-recoverable failure in name resolution
pub const EAI_FAIL = 4;

/// ai_family not supported
pub const EAI_FAMILY = 5;

/// memory allocation failure
pub const EAI_MEMORY = 6;

/// no address associated with hostname
pub const EAI_NODATA = 7;

/// hostname nor servname provided, or not known
pub const EAI_NONAME = 8;

/// servname not supported for ai_socktype
pub const EAI_SERVICE = 9;

/// ai_socktype not supported
pub const EAI_SOCKTYPE = 10;

/// system error returned in errno
pub const EAI_SYSTEM = 11;

/// invalid value for hints
pub const EAI_BADHINTS = 12;

/// resolved protocol is unknown
pub const EAI_PROTOCOL = 13;

/// argument buffer overflow
pub const EAI_OVERFLOW = 14;
pub const EAI_MAX = 15;
35 changes: 35 additions & 0 deletions lib/std/c/linux.zig
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,41 @@ pub const _errno = switch (builtin.abi) {

pub const MAP_FAILED = @intToPtr(*c_void, maxInt(usize));

pub const AI_PASSIVE = 0x01;
pub const AI_CANONNAME = 0x02;
pub const AI_NUMERICHOST = 0x04;
pub const AI_V4MAPPED = 0x08;
pub const AI_ALL = 0x10;
pub const AI_ADDRCONFIG = 0x20;
pub const AI_NUMERICSERV = 0x400;

pub const NI_NUMERICHOST = 0x01;
pub const NI_NUMERICSERV = 0x02;
pub const NI_NOFQDN = 0x04;
pub const NI_NAMEREQD = 0x08;
pub const NI_DGRAM = 0x10;
pub const NI_NUMERICSCOPE = 0x100;

pub const EAI_BADFLAGS = -1;
pub const EAI_NONAME = -2;
pub const EAI_AGAIN = -3;
pub const EAI_FAIL = -4;
pub const EAI_FAMILY = -6;
pub const EAI_SOCKTYPE = -7;
pub const EAI_SERVICE = -8;
pub const EAI_MEMORY = -10;
pub const EAI_SYSTEM = -11;
pub const EAI_OVERFLOW = -12;

pub const EAI_NODATA = -5;
pub const EAI_ADDRFAMILY = -9;
pub const EAI_INPROGRESS = -100;
pub const EAI_CANCELED = -101;
pub const EAI_NOTCANCELED = -102;
pub const EAI_ALLDONE = -103;
pub const EAI_INTR = -104;
pub const EAI_IDN_ENCODE = -105;

pub extern "c" fn getrandom(buf_ptr: [*]u8, buf_len: usize, flags: c_uint) isize;
pub extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int;
pub extern "c" fn eventfd(initval: c_uint, flags: c_uint) c_int;
Expand Down
2 changes: 0 additions & 2 deletions lib/std/event.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ pub const RwLock = @import("event/rwlock.zig").RwLock;
pub const RwLocked = @import("event/rwlocked.zig").RwLocked;
pub const Loop = @import("event/loop.zig").Loop;
pub const fs = @import("event/fs.zig");
pub const net = @import("event/net.zig");

test "import event tests" {
_ = @import("event/channel.zig");
Expand All @@ -19,5 +18,4 @@ test "import event tests" {
_ = @import("event/rwlock.zig");
_ = @import("event/rwlocked.zig");
_ = @import("event/loop.zig");
_ = @import("event/net.zig");
}
10 changes: 6 additions & 4 deletions lib/std/event/channel.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ const assert = std.debug.assert;
const testing = std.testing;
const Loop = std.event.Loop;

/// many producer, many consumer, thread-safe, runtime configurable buffer size
/// when buffer is empty, consumers suspend and are resumed by producers
/// when buffer is full, producers suspend and are resumed by consumers
/// Many producer, many consumer, thread-safe, runtime configurable buffer size.
/// When buffer is empty, consumers suspend and are resumed by producers.
/// When buffer is full, producers suspend and are resumed by consumers.
/// TODO now that async function rewrite has landed, this API should be adjusted
/// to not use the event loop's allocator, and to not require allocation.
pub fn Channel(comptime T: type) type {
return struct {
loop: *Loop,
Expand Down Expand Up @@ -48,7 +50,7 @@ pub fn Channel(comptime T: type) type {
tick_node: *Loop.NextTickNode,
};

/// call destroy when done
/// Call `destroy` when done.
pub fn create(loop: *Loop, capacity: usize) !*SelfChannel {
const buffer_nodes = try loop.allocator.alloc(T, capacity);
errdefer loop.allocator.free(buffer_nodes);
Expand Down
87 changes: 67 additions & 20 deletions lib/std/event/loop.zig
Original file line number Diff line number Diff line change
Expand Up @@ -448,22 +448,67 @@ pub const Loop = struct {
self.finishOneEvent();
}

pub fn linuxWaitFd(self: *Loop, fd: i32, flags: u32) !void {
defer self.linuxRemoveFd(fd);
pub fn linuxWaitFd(self: *Loop, fd: i32, flags: u32) void {
assert(flags & os.EPOLLET == os.EPOLLET);
assert(flags & os.EPOLLONESHOT == os.EPOLLONESHOT);
var resume_node = ResumeNode.Basic{
.base = ResumeNode{
.id = .Basic,
.handle = @frame(),
.overlapped = ResumeNode.overlapped_init,
},
};
var need_to_delete = false;
defer if (need_to_delete) self.linuxRemoveFd(fd);

suspend {
var resume_node = ResumeNode.Basic{
.base = ResumeNode{
.id = .Basic,
.handle = @frame(),
.overlapped = ResumeNode.overlapped_init,
if (self.linuxAddFd(fd, &resume_node.base, flags)) |_| {
need_to_delete = true;
} else |err| switch (err) {
error.FileDescriptorNotRegistered => unreachable,
error.OperationCausesCircularLoop => unreachable,
error.FileDescriptorIncompatibleWithEpoll => unreachable,
error.FileDescriptorAlreadyPresentInSet => unreachable, // evented writes to the same fd is not thread-safe

error.SystemResources,
error.UserResourceLimitReached,
error.Unexpected,
=> {
// Fall back to a blocking poll(). Ideally this codepath is never hit, since
// epoll should be just fine. But this is better than incorrect behavior.
var poll_flags: i16 = 0;
if ((flags & os.EPOLLIN) != 0) poll_flags |= os.POLLIN;
if ((flags & os.EPOLLOUT) != 0) poll_flags |= os.POLLOUT;
var pfd = [1]os.pollfd{os.pollfd{
.fd = fd,
.events = poll_flags,
.revents = undefined,
}};
_ = os.poll(&pfd, -1) catch |poll_err| switch (poll_err) {
error.SystemResources,
error.Unexpected,
=> {
// Even poll() didn't work. The best we can do now is sleep for a
// small duration and then hope that something changed.
std.time.sleep(1 * std.time.millisecond);
},
};
resume @frame();
},
};
try self.linuxAddFd(fd, &resume_node.base, flags);
}
}
}

pub fn waitUntilFdReadable(self: *Loop, fd: os.fd_t) !void {
return self.linuxWaitFd(fd, os.EPOLLET | os.EPOLLIN);
pub fn waitUntilFdReadable(self: *Loop, fd: os.fd_t) void {
return self.linuxWaitFd(fd, os.EPOLLET | os.EPOLLONESHOT | os.EPOLLIN);
}

pub fn waitUntilFdWritable(self: *Loop, fd: os.fd_t) void {
return self.linuxWaitFd(fd, os.EPOLLET | os.EPOLLONESHOT | os.EPOLLOUT);
}

pub fn waitUntilFdWritableOrReadable(self: *Loop, fd: os.fd_t) void {
return self.linuxWaitFd(fd, os.EPOLLET | os.EPOLLONESHOT | os.EPOLLOUT | os.EPOLLIN);
}

pub async fn bsdWaitKev(self: *Loop, ident: usize, filter: i16, fflags: u32) !os.Kevent {
Expand Down Expand Up @@ -641,7 +686,7 @@ pub const Loop = struct {
.linux => {
self.posixFsRequest(&self.os_data.fs_end_request);
// writing 8 bytes to an eventfd cannot fail
os.write(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;
noasync os.write(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;
return;
},
.macosx, .freebsd, .netbsd => {
Expand Down Expand Up @@ -789,6 +834,8 @@ pub const Loop = struct {
}
}

// TODO make this whole function noasync
// https://github.com/ziglang/zig/issues/3157
fn posixFsRun(self: *Loop) void {
while (true) {
if (builtin.os == .linux) {
Expand All @@ -798,27 +845,27 @@ pub const Loop = struct {
switch (node.data.msg) {
.End => return,
.WriteV => |*msg| {
msg.result = os.writev(msg.fd, msg.iov);
msg.result = noasync os.writev(msg.fd, msg.iov);
},
.PWriteV => |*msg| {
msg.result = os.pwritev(msg.fd, msg.iov, msg.offset);
msg.result = noasync os.pwritev(msg.fd, msg.iov, msg.offset);
},
.PReadV => |*msg| {
msg.result = os.preadv(msg.fd, msg.iov, msg.offset);
msg.result = noasync os.preadv(msg.fd, msg.iov, msg.offset);
},
.Open => |*msg| {
msg.result = os.openC(msg.path.ptr, msg.flags, msg.mode);
msg.result = noasync os.openC(msg.path.ptr, msg.flags, msg.mode);
},
.Close => |*msg| os.close(msg.fd),
.Close => |*msg| noasync os.close(msg.fd),
.WriteFile => |*msg| blk: {
const flags = os.O_LARGEFILE | os.O_WRONLY | os.O_CREAT |
os.O_CLOEXEC | os.O_TRUNC;
const fd = os.openC(msg.path.ptr, flags, msg.mode) catch |err| {
const fd = noasync os.openC(msg.path.ptr, flags, msg.mode) catch |err| {
msg.result = err;
break :blk;
};
defer os.close(fd);
msg.result = os.write(fd, msg.contents);
defer noasync os.close(fd);
msg.result = noasync os.write(fd, msg.contents);
},
}
switch (node.data.finish) {
Expand Down
Loading