@zigc/lib 0.17.0-dev.56 → 0.17.0-dev.87

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -215,8 +215,9 @@ fn checkIdentifierCodepointWarnings(p: *Parser, codepoint: u21, loc: Source.Loca
215
215
  assert(codepoint >= 0x80);
216
216
 
217
217
  const prev_total = p.diagnostics.total;
218
- var sf = std.heap.stackFallback(1024, p.comp.gpa);
219
- var allocating: std.Io.Writer.Allocating = .init(sf.get());
218
+ var bfa_buf: [1024]u8 = undefined;
219
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, p.comp.gpa);
220
+ var allocating: std.Io.Writer.Allocating = .init(bfa.allocator());
220
221
  defer allocating.deinit();
221
222
 
222
223
  if (!char_info.isC99IdChar(codepoint)) {
@@ -429,8 +430,9 @@ pub fn err(p: *Parser, tok_i: TokenIndex, diagnostic: Diagnostic, args: anytype)
429
430
  if (diagnostic.suppress_unless_version) |some| if (!p.comp.langopts.standard.atLeast(some)) return;
430
431
  if (p.diagnostics.effectiveKind(diagnostic) == .off) return;
431
432
 
432
- var sf = std.heap.stackFallback(1024, p.comp.gpa);
433
- var allocating: std.Io.Writer.Allocating = .init(sf.get());
433
+ var bfa_buf: [1024]u8 = undefined;
434
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, p.comp.gpa);
435
+ var allocating: std.Io.Writer.Allocating = .init(bfa.allocator());
434
436
  defer allocating.deinit();
435
437
 
436
438
  p.formatArgs(&allocating.writer, diagnostic.fmt, args) catch return error.OutOfMemory;
@@ -1537,8 +1539,9 @@ fn staticAssert(p: *Parser) Error!bool {
1537
1539
  }
1538
1540
  } else {
1539
1541
  if (!res.val.toBool(p.comp)) {
1540
- var sf = std.heap.stackFallback(1024, gpa);
1541
- var allocating: std.Io.Writer.Allocating = .init(sf.get());
1542
+ var bfa_buf: [1024]u8 = undefined;
1543
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, gpa);
1544
+ var allocating: std.Io.Writer.Allocating = .init(bfa.allocator());
1542
1545
  defer allocating.deinit();
1543
1546
 
1544
1547
  if (p.staticAssertMessage(res_node, str, &allocating) catch return error.OutOfMemory) |message| {
@@ -4837,8 +4840,9 @@ fn gnuAsmStmt(p: *Parser, quals: Tree.GNUAssemblyQualifiers, asm_tok: TokenIndex
4837
4840
  const expected_items = 8; // arbitrarily chosen, most assembly will have fewer than 8 inputs/outputs/constraints/names
4838
4841
  const bytes_needed = expected_items * @sizeOf(Tree.Node.AsmStmt.Operand) + expected_items * 2 * @sizeOf(Node.Index);
4839
4842
 
4840
- var stack_fallback = std.heap.stackFallback(bytes_needed, gpa);
4841
- const allocator = stack_fallback.get();
4843
+ var bfa_buf: [bytes_needed]u8 = undefined;
4844
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, gpa);
4845
+ const allocator = bfa.allocator();
4842
4846
 
4843
4847
  var operands: std.ArrayList(Tree.Node.AsmStmt.Operand) = .empty;
4844
4848
  defer operands.deinit(allocator);
@@ -9922,8 +9926,9 @@ fn primaryExpr(p: *Parser) Error!?Result {
9922
9926
  if (p.func.pretty_ident) |some| {
9923
9927
  qt = some.qt;
9924
9928
  } else if (p.func.qt) |func_qt| {
9925
- var sf = std.heap.stackFallback(1024, gpa);
9926
- var allocating: std.Io.Writer.Allocating = .init(sf.get());
9929
+ var bfa_buf: [1024]u8 = undefined;
9930
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, gpa);
9931
+ var allocating: std.Io.Writer.Allocating = .init(bfa.allocator());
9927
9932
  defer allocating.deinit();
9928
9933
 
9929
9934
  func_qt.printNamed(p.tokSlice(p.func.name), p.comp, &allocating.writer) catch return error.OutOfMemory;
@@ -10212,8 +10217,9 @@ fn charLiteral(p: *Parser) Error!?Result {
10212
10217
  };
10213
10218
 
10214
10219
  const max_chars_expected = 4;
10215
- var sf = std.heap.stackFallback(max_chars_expected * @sizeOf(u32), gpa);
10216
- const allocator = sf.get();
10220
+ var bfa_buf: [max_chars_expected]u32 = undefined;
10221
+ var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), gpa);
10222
+ const allocator = bfa.allocator();
10217
10223
  var chars: std.ArrayList(u32) = .empty;
10218
10224
  defer chars.deinit(allocator);
10219
10225
 
@@ -212,8 +212,9 @@ pub const Diagnostic = struct {
212
212
  };
213
213
 
214
214
  pub fn err(pp: *Preprocessor, tok_i: TokenIndex, diagnostic: Diagnostic, args: anytype) Compilation.Error!void {
215
- var sf = std.heap.stackFallback(1024, pp.comp.gpa);
216
- var allocating: std.Io.Writer.Allocating = .init(sf.get());
215
+ var buf: [1024]u8 = undefined;
216
+ var bfa: std.heap.BufferFirstAllocator = .init(&buf, pp.comp.gpa);
217
+ var allocating: std.Io.Writer.Allocating = .init(bfa.allocator());
217
218
  defer allocating.deinit();
218
219
 
219
220
  Diagnostics.formatArgs(&allocating.writer, diagnostic.fmt, args) catch return error.OutOfMemory;
@@ -1023,8 +1023,9 @@ fn err(pp: *Preprocessor, loc: anytype, diagnostic: Diagnostic, args: anytype) C
1023
1023
  defer pp.diagnostics.state.suppress_system_headers = old_suppress_system;
1024
1024
  if (diagnostic.show_in_system_headers) pp.diagnostics.state.suppress_system_headers = false;
1025
1025
 
1026
- var sf = std.heap.stackFallback(1024, pp.comp.gpa);
1027
- var allocating: std.Io.Writer.Allocating = .init(sf.get());
1026
+ var bfa_buf: [1024]u8 = undefined;
1027
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, pp.comp.gpa);
1028
+ var allocating: std.Io.Writer.Allocating = .init(bfa.allocator());
1028
1029
  defer allocating.deinit();
1029
1030
 
1030
1031
  Diagnostics.formatArgs(&allocating.writer, diagnostic.fmt, args) catch return error.OutOfMemory;
@@ -1052,8 +1053,9 @@ fn err(pp: *Preprocessor, loc: anytype, diagnostic: Diagnostic, args: anytype) C
1052
1053
  }
1053
1054
 
1054
1055
  fn fatal(pp: *Preprocessor, raw: RawToken, comptime fmt: []const u8, args: anytype) Compilation.Error {
1055
- var sf = std.heap.stackFallback(1024, pp.comp.gpa);
1056
- var allocating: std.Io.Writer.Allocating = .init(sf.get());
1056
+ var bfa_buf: [1024]u8 = undefined;
1057
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, pp.comp.gpa);
1058
+ var allocating: std.Io.Writer.Allocating = .init(bfa.allocator());
1057
1059
  defer allocating.deinit();
1058
1060
 
1059
1061
  Diagnostics.formatArgs(&allocating.writer, fmt, args) catch return error.OutOfMemory;
@@ -1074,8 +1076,9 @@ fn fatalNotFound(pp: *Preprocessor, tok: TokenWithExpansionLocs, filename: []con
1074
1076
  pp.diagnostics.state.fatal_errors = true;
1075
1077
  defer pp.diagnostics.state.fatal_errors = old;
1076
1078
 
1077
- var sf = std.heap.stackFallback(1024, pp.comp.gpa);
1078
- const allocator = sf.get();
1079
+ var bfa_buf: [1024]u8 = undefined;
1080
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, pp.comp.gpa);
1081
+ const allocator = bfa.allocator();
1079
1082
  var buf: std.ArrayList(u8) = .empty;
1080
1083
  defer buf.deinit(allocator);
1081
1084
 
@@ -44,8 +44,9 @@ fn preprocessorHandler(_: *Pragma, pp: *Preprocessor, start_idx: TokenIndex) Pra
44
44
 
45
45
  const diagnostic: Pragma.Diagnostic = .pragma_message;
46
46
 
47
- var sf = std.heap.stackFallback(1024, pp.comp.gpa);
48
- var allocating: std.Io.Writer.Allocating = .init(sf.get());
47
+ var bfa_buf: [1024]u8 = undefined;
48
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, pp.comp.gpa);
49
+ var allocating: std.Io.Writer.Allocating = .init(bfa.allocator());
49
50
  defer allocating.deinit();
50
51
 
51
52
  Diagnostics.formatArgs(&allocating.writer, diagnostic.fmt, .{str}) catch return error.OutOfMemory;
@@ -315,8 +315,9 @@ pub const Parser = struct {
315
315
  if (p.errored) return;
316
316
  if (p.comp.diagnostics.effectiveKind(diagnostic) == .off) return;
317
317
 
318
- var sf = std.heap.stackFallback(1024, p.comp.gpa);
319
- var allocating: std.Io.Writer.Allocating = .init(sf.get());
318
+ var bfa_buf: [1024]u8 = undefined;
319
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, p.comp.gpa);
320
+ var allocating: std.Io.Writer.Allocating = .init(bfa.allocator());
320
321
  defer allocating.deinit();
321
322
 
322
323
  formatArgs(&allocating.writer, diagnostic.fmt, args) catch return error.OutOfMemory;
@@ -68,8 +68,9 @@ fn serializeFloat(comptime T: type, value: T, w: *std.Io.Writer) !void {
68
68
  pub fn todo(c: *AsmCodeGen, msg: []const u8, tok: Tree.TokenIndex) Error {
69
69
  const loc: Source.Location = c.tree.tokens.items(.loc)[tok];
70
70
 
71
- var sf = std.heap.stackFallback(1024, c.comp.gpa);
72
- const allocator = sf.get();
71
+ var bfa_buf: [u8]1024 = undefined;
72
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, c.comp.gpa);
73
+ const allocator = bfa.allocator();
73
74
  var buf: std.ArrayList(u8) = .empty;
74
75
  defer buf.deinit(allocator);
75
76
 
@@ -57,9 +57,10 @@ fn fixLastLimb(out_ptr: [*]u64, is_signed: bool, bits: u16) void {
57
57
  if (limb_cnt == true_limb_cnt) return;
58
58
  const true_out = out_ptr[0..true_limb_cnt];
59
59
 
60
- const sign: u64 = if (!is_signed or @as(i64, @bitCast(true_out[limb_cnt - 1])) >= 0) 0 else ~@as(u64, 0);
60
+ const ms = limbGet(true_out, limb_cnt - 1);
61
+ const sign: u64 = if (!is_signed or @as(i64, @bitCast(ms)) >= 0) 0 else ~@as(u64, 0);
61
62
  for (limb_cnt..true_limb_cnt) |i| {
62
- true_out[i] = sign;
63
+ limbSet(true_out, i, sign);
63
64
  }
64
65
  }
65
66
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zigc/lib",
3
- "version": "0.17.0-dev.56",
3
+ "version": "0.17.0-dev.87",
4
4
  "description": "Zig standard library and libc headers (shared across all platforms)",
5
5
  "repository": {
6
6
  "type": "git",
@@ -15,14 +15,42 @@ cond: Io.Condition = .init,
15
15
  /// It is OK to initialize this field to any value.
16
16
  permits: usize = 0,
17
17
 
18
+ /// Blocks until a `permit` is available and consumes a single one.
19
+ /// Unblocks without consuming a `permit` when canceled.
20
+ ///
21
+ /// See also:
22
+ /// * `waitTimeout`
23
+ /// * `waitUncancelable`
18
24
  pub fn wait(s: *Semaphore, io: Io) Io.Cancelable!void {
25
+ s.waitTimeout(io, .none) catch |err| switch (err) {
26
+ error.Timeout => unreachable,
27
+ error.Canceled => |e| return e,
28
+ };
29
+ }
30
+
31
+ pub const WaitTimeoutError = Io.Cancelable || Io.Timeout.Error;
32
+
33
+ /// Blocks until a `permit` is available and consumes a single one.
34
+ /// Unblocks without consuming a `permit` when canceled or when the provided
35
+ /// timeout expires before a `permit` is available.
36
+ ///
37
+ /// See also:
38
+ /// * `wait`
39
+ /// * `waitUncancelable`
40
+ pub fn waitTimeout(s: *Semaphore, io: Io, timeout: Io.Timeout) WaitTimeoutError!void {
41
+ const deadline = timeout.toDeadline(io);
19
42
  try s.mutex.lock(io);
20
43
  defer s.mutex.unlock(io);
21
- while (s.permits == 0) try s.cond.wait(io, &s.mutex);
44
+ while (s.permits == 0) try s.cond.waitTimeout(io, &s.mutex, deadline);
22
45
  s.permits -= 1;
23
46
  if (s.permits > 0) s.cond.signal(io);
24
47
  }
25
48
 
49
+ /// Blocks until a `permit` is available and consumes a single one.
50
+ ///
51
+ /// See also:
52
+ /// * `wait`
53
+ /// * `waitTimeout`
26
54
  pub fn waitUncancelable(s: *Semaphore, io: Io) void {
27
55
  s.mutex.lockUncancelable(io);
28
56
  defer s.mutex.unlock(io);
@@ -31,6 +59,7 @@ pub fn waitUncancelable(s: *Semaphore, io: Io) void {
31
59
  if (s.permits > 0) s.cond.signal(io);
32
60
  }
33
61
 
62
+ /// Makes an additional `permit` available.
34
63
  pub fn post(s: *Semaphore, io: Io) void {
35
64
  s.mutex.lockUncancelable(io);
36
65
  defer s.mutex.unlock(io);
@@ -39,27 +68,93 @@ pub fn post(s: *Semaphore, io: Io) void {
39
68
  s.cond.signal(io);
40
69
  }
41
70
 
42
- test Semaphore {
43
- if (builtin.single_threaded) return error.SkipZigTest;
71
+ test wait {
44
72
  const io = testing.io;
45
73
 
46
- const TestContext = struct {
47
- sem: *Semaphore,
48
- n: *i32,
74
+ const Context = struct {
75
+ sem: Semaphore = .{ .permits = 1 },
76
+ n: u32 = 0,
77
+
49
78
  fn worker(ctx: *@This()) !void {
50
79
  try ctx.sem.wait(io);
51
- ctx.n.* += 1;
80
+ ctx.n += 1;
52
81
  ctx.sem.post(io);
53
82
  }
54
83
  };
55
- const num_threads = 3;
56
- var sem: Semaphore = .{ .permits = 1 };
57
- var threads: [num_threads]std.Thread = undefined;
58
- var n: i32 = 0;
59
- var ctx = TestContext{ .sem = &sem, .n = &n };
60
-
61
- for (&threads) |*t| t.* = try std.Thread.spawn(.{}, TestContext.worker, .{&ctx});
62
- for (threads) |t| t.join();
63
- try sem.wait(io);
64
- try testing.expect(n == num_threads);
84
+
85
+ var ctx: Context = .{};
86
+
87
+ var group: Io.Group = .init;
88
+ defer group.cancel(io);
89
+
90
+ const num_workers = 3;
91
+ for (0..num_workers) |_| group.async(io, Context.worker, .{&ctx});
92
+
93
+ try group.await(io);
94
+ try testing.expectEqual(num_workers, ctx.n);
95
+ }
96
+
97
+ test waitTimeout {
98
+ const io = testing.io;
99
+
100
+ const Context = struct {
101
+ ready: Io.Event = .unset,
102
+ sem: Semaphore = .{ .permits = 0 },
103
+ value: u32 = 0,
104
+
105
+ fn worker(ctx: *@This()) !void {
106
+ defer ctx.ready.set(io);
107
+
108
+ try testing.expectError(error.Timeout, ctx.sem.waitTimeout(io, .{ .duration = .{
109
+ .raw = .fromMilliseconds(1),
110
+ .clock = .awake,
111
+ } }));
112
+ try testing.expectEqual(0, ctx.value);
113
+
114
+ ctx.ready.set(io);
115
+
116
+ while (ctx.value == 0) try ctx.sem.wait(io);
117
+ try testing.expectEqual(1, ctx.value);
118
+ }
119
+ };
120
+
121
+ var ctx: Context = .{};
122
+
123
+ var future = io.concurrent(Context.worker, .{&ctx}) catch |err| switch (err) {
124
+ error.ConcurrencyUnavailable => return error.SkipZigTest,
125
+ };
126
+ defer future.cancel(io) catch {};
127
+
128
+ try ctx.ready.wait(io);
129
+
130
+ ctx.value = 1;
131
+ ctx.sem.post(io);
132
+
133
+ try future.await(io);
134
+ }
135
+
136
+ test waitUncancelable {
137
+ const io = testing.io;
138
+
139
+ const Context = struct {
140
+ sem: Semaphore = .{ .permits = 1 },
141
+ n: u32 = 0,
142
+
143
+ fn worker(ctx: *@This()) !void {
144
+ ctx.sem.waitUncancelable(io);
145
+ ctx.n += 1;
146
+ ctx.sem.post(io);
147
+ }
148
+ };
149
+
150
+ var ctx: Context = .{};
151
+
152
+ var group: Io.Group = .init;
153
+ defer group.cancel(io);
154
+
155
+ const num_workers = 3;
156
+ for (0..num_workers) |_| group.async(io, Context.worker, .{&ctx});
157
+
158
+ try group.await(io);
159
+ try testing.expectEqual(num_workers, ctx.n);
65
160
  }
@@ -2005,7 +2005,7 @@ const have_waitid = switch (native_os) {
2005
2005
 
2006
2006
  const have_wait4 = switch (native_os) {
2007
2007
  .linux => @hasField(std.os.linux.SYS, "wait4"),
2008
- .dragonfly, .freebsd, .netbsd, .openbsd, .illumos, .serenity, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => true,
2008
+ .dragonfly, .freebsd, .netbsd, .openbsd, .illumos, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => true,
2009
2009
  else => false,
2010
2010
  };
2011
2011
 
@@ -5484,7 +5484,7 @@ fn dirReadLinux(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir
5484
5484
  }
5485
5485
  const syscall: Syscall = try .start();
5486
5486
  const n = while (true) {
5487
- const rc = linux.getdents64(dr.dir.handle, dr.buffer.ptr, dr.buffer.len);
5487
+ const rc = linux.getdents64(dr.dir.handle, dr.buffer.ptr, @min(dr.buffer.len, std.math.maxInt(c_uint)));
5488
5488
  switch (linux.errno(rc)) {
5489
5489
  .SUCCESS => {
5490
5490
  syscall.finish();
package/std/Io/Uring.zig CHANGED
@@ -3070,7 +3070,7 @@ fn dirRead(userdata: ?*anyopaque, dr: *Dir.Reader, buffer: []Dir.Entry) Dir.Read
3070
3070
  }
3071
3071
  const n = while (true) {
3072
3072
  try sync.cancel_region.await(.nothing);
3073
- const rc = linux.getdents64(dr.dir.handle, dr.buffer.ptr, dr.buffer.len);
3073
+ const rc = linux.getdents64(dr.dir.handle, dr.buffer.ptr, @min(dr.buffer.len, std.math.maxInt(c_uint)));
3074
3074
  switch (linux.errno(rc)) {
3075
3075
  .SUCCESS => break rc,
3076
3076
  .INTR => {},
package/std/Io.zig CHANGED
@@ -1681,20 +1681,29 @@ pub const Condition = struct {
1681
1681
  .epoch = .init(0),
1682
1682
  };
1683
1683
 
1684
+ /// Blocks until the condition is signaled or canceled.
1685
+ ///
1686
+ /// See also:
1687
+ /// * `waitUncancelable`
1688
+ /// * `waitTimeout`
1684
1689
  pub fn wait(cond: *Condition, io: Io, mutex: *Mutex) Cancelable!void {
1685
- try waitInner(cond, io, mutex, false);
1690
+ waitTimeout(cond, io, mutex, .none) catch |err| switch (err) {
1691
+ error.Timeout => unreachable,
1692
+ error.Canceled => |e| return e,
1693
+ };
1686
1694
  }
1687
1695
 
1688
- /// Same as `wait`, except does not introduce a cancelation point.
1696
+ pub const WaitTimeoutError = Cancelable || Timeout.Error;
1697
+
1698
+ /// Blocks until the condition is signaled, canceled, or the provided
1699
+ /// timeout expires.
1689
1700
  ///
1690
- /// For a description of cancelation and cancelation points, see `Future.cancel`.
1691
- pub fn waitUncancelable(cond: *Condition, io: Io, mutex: *Mutex) void {
1692
- waitInner(cond, io, mutex, true) catch |err| switch (err) {
1693
- error.Canceled => unreachable,
1694
- };
1695
- }
1701
+ /// See also:
1702
+ /// * `wait`
1703
+ /// * `waitUncancelable`
1704
+ pub fn waitTimeout(cond: *Condition, io: Io, mutex: *Mutex, timeout: Timeout) WaitTimeoutError!void {
1705
+ const deadline = timeout.toDeadline(io);
1696
1706
 
1697
- fn waitInner(cond: *Condition, io: Io, mutex: *Mutex, uncancelable: bool) Cancelable!void {
1698
1707
  var epoch = cond.epoch.load(.acquire); // `.acquire` to ensure ordered before state load
1699
1708
 
1700
1709
  {
@@ -1706,10 +1715,7 @@ pub const Condition = struct {
1706
1715
  defer mutex.lockUncancelable(io);
1707
1716
 
1708
1717
  while (true) {
1709
- const result = if (uncancelable)
1710
- io.futexWaitUncancelable(u32, &cond.epoch.raw, epoch)
1711
- else
1712
- io.futexWait(u32, &cond.epoch.raw, epoch);
1718
+ const result = io.futexWaitTimeout(u32, &cond.epoch.raw, epoch, deadline);
1713
1719
 
1714
1720
  epoch = cond.epoch.load(.acquire); // `.acquire` to ensure ordered before `state` laod
1715
1721
 
@@ -1729,13 +1735,62 @@ pub const Condition = struct {
1729
1735
  }
1730
1736
 
1731
1737
  // There are no more signals available; this was a spurious wakeup or an error. If it
1732
- // was an error, we will remove ourselves as a waiter and return that error. Otherwise,
1733
- // we'll loop back to the futex wait.
1738
+ // was an error, we will remove ourselves as a waiter and return that error. If a
1739
+ // timeout was specified and the deadline has passed, we remove ourselves as a waiter
1740
+ // and return `error.Timeout`. Otherwise, we'll loop back to the futex wait.
1734
1741
  result catch |err| {
1735
1742
  const prev_state = cond.state.fetchSub(.{ .waiters = 1, .signals = 0 }, .monotonic);
1736
1743
  assert(prev_state.waiters > 0); // underflow caused by illegal state
1737
1744
  return err;
1738
1745
  };
1746
+ switch (deadline) {
1747
+ .none => {},
1748
+ .deadline => |d| if (d.untilNow(io).raw.nanoseconds >= 0) {
1749
+ const prev_state = cond.state.fetchSub(.{ .waiters = 1, .signals = 0 }, .monotonic);
1750
+ assert(prev_state.waiters > 0); // underflow caused by illegal state
1751
+ return error.Timeout;
1752
+ },
1753
+ .duration => unreachable,
1754
+ }
1755
+ }
1756
+ }
1757
+
1758
+ /// Same as `wait`, except does not introduce a cancelation point.
1759
+ ///
1760
+ /// See `Future.cancel` for a description of cancelation points.
1761
+ pub fn waitUncancelable(cond: *Condition, io: Io, mutex: *Mutex) void {
1762
+ var epoch = cond.epoch.load(.acquire); // `.acquire` to ensure ordered before state load
1763
+
1764
+ {
1765
+ const prev_state = cond.state.fetchAdd(.{ .waiters = 1, .signals = 0 }, .monotonic);
1766
+ assert(prev_state.waiters < math.maxInt(u16)); // overflow caused by too many waiters
1767
+ }
1768
+
1769
+ mutex.unlock(io);
1770
+ defer mutex.lockUncancelable(io);
1771
+
1772
+ while (true) {
1773
+ io.futexWaitUncancelable(u32, &cond.epoch.raw, epoch);
1774
+
1775
+ epoch = cond.epoch.load(.acquire); // `.acquire` to ensure ordered before `state` laod
1776
+
1777
+ // Even on error, try to consume a pending signal first. Otherwise a race might
1778
+ // cause a signal to get stuck in the state with no corresponding waiter.
1779
+ {
1780
+ var prev_state = cond.state.load(.monotonic);
1781
+ while (prev_state.signals > 0) {
1782
+ prev_state = cond.state.cmpxchgWeak(prev_state, .{
1783
+ .waiters = prev_state.waiters - 1,
1784
+ .signals = prev_state.signals - 1,
1785
+ }, .acquire, .monotonic) orelse {
1786
+ // We successfully consumed a signal.
1787
+ return;
1788
+ };
1789
+ }
1790
+ }
1791
+
1792
+ // There are no more signals available; this was a spurious wakeup,
1793
+ // so we'll loop back to the futex wait.
1739
1794
  }
1740
1795
  }
1741
1796
 
@@ -53,9 +53,7 @@ pub extern "c" fn profiling_enable(pid: pid_t, event_mask: PERF_EVENT) c_int;
53
53
  pub extern "c" fn profiling_disable(pid: pid_t) c_int;
54
54
  pub extern "c" fn profiling_free_buffer(pid: pid_t) c_int;
55
55
 
56
- pub extern "c" fn futex(userspace_address: *u32, futex_op: c_int, value: u32, timeout: *const timespec, userspace_address2: *u32, value3: u32) c_int;
57
- pub extern "c" fn futex_wait(userspace_address: *u32, value: u32, abstime: *const timespec, clockid: clockid_t, process_shared: c_int) c_int;
58
- pub extern "c" fn futex_wake(userspace_address: *u32, count: u32, process_shared: c_int) c_int;
56
+ pub extern "c" fn futex(userspace_address: *u32, futex_op: c_int, value: u32, timeout: ?*const timespec, userspace_address2: ?*u32, value3: u32) c_int;
59
57
 
60
58
  pub extern "c" fn purge(mode: c_int) c_int;
61
59
 
@@ -66,9 +64,6 @@ pub extern "c" fn get_stack_bounds(user_stack_base: *usize, user_stack_size: *us
66
64
 
67
65
  pub extern "c" fn anon_create(size: usize, options: O) c_int;
68
66
 
69
- pub extern "c" fn serenity_readlink(path: [*]const u8, path_length: usize, buffer: [*]u8, buffer_size: usize) c_int;
70
- pub extern "c" fn serenity_open(path: [*]const u8, path_length: usize, options: c_int, ...) c_int;
71
-
72
67
  pub extern "c" fn getkeymap(name_buffer: [*]u8, name_buffer_size: usize, map: [*]u32, shift_map: [*]u32, alt_map: [*]u32, altgr_map: [*]u32, shift_altgr_map: [*]u32) c_int;
73
68
  pub extern "c" fn setkeymap(name: [*]const u8, map: [*]const u32, shift_map: [*]const u32, alt_map: [*]const u32, altgr_map: [*]const u32, shift_altgr_map: [*]const u32) c_int;
74
69
 
package/std/c.zig CHANGED
@@ -11102,13 +11102,60 @@ pub const ioctl = switch (native_os) {
11102
11102
  else => private.ioctl,
11103
11103
  };
11104
11104
 
11105
+ pub extern "c" fn bzero(s: *anyopaque, n: usize) void;
11106
+
11107
+ pub extern "c" fn swab(noalias from: *const anyopaque, noalias to: *anyopaque, n: isize) void;
11108
+
11109
+ pub extern "c" fn strncmp(a: [*:0]const c_char, b: [*:0]const c_char, max: usize) c_int;
11110
+ pub extern "c" fn strcasecmp(a: [*:0]const c_char, b: [*:0]const c_char) c_int;
11111
+ pub extern "c" fn strncasecmp(a: [*:0]const c_char, b: [*:0]const c_char, max: usize) c_int;
11112
+
11113
+ pub extern "c" fn ffs(i: c_int) c_int;
11114
+ pub extern "c" fn ffsl(i: c_long) c_long;
11115
+ pub extern "c" fn ffsll(i: c_longlong) c_longlong;
11116
+
11117
+ pub extern "c" fn erand48(xsubi: *[3]c_ushort) f64;
11118
+ pub extern "c" fn jrand48(xsubi: *[3]c_ushort) c_long;
11119
+ pub extern "c" fn nrand48(xsubi: *[3]c_ushort) c_long;
11120
+
11121
+ pub extern "c" fn insque(element: *anyopaque, pred: ?*anyopaque) void;
11122
+ pub extern "c" fn remque(element: *anyopaque) void;
11123
+
11124
+ pub extern "c" fn imaxabs(a: intmax_t) intmax_t;
11125
+ pub extern "c" fn imaxdiv(a: intmax_t, b: intmax_t) imaxdiv_t;
11126
+
11127
+ pub extern "c" fn abs(a: c_int) c_int;
11128
+ pub extern "c" fn labs(a: c_long) c_long;
11129
+ pub extern "c" fn llabs(a: c_longlong) c_longlong;
11130
+
11131
+ pub extern "c" fn div(a: c_int, b: c_int) div_t;
11132
+ pub extern "c" fn ldiv(a: c_long, b: c_long) ldiv_t;
11133
+ pub extern "c" fn lldiv(a: c_longlong, b: c_longlong) lldiv_t;
11134
+
11135
+ pub extern "c" fn atoi(str: [*:0]const c_char) c_int;
11136
+ pub extern "c" fn atol(str: [*:0]const c_char) c_long;
11137
+ pub extern "c" fn atoll(str: [*:0]const c_char) c_longlong;
11138
+
11139
+ pub extern "c" fn bsearch(
11140
+ key: *const anyopaque,
11141
+ base: *const anyopaque,
11142
+ n: usize,
11143
+ size: usize,
11144
+ compare: *const fn (a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int,
11145
+ ) ?*anyopaque;
11146
+
11105
11147
  // Math
11106
- pub extern "c" fn atan(x: f64) callconv(.c) f64;
11107
- pub extern "c" fn copysign(x: f64, y: f64) callconv(.c) f64;
11108
- pub extern "c" fn fdim(x: f64, y: f64) callconv(.c) f64;
11109
- pub extern "c" fn frexp(x: f64, e: *c_int) callconv(.c) f64;
11110
- pub extern "c" fn hypot(x: f64, y: f64) callconv(.c) f64;
11111
- pub extern "c" fn modf(x: f64, iptr: *f64) callconv(.c) f64;
11148
+ pub extern "c" fn atan(x: f64) f64;
11149
+ pub extern "c" fn copysign(x: f64, y: f64) f64;
11150
+ pub extern "c" fn fdim(x: f64, y: f64) f64;
11151
+ pub extern "c" fn frexp(x: f64, e: *c_int) f64;
11152
+ pub extern "c" fn hypot(x: f64, y: f64) f64;
11153
+ pub extern "c" fn modff(x: f32, iptr: *f32) f32;
11154
+ pub extern "c" fn modf(x: f64, iptr: *f64) f64;
11155
+ pub extern "c" fn modfl(x: c_longdouble, iptr: *c_longdouble) c_longdouble;
11156
+ pub extern "c" fn rintf(x: f32) f32;
11157
+ pub extern "c" fn rint(x: f64) f64;
11158
+ pub extern "c" fn rintl(x: c_longdouble) c_longdouble;
11112
11159
 
11113
11160
  // OS-specific bits. These are protected from being used on the wrong OS by
11114
11161
  // comptime assertions inside each OS-specific file.
@@ -11459,15 +11506,11 @@ pub const disown = serenity.disown;
11459
11506
  pub const profiling_enable = serenity.profiling_enable;
11460
11507
  pub const profiling_disable = serenity.profiling_disable;
11461
11508
  pub const profiling_free_buffer = serenity.profiling_free_buffer;
11462
- pub const futex_wait = serenity.futex_wait;
11463
- pub const futex_wake = serenity.futex_wake;
11464
11509
  pub const purge = serenity.purge;
11465
11510
  pub const perf_event = serenity.perf_event;
11466
11511
  pub const perf_register_string = serenity.perf_register_string;
11467
11512
  pub const get_stack_bounds = serenity.get_stack_bounds;
11468
11513
  pub const anon_create = serenity.anon_create;
11469
- pub const serenity_readlink = serenity.serenity_readlink;
11470
- pub const serenity_open = serenity.serenity_open;
11471
11514
  pub const getkeymap = serenity.getkeymap;
11472
11515
  pub const setkeymap = serenity.setkeymap;
11473
11516
 
package/std/debug.zig CHANGED
@@ -1197,8 +1197,9 @@ fn printSourceAtAddress(
1197
1197
 
1198
1198
  // Initialize the symbol array with space for at least one element, allocating this on the stack
1199
1199
  // in the common case where only one element is needed
1200
- var symbol_fallback_allocator = std.heap.stackFallback(@sizeOf(Symbol) + @alignOf(Symbol) - 1, getDebugInfoAllocator());
1201
- const symbol_allocator = symbol_fallback_allocator.get();
1200
+ var buf: [1]Symbol = undefined;
1201
+ var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&buf), getDebugInfoAllocator());
1202
+ const symbol_allocator = bfa.allocator();
1202
1203
  var symbols = std.ArrayList(Symbol).initCapacity(symbol_allocator, 1) catch unreachable;
1203
1204
  defer symbols.deinit(symbol_allocator);
1204
1205
 
package/std/fs/path.zig CHANGED
@@ -894,8 +894,9 @@ pub fn resolve(allocator: Allocator, paths: []const []const u8) Allocator.Error!
894
894
  pub fn resolveWindows(allocator: Allocator, paths: []const []const u8) Allocator.Error![]u8 {
895
895
  // Avoid heap allocation when paths.len is <= @bitSizeOf(usize) * 2
896
896
  // (we use `* 3` because stackFallback uses 1 usize as a length)
897
- var bit_set_allocator_state = std.heap.stackFallback(@sizeOf(usize) * 3, allocator);
898
- const bit_set_allocator = bit_set_allocator_state.get();
897
+ var buf: [3]usize = undefined;
898
+ var bit_set_allocator_state: std.heap.BufferFirstAllocator = .init(@ptrCast(&buf), allocator);
899
+ const bit_set_allocator = bit_set_allocator_state.allocator();
899
900
  var relevant_paths = try std.bit_set.DynamicBitSetUnmanaged.initEmpty(bit_set_allocator, paths.len);
900
901
  defer relevant_paths.deinit(bit_set_allocator);
901
902
 
@@ -1642,7 +1643,8 @@ fn windowsResolveAgainstCwd(
1642
1643
  parsed: WindowsPath2(u8),
1643
1644
  ) ![]u8 {
1644
1645
  // Space for 256 WTF-16 code units; potentially 3 WTF-8 bytes per WTF-16 code unit
1645
- var temp_allocator_state = std.heap.stackFallback(256 * 3, gpa);
1646
+ var buf: [256 * 3]u8 = undefined;
1647
+ var temp_allocator_state: std.heap.BufferFirstAllocator = .init(&buf, gpa);
1646
1648
  return switch (parsed.kind) {
1647
1649
  .drive_absolute,
1648
1650
  .unc_absolute,
@@ -1668,7 +1670,7 @@ fn windowsResolveAgainstCwd(
1668
1670
  }
1669
1671
  },
1670
1672
  .drive_relative => blk: {
1671
- const temp_allocator = temp_allocator_state.get();
1673
+ const temp_allocator = temp_allocator_state.allocator();
1672
1674
  const drive_cwd = drive_cwd: {
1673
1675
  const parsed_cwd = parsePathWindows(u8, cwd);
1674
1676