authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-27 12:06:29-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-27 20:56:49-07:00
logdcf9cae2568a7422ab7885404da63fafa31b00fc
treeabddb7a0d5b0eb192e8d7c29ba9613a6bbfab04e
parenteea7e5e554ff12b4b72a8aa8877d059e7c055bc3

std.Progress: handle big-endian targets

We cannot rely on host endianness because the parent or child process may be executing inside QEMU.

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

lib/std/Progress.zig+16-4
...@@ -7,6 +7,7 @@ const testing = std.testing;...@@ -7,6 +7,7 @@ const testing = std.testing;
7const assert = std.debug.assert;7const assert = std.debug.assert;
8const Progress = @This();8const Progress = @This();
9const posix = std.posix;9const posix = std.posix;
10const is_big_endian = builtin.cpu.arch.endian() == .big;
1011
11/// `null` if the current node (and its children) should12/// `null` if the current node (and its children) should
12/// not print on update()13/// not print on update()
...@@ -101,6 +102,11 @@ pub const Node = struct {...@@ -101,6 +102,11 @@ pub const Node = struct {
101 };102 };
102 }103 }
103104
105 fn byteSwap(s: *Storage) void {
106 s.completed_count = @byteSwap(s.completed_count);
107 s.estimated_total_count = @byteSwap(s.estimated_total_count);
108 }
109
104 comptime {110 comptime {
105 assert((@sizeOf(Storage) % 4) == 0);111 assert((@sizeOf(Storage) % 4) == 0);
106 }112 }
...@@ -719,9 +725,14 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff...@@ -719,9 +725,14 @@ fn serializeIpc(start_serialized_len: usize, serialized_buffer: *Serialized.Buff
719725
720 // Mount the root here.726 // Mount the root here.
721 copyRoot(main_storage, &storage[0]);727 copyRoot(main_storage, &storage[0]);
728 if (is_big_endian) main_storage.byteSwap();
722729
723 // Copy the rest of the tree to the end.730 // Copy the rest of the tree to the end.
724 @memcpy(serialized_buffer.storage[serialized_len..][0..nodes_len], storage[1..][0..nodes_len]);731 const storage_dest = serialized_buffer.storage[serialized_len..][0..nodes_len];
732 @memcpy(storage_dest, storage[1..][0..nodes_len]);
733
734 // Always little-endian over the pipe.
735 if (is_big_endian) for (storage_dest) |*s| s.byteSwap();
725736
726 // Patch up parent pointers taking into account how the subtree is mounted.737 // Patch up parent pointers taking into account how the subtree is mounted.
727 for (serialized_buffer.parents[serialized_len..][0..nodes_len], parents[1..][0..nodes_len]) |*dest, p| {738 for (serialized_buffer.parents[serialized_len..][0..nodes_len], parents[1..][0..nodes_len]) |*dest, p| {
...@@ -983,6 +994,10 @@ fn write(buf: []const u8) anyerror!void {...@@ -983,6 +994,10 @@ fn write(buf: []const u8) anyerror!void {
983}994}
984995
985fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void {996fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void {
997 // Byteswap if necessary to ensure little endian over the pipe. This is
998 // needed because the parent or child process might be running in qemu.
999 if (is_big_endian) for (serialized.storage) |*s| s.byteSwap();
1000
986 assert(serialized.parents.len == serialized.storage.len);1001 assert(serialized.parents.len == serialized.storage.len);
987 const serialized_len: u8 = @intCast(serialized.parents.len);1002 const serialized_len: u8 = @intCast(serialized.parents.len);
988 const header = std.mem.asBytes(&serialized_len);1003 const header = std.mem.asBytes(&serialized_len);
...@@ -995,9 +1010,6 @@ fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void {...@@ -995,9 +1010,6 @@ fn writeIpc(fd: posix.fd_t, serialized: Serialized) error{BrokenPipe}!void {
995 .{ .base = parents.ptr, .len = parents.len },1010 .{ .base = parents.ptr, .len = parents.len },
996 };1011 };
9971012
998 // TODO: if big endian, byteswap
999 // this is needed because the parent or child process might be running in qemu
1000
1001 // If this write would block we do not want to keep trying, but we need to1013 // If this write would block we do not want to keep trying, but we need to
1002 // know if a partial message was written.1014 // know if a partial message was written.
1003 if (posix.writev(fd, &vecs)) |written| {1015 if (posix.writev(fd, &vecs)) |written| {