@zigc/lib 0.17.0-dev.56 → 0.17.0-dev.76
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.
- package/c/inttypes.zig +0 -10
- package/c/math.zig +0 -100
- package/c/search.zig +1 -27
- package/c/stdlib/drand48.zig +0 -57
- package/c/stdlib.zig +0 -100
- package/c/string.zig +0 -7
- package/c/strings.zig +0 -38
- package/c/unistd.zig +27 -26
- package/c.zig +1 -2
- package/compiler_rt/limb64.zig +32 -0
- package/package.json +1 -1
- package/std/Io/Semaphore.zig +112 -17
- package/std/Io/Threaded.zig +1 -1
- package/std/Io.zig +70 -15
- package/std/c/serenity.zig +1 -6
- package/std/c.zig +53 -10
- package/std/os.zig +41 -0
- package/libc/musl/src/unistd/dup2.c +0 -20
- package/libc/musl/src/unistd/dup3.c +0 -26
package/c/inttypes.zig
CHANGED
|
@@ -24,13 +24,3 @@ fn imaxdiv(a: intmax_t, b: intmax_t) callconv(.c) imaxdiv_t {
|
|
|
24
24
|
.rem = @rem(a, b),
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
-
|
|
28
|
-
test imaxabs {
|
|
29
|
-
const val: intmax_t = -10;
|
|
30
|
-
try std.testing.expectEqual(10, imaxabs(val));
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
test imaxdiv {
|
|
34
|
-
const expected: imaxdiv_t = .{ .quot = 9, .rem = 0 };
|
|
35
|
-
try std.testing.expectEqual(expected, imaxdiv(9, 1));
|
|
36
|
-
}
|
package/c/math.zig
CHANGED
|
@@ -2,10 +2,6 @@ const builtin = @import("builtin");
|
|
|
2
2
|
|
|
3
3
|
const std = @import("std");
|
|
4
4
|
const math = std.math;
|
|
5
|
-
const expect = std.testing.expect;
|
|
6
|
-
const expectEqual = std.testing.expectEqual;
|
|
7
|
-
const expectApproxEqAbs = std.testing.expectApproxEqAbs;
|
|
8
|
-
const expectApproxEqRel = std.testing.expectApproxEqRel;
|
|
9
5
|
|
|
10
6
|
const symbol = @import("../c.zig").symbol;
|
|
11
7
|
|
|
@@ -304,59 +300,6 @@ fn modfl(x: c_longdouble, iptr: *c_longdouble) callconv(.c) c_longdouble {
|
|
|
304
300
|
};
|
|
305
301
|
}
|
|
306
302
|
|
|
307
|
-
fn testModf(comptime T: type) !void {
|
|
308
|
-
// Choose the appropriate `modf` impl to test based on type
|
|
309
|
-
const f = switch (T) {
|
|
310
|
-
f32 => modff,
|
|
311
|
-
f64 => modf,
|
|
312
|
-
c_longdouble => modfl,
|
|
313
|
-
else => @compileError("modf not implemented for " ++ @typeName(T)),
|
|
314
|
-
};
|
|
315
|
-
|
|
316
|
-
var int: T = undefined;
|
|
317
|
-
const iptr = ∫
|
|
318
|
-
const eps_val: comptime_float = @max(1e-6, math.floatEps(T));
|
|
319
|
-
|
|
320
|
-
const normal_frac = f(@as(T, 1234.567), iptr);
|
|
321
|
-
// Account for precision error
|
|
322
|
-
const expected = 1234.567 - @as(T, 1234);
|
|
323
|
-
try expectApproxEqAbs(expected, normal_frac, eps_val);
|
|
324
|
-
try expectApproxEqRel(@as(T, 1234.0), iptr.*, eps_val);
|
|
325
|
-
|
|
326
|
-
// When `x` is a NaN, NaN is returned and `*iptr` is set to NaN
|
|
327
|
-
const nan_frac = f(math.nan(T), iptr);
|
|
328
|
-
try expect(math.isNan(nan_frac));
|
|
329
|
-
try expect(math.isNan(iptr.*));
|
|
330
|
-
|
|
331
|
-
// When `x` is positive infinity, +0 is returned and `*iptr` is set to
|
|
332
|
-
// positive infinity
|
|
333
|
-
const pos_zero_frac = f(math.inf(T), iptr);
|
|
334
|
-
try expect(math.isPositiveZero(pos_zero_frac));
|
|
335
|
-
try expect(math.isPositiveInf(iptr.*));
|
|
336
|
-
|
|
337
|
-
// When `x` is negative infinity, -0 is returned and `*iptr` is set to
|
|
338
|
-
// negative infinity
|
|
339
|
-
const neg_zero_frac = f(-math.inf(T), iptr);
|
|
340
|
-
try expect(math.isNegativeZero(neg_zero_frac));
|
|
341
|
-
try expect(math.isNegativeInf(iptr.*));
|
|
342
|
-
|
|
343
|
-
// Return -0 when `x` is a negative integer
|
|
344
|
-
const nz_frac = f(@as(T, -1000.0), iptr);
|
|
345
|
-
try expect(math.isNegativeZero(nz_frac));
|
|
346
|
-
try expectEqual(@as(T, -1000.0), iptr.*);
|
|
347
|
-
|
|
348
|
-
// Return +0 when `x` is a positive integer
|
|
349
|
-
const pz_frac = f(@as(T, 1000.0), iptr);
|
|
350
|
-
try expect(math.isPositiveZero(pz_frac));
|
|
351
|
-
try expectEqual(@as(T, 1000.0), iptr.*);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
test "modf" {
|
|
355
|
-
try testModf(f32);
|
|
356
|
-
try testModf(f64);
|
|
357
|
-
try testModf(c_longdouble);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
303
|
fn nan(_: [*:0]const c_char) callconv(.c) f64 {
|
|
361
304
|
return math.nan(f64);
|
|
362
305
|
}
|
|
@@ -421,49 +364,6 @@ fn rintf(x: f32) callconv(.c) f32 {
|
|
|
421
364
|
return y;
|
|
422
365
|
}
|
|
423
366
|
|
|
424
|
-
fn testRint(comptime T: type) !void {
|
|
425
|
-
const f = switch (T) {
|
|
426
|
-
f32 => rintf,
|
|
427
|
-
f64 => rint,
|
|
428
|
-
else => @compileError("rint not implemented for" ++ @typeName(T)),
|
|
429
|
-
};
|
|
430
|
-
|
|
431
|
-
// Positive numbers round correctly
|
|
432
|
-
try expectEqual(@as(T, 42.0), f(42.2));
|
|
433
|
-
try expectEqual(@as(T, 42.0), f(41.8));
|
|
434
|
-
|
|
435
|
-
// Negative numbers round correctly
|
|
436
|
-
try expectEqual(@as(T, -6.0), f(-5.9));
|
|
437
|
-
try expectEqual(@as(T, -6.0), f(-6.1));
|
|
438
|
-
|
|
439
|
-
// No rounding needed test
|
|
440
|
-
try expectEqual(@as(T, 5.0), f(5.0));
|
|
441
|
-
try expectEqual(@as(T, -10.0), f(-10.0));
|
|
442
|
-
try expectEqual(@as(T, 0.0), f(0.0));
|
|
443
|
-
|
|
444
|
-
// Very large numbers return unchanged
|
|
445
|
-
const large: T = 9007199254740992.0; // 2^53
|
|
446
|
-
try expectEqual(large, f(large));
|
|
447
|
-
try expectEqual(-large, f(-large));
|
|
448
|
-
|
|
449
|
-
// Small positive numbers round to zero
|
|
450
|
-
const pos_result = f(0.3);
|
|
451
|
-
try expect(math.isPositiveZero(pos_result));
|
|
452
|
-
|
|
453
|
-
// Small negative numbers round to negative zero
|
|
454
|
-
const neg_result = f(-0.3);
|
|
455
|
-
try expect(math.isNegativeZero(neg_result));
|
|
456
|
-
|
|
457
|
-
// Exact half rounds to nearest even (banker's rounding)
|
|
458
|
-
try expectEqual(@as(T, 2.0), f(2.5));
|
|
459
|
-
try expectEqual(@as(T, 4.0), f(3.5));
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
test "rint" {
|
|
463
|
-
try testRint(f32);
|
|
464
|
-
try testRint(f64);
|
|
465
|
-
}
|
|
466
|
-
|
|
467
367
|
fn tanh(x: f64) callconv(.c) f64 {
|
|
468
368
|
return math.tanh(x);
|
|
469
369
|
}
|
package/c/search.zig
CHANGED
|
@@ -9,6 +9,7 @@ comptime {
|
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
/// Not defined in `std.c` because C headers don't either.
|
|
12
13
|
const Node = extern struct {
|
|
13
14
|
next: ?*Node,
|
|
14
15
|
prev: ?*Node,
|
|
@@ -38,30 +39,3 @@ fn remque(element: *anyopaque) callconv(.c) void {
|
|
|
38
39
|
if (e.next) |next| next.prev = e.prev;
|
|
39
40
|
if (e.prev) |prev| prev.next = e.next;
|
|
40
41
|
}
|
|
41
|
-
|
|
42
|
-
test "insque and remque" {
|
|
43
|
-
var first = Node{ .next = null, .prev = null };
|
|
44
|
-
var second = Node{ .next = null, .prev = null };
|
|
45
|
-
var third = Node{ .next = null, .prev = null };
|
|
46
|
-
|
|
47
|
-
insque(&first, null);
|
|
48
|
-
try std.testing.expectEqual(@as(?*Node, null), first.next);
|
|
49
|
-
try std.testing.expectEqual(@as(?*Node, null), first.prev);
|
|
50
|
-
|
|
51
|
-
insque(&second, &first);
|
|
52
|
-
try std.testing.expectEqual(@as(?*Node, &second), first.next);
|
|
53
|
-
try std.testing.expectEqual(@as(?*Node, &first), second.prev);
|
|
54
|
-
|
|
55
|
-
insque(&third, &first);
|
|
56
|
-
try std.testing.expectEqual(@as(?*Node, &third), first.next);
|
|
57
|
-
try std.testing.expectEqual(@as(?*Node, &second), third.next);
|
|
58
|
-
try std.testing.expectEqual(@as(?*Node, &first), third.prev);
|
|
59
|
-
try std.testing.expectEqual(@as(?*Node, &third), second.prev);
|
|
60
|
-
|
|
61
|
-
remque(&third);
|
|
62
|
-
try std.testing.expectEqual(@as(?*Node, &second), first.next);
|
|
63
|
-
try std.testing.expectEqual(@as(?*Node, &first), second.prev);
|
|
64
|
-
|
|
65
|
-
remque(&second);
|
|
66
|
-
try std.testing.expectEqual(@as(?*Node, null), first.next);
|
|
67
|
-
}
|
package/c/stdlib/drand48.zig
CHANGED
|
@@ -90,60 +90,3 @@ fn srand48(seedval: c_long) callconv(.c) void {
|
|
|
90
90
|
const xi = (@as(u32, @truncate(@as(c_ulong, @bitCast(seedval)))) << 16) | 0x330E;
|
|
91
91
|
lcg = .init(xi, default_multiplier, default_addend);
|
|
92
92
|
}
|
|
93
|
-
|
|
94
|
-
test erand48 {
|
|
95
|
-
var xsubi: [3]c_ushort = .{ 37174, 64810, 11603 };
|
|
96
|
-
|
|
97
|
-
try std.testing.expectApproxEqAbs(0.8965, erand48(&xsubi), 0.0005);
|
|
98
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 22537, 47966, 58735 }, &xsubi);
|
|
99
|
-
|
|
100
|
-
try std.testing.expectApproxEqAbs(0.3375, erand48(&xsubi), 0.0005);
|
|
101
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 37344, 32911, 22119 }, &xsubi);
|
|
102
|
-
|
|
103
|
-
try std.testing.expectApproxEqAbs(0.6475, erand48(&xsubi), 0.0005);
|
|
104
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 23659, 29872, 42445 }, &xsubi);
|
|
105
|
-
|
|
106
|
-
try std.testing.expectApproxEqAbs(0.5005, erand48(&xsubi), 0.0005);
|
|
107
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 31642, 7875, 32802 }, &xsubi);
|
|
108
|
-
|
|
109
|
-
try std.testing.expectApproxEqAbs(0.5065, erand48(&xsubi), 0.0005);
|
|
110
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 64669, 14399, 33170 }, &xsubi);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
test jrand48 {
|
|
114
|
-
var xsubi: [3]c_ushort = .{ 25175, 11052, 45015 };
|
|
115
|
-
|
|
116
|
-
try std.testing.expectEqual(1699503220, jrand48(&xsubi));
|
|
117
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 2326, 23668, 25932 }, &xsubi);
|
|
118
|
-
|
|
119
|
-
try std.testing.expectEqual(-992276007, jrand48(&xsubi));
|
|
120
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 41577, 4569, 50395 }, &xsubi);
|
|
121
|
-
|
|
122
|
-
try std.testing.expectEqual(-19535776, jrand48(&xsubi));
|
|
123
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 31936, 59488, 65237 }, &xsubi);
|
|
124
|
-
|
|
125
|
-
try std.testing.expectEqual(79438377, jrand48(&xsubi));
|
|
126
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 40395, 8745, 1212 }, &xsubi);
|
|
127
|
-
|
|
128
|
-
try std.testing.expectEqual(-1258917728, jrand48(&xsubi));
|
|
129
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 37242, 28832, 46326 }, &xsubi);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
test nrand48 {
|
|
133
|
-
var xsubi: [3]c_ushort = .{ 546, 33817, 23389 };
|
|
134
|
-
|
|
135
|
-
try std.testing.expectEqual(914920692, nrand48(&xsubi));
|
|
136
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 29829, 10728, 27921 }, &xsubi);
|
|
137
|
-
|
|
138
|
-
try std.testing.expectEqual(754104482, nrand48(&xsubi));
|
|
139
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 6828, 28997, 23013 }, &xsubi);
|
|
140
|
-
|
|
141
|
-
try std.testing.expectEqual(609453945, nrand48(&xsubi));
|
|
142
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 58183, 3826, 18599 }, &xsubi);
|
|
143
|
-
|
|
144
|
-
try std.testing.expectEqual(1878644360, nrand48(&xsubi));
|
|
145
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 36678, 44304, 57331 }, &xsubi);
|
|
146
|
-
|
|
147
|
-
try std.testing.expectEqual(2114923686, nrand48(&xsubi));
|
|
148
|
-
try std.testing.expectEqualSlices(c_ushort, &.{ 58585, 22861, 64542 }, &xsubi);
|
|
149
|
-
}
|
package/c/stdlib.zig
CHANGED
|
@@ -294,103 +294,3 @@ fn bsearch(key: *const anyopaque, base: *const anyopaque, n: usize, size: usize,
|
|
|
294
294
|
}
|
|
295
295
|
return null;
|
|
296
296
|
}
|
|
297
|
-
|
|
298
|
-
test abs {
|
|
299
|
-
const val: c_int = -10;
|
|
300
|
-
try std.testing.expectEqual(10, abs(val));
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
test labs {
|
|
304
|
-
const val: c_long = -10;
|
|
305
|
-
try std.testing.expectEqual(10, labs(val));
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
test llabs {
|
|
309
|
-
const val: c_longlong = -10;
|
|
310
|
-
try std.testing.expectEqual(10, llabs(val));
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
test div {
|
|
314
|
-
const expected: div_t = .{ .quot = 5, .rem = 5 };
|
|
315
|
-
try std.testing.expectEqual(expected, div(55, 10));
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
test ldiv {
|
|
319
|
-
const expected: ldiv_t = .{ .quot = -6, .rem = 2 };
|
|
320
|
-
try std.testing.expectEqual(expected, ldiv(38, -6));
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
test lldiv {
|
|
324
|
-
const expected: lldiv_t = .{ .quot = 1, .rem = 2 };
|
|
325
|
-
try std.testing.expectEqual(expected, lldiv(5, 3));
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
test atoi {
|
|
329
|
-
try std.testing.expectEqual(0, atoi(@ptrCast("stop42true")));
|
|
330
|
-
try std.testing.expectEqual(42, atoi(@ptrCast("42true")));
|
|
331
|
-
try std.testing.expectEqual(-1, atoi(@ptrCast("-01")));
|
|
332
|
-
try std.testing.expectEqual(1, atoi(@ptrCast("+001")));
|
|
333
|
-
try std.testing.expectEqual(100, atoi(@ptrCast(" 100")));
|
|
334
|
-
try std.testing.expectEqual(500, atoi(@ptrCast("000000000000500")));
|
|
335
|
-
try std.testing.expectEqual(1111, atoi(@ptrCast("0000000000001111_0000")));
|
|
336
|
-
try std.testing.expectEqual(0, atoi(@ptrCast("0xAA")));
|
|
337
|
-
try std.testing.expectEqual(700, atoi(@ptrCast("700B")));
|
|
338
|
-
try std.testing.expectEqual(32453, atoi(@ptrCast("+32453more")));
|
|
339
|
-
try std.testing.expectEqual(std.math.maxInt(c_int), atoi(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.maxInt(c_int)}))));
|
|
340
|
-
try std.testing.expectEqual(std.math.minInt(c_int), atoi(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.minInt(c_int)}))));
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
test atol {
|
|
344
|
-
try std.testing.expectEqual(0, atol(@ptrCast("stop42true")));
|
|
345
|
-
try std.testing.expectEqual(42, atol(@ptrCast("42true")));
|
|
346
|
-
try std.testing.expectEqual(-1, atol(@ptrCast("-01")));
|
|
347
|
-
try std.testing.expectEqual(1, atol(@ptrCast("+001")));
|
|
348
|
-
try std.testing.expectEqual(100, atol(@ptrCast(" 100")));
|
|
349
|
-
try std.testing.expectEqual(500, atol(@ptrCast("000000000000500")));
|
|
350
|
-
try std.testing.expectEqual(1111, atol(@ptrCast("0000000000001111_0000")));
|
|
351
|
-
try std.testing.expectEqual(0, atol(@ptrCast("0xAA")));
|
|
352
|
-
try std.testing.expectEqual(700, atol(@ptrCast("700B")));
|
|
353
|
-
try std.testing.expectEqual(32453, atol(@ptrCast("+32453more")));
|
|
354
|
-
try std.testing.expectEqual(std.math.maxInt(c_long), atol(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.maxInt(c_long)}))));
|
|
355
|
-
try std.testing.expectEqual(std.math.minInt(c_long), atol(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.minInt(c_long)}))));
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
test atoll {
|
|
359
|
-
try std.testing.expectEqual(0, atoll(@ptrCast("stop42true")));
|
|
360
|
-
try std.testing.expectEqual(42, atoll(@ptrCast("42true")));
|
|
361
|
-
try std.testing.expectEqual(-1, atoll(@ptrCast("-01")));
|
|
362
|
-
try std.testing.expectEqual(1, atoll(@ptrCast("+001")));
|
|
363
|
-
try std.testing.expectEqual(100, atoll(@ptrCast(" 100")));
|
|
364
|
-
try std.testing.expectEqual(500, atoll(@ptrCast("000000000000500")));
|
|
365
|
-
try std.testing.expectEqual(1111, atoll(@ptrCast("0000000000001111_0000")));
|
|
366
|
-
try std.testing.expectEqual(0, atoll(@ptrCast("0xAA")));
|
|
367
|
-
try std.testing.expectEqual(700, atoll(@ptrCast("700B")));
|
|
368
|
-
try std.testing.expectEqual(32453, atoll(@ptrCast(" +32453more")));
|
|
369
|
-
try std.testing.expectEqual(std.math.maxInt(c_longlong), atoll(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.maxInt(c_longlong)}))));
|
|
370
|
-
try std.testing.expectEqual(std.math.minInt(c_longlong), atoll(@ptrCast(std.fmt.comptimePrint("{d}", .{std.math.minInt(c_longlong)}))));
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// FIXME: We cannot test strtol, strtoll, strtoul, etc.. here as it must modify errno and libc is not linked in tests
|
|
374
|
-
|
|
375
|
-
test bsearch {
|
|
376
|
-
const Comparison = struct {
|
|
377
|
-
pub fn compare(a: *const anyopaque, b: *const anyopaque) callconv(.c) c_int {
|
|
378
|
-
const a_u16: *const u16 = @ptrCast(@alignCast(a));
|
|
379
|
-
const b_u16: *const u16 = @ptrCast(@alignCast(b));
|
|
380
|
-
|
|
381
|
-
return switch (std.math.order(a_u16.*, b_u16.*)) {
|
|
382
|
-
.gt => 1,
|
|
383
|
-
.eq => 0,
|
|
384
|
-
.lt => -1,
|
|
385
|
-
};
|
|
386
|
-
}
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
const items: []const u16 = &.{ 0, 5, 7, 9, 10, 200, 512, 768 };
|
|
390
|
-
|
|
391
|
-
try std.testing.expectEqual(@as(?*anyopaque, null), bsearch(&@as(u16, 2000), items.ptr, items.len, @sizeOf(u16), Comparison.compare));
|
|
392
|
-
|
|
393
|
-
for (items) |*value| {
|
|
394
|
-
try std.testing.expectEqual(@as(*const anyopaque, value), bsearch(value, items.ptr, items.len, @sizeOf(u16), Comparison.compare));
|
|
395
|
-
}
|
|
396
|
-
}
|
package/c/string.zig
CHANGED
|
@@ -290,10 +290,3 @@ fn mempcpy(noalias dst: *anyopaque, noalias src: *const anyopaque, len: usize) c
|
|
|
290
290
|
@memcpy(dst_bytes[0..len], src_bytes[0..len]);
|
|
291
291
|
return dst_bytes + len;
|
|
292
292
|
}
|
|
293
|
-
|
|
294
|
-
test strncmp {
|
|
295
|
-
try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
|
|
296
|
-
try std.testing.expect(strncmp(@ptrCast("a"), @ptrCast("c"), 1) < 0);
|
|
297
|
-
try std.testing.expect(strncmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
|
|
298
|
-
try std.testing.expect(strncmp(@ptrCast("\xff"), @ptrCast("\x02"), 1) > 0);
|
|
299
|
-
}
|
package/c/strings.zig
CHANGED
|
@@ -81,41 +81,3 @@ fn __strncasecmp_l(a: [*:0]const c_char, b: [*:0]const c_char, n: usize, locale:
|
|
|
81
81
|
_ = locale;
|
|
82
82
|
return strncasecmp(a, b, n);
|
|
83
83
|
}
|
|
84
|
-
|
|
85
|
-
test bzero {
|
|
86
|
-
var array: [10]u8 = [_]u8{ '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };
|
|
87
|
-
var a = std.mem.zeroes([array.len]u8);
|
|
88
|
-
a[9] = '0';
|
|
89
|
-
bzero(&array[0], 9);
|
|
90
|
-
try std.testing.expect(std.mem.eql(u8, &array, &a));
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
test firstBitSet {
|
|
94
|
-
try std.testing.expectEqual(0, firstBitSet(usize, 0));
|
|
95
|
-
|
|
96
|
-
for (0..@bitSizeOf(usize)) |i| {
|
|
97
|
-
const bit = @as(usize, 1) << @intCast(i);
|
|
98
|
-
|
|
99
|
-
try std.testing.expectEqual(i + 1, firstBitSet(usize, bit));
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
test strcasecmp {
|
|
104
|
-
try std.testing.expect(strcasecmp(@ptrCast("a"), @ptrCast("b")) < 0);
|
|
105
|
-
try std.testing.expect(strcasecmp(@ptrCast("b"), @ptrCast("a")) > 0);
|
|
106
|
-
try std.testing.expect(strcasecmp(@ptrCast("A"), @ptrCast("b")) < 0);
|
|
107
|
-
try std.testing.expect(strcasecmp(@ptrCast("b"), @ptrCast("A")) > 0);
|
|
108
|
-
try std.testing.expect(strcasecmp(@ptrCast("A"), @ptrCast("A")) == 0);
|
|
109
|
-
try std.testing.expect(strcasecmp(@ptrCast("B"), @ptrCast("b")) == 0);
|
|
110
|
-
try std.testing.expect(strcasecmp(@ptrCast("bb"), @ptrCast("AA")) > 0);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
test strncasecmp {
|
|
114
|
-
try std.testing.expect(strncasecmp(@ptrCast("a"), @ptrCast("b"), 1) < 0);
|
|
115
|
-
try std.testing.expect(strncasecmp(@ptrCast("b"), @ptrCast("a"), 1) > 0);
|
|
116
|
-
try std.testing.expect(strncasecmp(@ptrCast("A"), @ptrCast("b"), 1) < 0);
|
|
117
|
-
try std.testing.expect(strncasecmp(@ptrCast("b"), @ptrCast("A"), 1) > 0);
|
|
118
|
-
try std.testing.expect(strncasecmp(@ptrCast("A"), @ptrCast("A"), 1) == 0);
|
|
119
|
-
try std.testing.expect(strncasecmp(@ptrCast("B"), @ptrCast("b"), 1) == 0);
|
|
120
|
-
try std.testing.expect(strncasecmp(@ptrCast("bb"), @ptrCast("AA"), 2) > 0);
|
|
121
|
-
}
|
package/c/unistd.zig
CHANGED
|
@@ -21,6 +21,8 @@ comptime {
|
|
|
21
21
|
symbol(&chrootLinux, "chroot");
|
|
22
22
|
symbol(&ctermidLinux, "ctermid");
|
|
23
23
|
symbol(&dupLinux, "dup");
|
|
24
|
+
symbol(&dup2Linux, "dup2");
|
|
25
|
+
symbol(&dup3Linux, "dup3");
|
|
24
26
|
|
|
25
27
|
symbol(&getegidLinux, "getegid");
|
|
26
28
|
symbol(&geteuidLinux, "geteuid");
|
|
@@ -101,6 +103,31 @@ fn dupLinux(fd: c_int) callconv(.c) c_int {
|
|
|
101
103
|
return errno(linux.dup(fd));
|
|
102
104
|
}
|
|
103
105
|
|
|
106
|
+
fn dup2Linux(old: c_int, new: c_int) callconv(.c) c_int {
|
|
107
|
+
const busy: usize = @bitCast(-@as(isize, @intFromEnum(linux.E.BUSY)));
|
|
108
|
+
var res = busy;
|
|
109
|
+
while (res == busy) res = linux.dup2(old, new);
|
|
110
|
+
return errno(res);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
fn dup3Linux(old: c_int, new: c_int, flags: c_int) callconv(.c) c_int {
|
|
114
|
+
const busy: usize = @bitCast(-@as(isize, @intFromEnum(linux.E.BUSY)));
|
|
115
|
+
var res = busy;
|
|
116
|
+
|
|
117
|
+
if (@hasField(linux.SYS, "dup3")) {
|
|
118
|
+
while (res == busy) res = linux.dup3(old, new, @intCast(flags));
|
|
119
|
+
} else if (@hasField(linux.SYS, "dup2")) {
|
|
120
|
+
const cloexec: c_int = @bitCast(linux.O{ .CLOEXEC = true });
|
|
121
|
+
const inval: usize = @bitCast(-@as(isize, @intFromEnum(linux.E.INVAL)));
|
|
122
|
+
if (old == new or (flags & ~cloexec != 0)) return errno(inval);
|
|
123
|
+
while (res == busy) res = linux.dup2(old, new);
|
|
124
|
+
_ = if (res >= 0 and (flags & cloexec == cloexec)) linux.fcntl(new, linux.F.SETFD, linux.FD_CLOEXEC);
|
|
125
|
+
} else {
|
|
126
|
+
return errno(@bitCast(-@as(isize, @intFromEnum(linux.E.NOSYS))));
|
|
127
|
+
}
|
|
128
|
+
return errno(res);
|
|
129
|
+
}
|
|
130
|
+
|
|
104
131
|
fn getegidLinux() callconv(.c) linux.gid_t {
|
|
105
132
|
return linux.getegid();
|
|
106
133
|
}
|
|
@@ -206,32 +233,6 @@ fn swab(noalias src_ptr: *const anyopaque, noalias dest_ptr: *anyopaque, n: isiz
|
|
|
206
233
|
}
|
|
207
234
|
}
|
|
208
235
|
|
|
209
|
-
test swab {
|
|
210
|
-
var a: [4]u8 = undefined;
|
|
211
|
-
@memset(a[0..], '\x00');
|
|
212
|
-
swab("abcd", &a, 4);
|
|
213
|
-
try std.testing.expectEqualSlices(u8, "badc", &a);
|
|
214
|
-
|
|
215
|
-
// Partial copy
|
|
216
|
-
@memset(a[0..], '\x00');
|
|
217
|
-
swab("abcd", &a, 2);
|
|
218
|
-
try std.testing.expectEqualSlices(u8, "ba\x00\x00", &a);
|
|
219
|
-
|
|
220
|
-
// n < 1
|
|
221
|
-
@memset(a[0..], '\x00');
|
|
222
|
-
swab("abcd", &a, 0);
|
|
223
|
-
try std.testing.expectEqualSlices(u8, "\x00" ** 4, &a);
|
|
224
|
-
swab("abcd", &a, -1);
|
|
225
|
-
try std.testing.expectEqualSlices(u8, "\x00" ** 4, &a);
|
|
226
|
-
|
|
227
|
-
// Odd n
|
|
228
|
-
@memset(a[0..], '\x00');
|
|
229
|
-
swab("abcd", &a, 1);
|
|
230
|
-
try std.testing.expectEqualSlices(u8, "\x00" ** 4, &a);
|
|
231
|
-
swab("abcd", &a, 3);
|
|
232
|
-
try std.testing.expectEqualSlices(u8, "ba\x00\x00", &a);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
236
|
fn close(fd: std.c.fd_t) callconv(.c) c_int {
|
|
236
237
|
const signed: isize = @bitCast(linux.close(fd));
|
|
237
238
|
if (signed < 0) {
|
package/c.zig
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
//! bundled libcs.
|
|
3
3
|
//!
|
|
4
4
|
//! mingw-w64 libc is not fully statically linked, so some symbols don't need
|
|
5
|
-
//! to be exported.
|
|
6
|
-
//! dependency on msvcrt dll even when linking libc and targeting Windows.
|
|
5
|
+
//! to be exported.
|
|
7
6
|
|
|
8
7
|
const builtin = @import("builtin");
|
|
9
8
|
const std = @import("std");
|
package/compiler_rt/limb64.zig
CHANGED
|
@@ -152,6 +152,10 @@ fn test__addo_limb64(comptime T: type, a: T, b: T, expected: struct { T, bool })
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
test __addo_limb64 {
|
|
155
|
+
if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
156
|
+
if (builtin.cpu.arch == .mips64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
157
|
+
if (builtin.cpu.arch == .powerpc64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
158
|
+
|
|
155
159
|
try test__addo_limb64(u64, 1, 2, .{ 3, false });
|
|
156
160
|
try test__addo_limb64(u64, maxInt(u64), 2, .{ 1, true });
|
|
157
161
|
try test__addo_limb64(u65, maxInt(u65), 2, .{ 1, true });
|
|
@@ -228,6 +232,10 @@ fn test__subo_limb64(comptime T: type, a: T, b: T, expected: struct { T, bool })
|
|
|
228
232
|
}
|
|
229
233
|
|
|
230
234
|
test __subo_limb64 {
|
|
235
|
+
if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
236
|
+
if (builtin.cpu.arch == .mips64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
237
|
+
if (builtin.cpu.arch == .powerpc64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
238
|
+
|
|
231
239
|
try test__subo_limb64(u64, 3, 2, .{ 1, false });
|
|
232
240
|
try test__subo_limb64(u64, 0, 1, .{ maxInt(u64), true });
|
|
233
241
|
try test__subo_limb64(u65, 0, 1, .{ maxInt(u65), true });
|
|
@@ -477,6 +485,10 @@ fn test__not_limb64(comptime T: type, a: T, expected: T) !void {
|
|
|
477
485
|
}
|
|
478
486
|
|
|
479
487
|
test __not_limb64 {
|
|
488
|
+
if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
489
|
+
if (builtin.cpu.arch == .mips64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
490
|
+
if (builtin.cpu.arch == .powerpc64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
491
|
+
|
|
480
492
|
try test__not_limb64(u64, 1, maxInt(u64) - 1);
|
|
481
493
|
try test__not_limb64(u64, 3, maxInt(u64) - 3);
|
|
482
494
|
try test__not_limb64(u65, maxInt(u65), 0);
|
|
@@ -555,6 +567,10 @@ fn test__shlo_limb64(comptime T: type, a: T, shift: u16, expected: struct { T, b
|
|
|
555
567
|
}
|
|
556
568
|
|
|
557
569
|
test __shlo_limb64 {
|
|
570
|
+
if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
571
|
+
if (builtin.cpu.arch == .mips64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
572
|
+
if (builtin.cpu.arch == .powerpc64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
573
|
+
|
|
558
574
|
try test__shlo_limb64(u64, 0x1234_5678_9ABC_DEF0, 4, .{ 0x2345_6789_ABCD_EF00, true });
|
|
559
575
|
try test__shlo_limb64(u64, 0x8000_0000_0000_0001, 63, .{ 0x8000_0000_0000_0000, true });
|
|
560
576
|
try test__shlo_limb64(u65, 1, 64, .{ 0x1_0000_0000_0000_0000, false });
|
|
@@ -631,6 +647,10 @@ fn test__shr_limb64(comptime T: type, a: T, shift: u16, expected: T) !void {
|
|
|
631
647
|
}
|
|
632
648
|
|
|
633
649
|
test __shr_limb64 {
|
|
650
|
+
if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
651
|
+
if (builtin.cpu.arch == .mips64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
652
|
+
if (builtin.cpu.arch == .powerpc64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
653
|
+
|
|
634
654
|
try test__shr_limb64(u64, 0x1234_5678_9ABC_DEF0, 4, 0x0123_4567_89AB_CDEF);
|
|
635
655
|
try test__shr_limb64(u64, 0x8000_0000_0000_0001, 63, 1);
|
|
636
656
|
try test__shr_limb64(u65, 0x1_0000_0000_0000_0000, 64, 1);
|
|
@@ -858,6 +878,10 @@ fn test__bitreverse_limb64(comptime T: type, a: T, expected: T) !void {
|
|
|
858
878
|
}
|
|
859
879
|
|
|
860
880
|
test __bitreverse_limb64 {
|
|
881
|
+
if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
882
|
+
if (builtin.cpu.arch == .mips64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
883
|
+
if (builtin.cpu.arch == .powerpc64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
884
|
+
|
|
861
885
|
try test__bitreverse_limb64(u64, 1 << 7, 1 << 56);
|
|
862
886
|
try test__bitreverse_limb64(u65, 1 << 64, 1);
|
|
863
887
|
try test__bitreverse_limb64(u65, 1 << 9, 1 << 55);
|
|
@@ -910,6 +934,10 @@ fn test__byteswap_limb64(comptime T: type, a: T, expected: T) !void {
|
|
|
910
934
|
}
|
|
911
935
|
|
|
912
936
|
test __byteswap_limb64 {
|
|
937
|
+
if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
938
|
+
if (builtin.cpu.arch == .mips64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
939
|
+
if (builtin.cpu.arch == .powerpc64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
940
|
+
|
|
913
941
|
try test__byteswap_limb64(u64, 0x0123_4567_89AB_CDEF, 0xEFCD_AB89_6745_2301);
|
|
914
942
|
try test__byteswap_limb64(u72, 0x01_23_45_67_89_AB_CD_EF_11, 0x11_EF_CD_AB_89_67_45_23_01);
|
|
915
943
|
try test__byteswap_limb64(u128, 1 << 72, 1 << 48);
|
|
@@ -1036,6 +1064,10 @@ fn test__mulo_limb64(comptime T: type, a: T, b: T, expected: struct { T, bool })
|
|
|
1036
1064
|
}
|
|
1037
1065
|
|
|
1038
1066
|
test __mulo_limb64 {
|
|
1067
|
+
if (builtin.cpu.arch == .aarch64_be) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
1068
|
+
if (builtin.cpu.arch == .mips64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
1069
|
+
if (builtin.cpu.arch == .powerpc64) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/31905
|
|
1070
|
+
|
|
1039
1071
|
try test__mulo_limb64(u64, 3, 5, .{ 15, false });
|
|
1040
1072
|
try test__mulo_limb64(u64, maxInt(u64), 2, .{ maxInt(u64) - 1, true });
|
|
1041
1073
|
try test__mulo_limb64(u65, 1 << 32, 1 << 32, .{ 1 << 64, false });
|
package/package.json
CHANGED
package/std/Io/Semaphore.zig
CHANGED
|
@@ -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.
|
|
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
|
|
43
|
-
if (builtin.single_threaded) return error.SkipZigTest;
|
|
71
|
+
test wait {
|
|
44
72
|
const io = testing.io;
|
|
45
73
|
|
|
46
|
-
const
|
|
47
|
-
sem:
|
|
48
|
-
n:
|
|
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
|
|
80
|
+
ctx.n += 1;
|
|
52
81
|
ctx.sem.post(io);
|
|
53
82
|
}
|
|
54
83
|
};
|
|
55
|
-
|
|
56
|
-
var
|
|
57
|
-
|
|
58
|
-
var
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
for (
|
|
63
|
-
|
|
64
|
-
try
|
|
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
|
}
|
package/std/Io/Threaded.zig
CHANGED
|
@@ -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, .
|
|
2008
|
+
.dragonfly, .freebsd, .netbsd, .openbsd, .illumos, .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => true,
|
|
2009
2009
|
else => false,
|
|
2010
2010
|
};
|
|
2011
2011
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
///
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
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 =
|
|
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.
|
|
1733
|
-
//
|
|
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
|
|
package/std/c/serenity.zig
CHANGED
|
@@ -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:
|
|
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)
|
|
11107
|
-
pub extern "c" fn copysign(x: f64, y: f64)
|
|
11108
|
-
pub extern "c" fn fdim(x: f64, y: f64)
|
|
11109
|
-
pub extern "c" fn frexp(x: f64, e: *c_int)
|
|
11110
|
-
pub extern "c" fn hypot(x: f64, y: f64)
|
|
11111
|
-
pub extern "c" fn
|
|
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/os.zig
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const builtin = @import("builtin");
|
|
2
|
+
const std = @import("std.zig");
|
|
2
3
|
const native_os = builtin.os.tag;
|
|
3
4
|
|
|
4
5
|
pub const linux = @import("os/linux.zig");
|
|
@@ -8,6 +9,46 @@ pub const wasi = @import("os/wasi.zig");
|
|
|
8
9
|
pub const emscripten = @import("os/emscripten.zig");
|
|
9
10
|
pub const windows = @import("os/windows.zig");
|
|
10
11
|
|
|
12
|
+
/// Returns whether the Zig standard library requires libc in order to interface
|
|
13
|
+
/// with the operating system on the given target.
|
|
14
|
+
pub fn targetRequiresLibC(target: *const std.Target) bool {
|
|
15
|
+
if (target.requiresLibC()) return true;
|
|
16
|
+
return switch (target.os.tag) {
|
|
17
|
+
.linux => switch (target.cpu.arch) {
|
|
18
|
+
// https://codeberg.org/ziglang/zig/issues/30940
|
|
19
|
+
.alpha,
|
|
20
|
+
// https://codeberg.org/ziglang/zig/issues/30942
|
|
21
|
+
.csky,
|
|
22
|
+
// https://codeberg.org/ziglang/zig/issues/30943
|
|
23
|
+
.hppa,
|
|
24
|
+
.hppa64,
|
|
25
|
+
// https://codeberg.org/ziglang/zig/issues/30944
|
|
26
|
+
.microblaze,
|
|
27
|
+
.microblazeel,
|
|
28
|
+
// https://codeberg.org/ziglang/zig/issues/30946
|
|
29
|
+
.sh,
|
|
30
|
+
.sheb,
|
|
31
|
+
// https://codeberg.org/ziglang/zig/issues/30945
|
|
32
|
+
.sparc,
|
|
33
|
+
// https://codeberg.org/ziglang/zig/issues/30947
|
|
34
|
+
.xtensa,
|
|
35
|
+
.xtensaeb,
|
|
36
|
+
=> true,
|
|
37
|
+
else => false,
|
|
38
|
+
},
|
|
39
|
+
.freebsd => true, // https://codeberg.org/ziglang/zig/issues/30981
|
|
40
|
+
.netbsd => true, // https://codeberg.org/ziglang/zig/issues/30980
|
|
41
|
+
.openbsd => true, // https://codeberg.org/ziglang/zig/issues/30982
|
|
42
|
+
else => false,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/// Returns whether the Zig standard library requires libc in order to interface
|
|
47
|
+
/// with the operating system on the current target.
|
|
48
|
+
pub fn requiresLibC() bool {
|
|
49
|
+
return targetRequiresLibC(&builtin.target);
|
|
50
|
+
}
|
|
51
|
+
|
|
11
52
|
test {
|
|
12
53
|
_ = linux;
|
|
13
54
|
if (native_os == .uefi) _ = uefi;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
#include <unistd.h>
|
|
2
|
-
#include <errno.h>
|
|
3
|
-
#include <fcntl.h>
|
|
4
|
-
#include "syscall.h"
|
|
5
|
-
|
|
6
|
-
int dup2(int old, int new)
|
|
7
|
-
{
|
|
8
|
-
int r;
|
|
9
|
-
#ifdef SYS_dup2
|
|
10
|
-
while ((r=__syscall(SYS_dup2, old, new))==-EBUSY);
|
|
11
|
-
#else
|
|
12
|
-
if (old==new) {
|
|
13
|
-
r = __syscall(SYS_fcntl, old, F_GETFD);
|
|
14
|
-
if (r >= 0) return old;
|
|
15
|
-
} else {
|
|
16
|
-
while ((r=__syscall(SYS_dup3, old, new, 0))==-EBUSY);
|
|
17
|
-
}
|
|
18
|
-
#endif
|
|
19
|
-
return __syscall_ret(r);
|
|
20
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
#define _GNU_SOURCE
|
|
2
|
-
#include <unistd.h>
|
|
3
|
-
#include <errno.h>
|
|
4
|
-
#include <fcntl.h>
|
|
5
|
-
#include "syscall.h"
|
|
6
|
-
|
|
7
|
-
int __dup3(int old, int new, int flags)
|
|
8
|
-
{
|
|
9
|
-
int r;
|
|
10
|
-
#ifdef SYS_dup2
|
|
11
|
-
if (old==new) return __syscall_ret(-EINVAL);
|
|
12
|
-
if (flags) {
|
|
13
|
-
while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY);
|
|
14
|
-
if (r!=-ENOSYS) return __syscall_ret(r);
|
|
15
|
-
if (flags & ~O_CLOEXEC) return __syscall_ret(-EINVAL);
|
|
16
|
-
}
|
|
17
|
-
while ((r=__syscall(SYS_dup2, old, new))==-EBUSY);
|
|
18
|
-
if (r >= 0 && (flags & O_CLOEXEC))
|
|
19
|
-
__syscall(SYS_fcntl, new, F_SETFD, FD_CLOEXEC);
|
|
20
|
-
#else
|
|
21
|
-
while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY);
|
|
22
|
-
#endif
|
|
23
|
-
return __syscall_ret(r);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
weak_alias(__dup3, dup3);
|