behavior tests passing on Linux
This commit is contained in:
parent
44a049e01e
commit
2b42e910bf
@ -1,4 +1,6 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const page_size = std.mem.page_size;
|
||||
|
||||
pub use @import("os/bits.zig");
|
||||
|
||||
@ -33,7 +35,7 @@ pub extern "c" fn close(fd: fd_t) c_int;
|
||||
pub extern "c" fn fstat(fd: fd_t, buf: *Stat) c_int;
|
||||
pub extern "c" fn @"fstat$INODE64"(fd: fd_t, buf: *Stat) c_int;
|
||||
pub extern "c" fn lseek(fd: fd_t, offset: isize, whence: c_int) isize;
|
||||
pub extern "c" fn open(path: [*]const u8, oflag: c_int, ...) c_int;
|
||||
pub extern "c" fn open(path: [*]const u8, oflag: c_uint, ...) c_int;
|
||||
pub extern "c" fn raise(sig: c_int) c_int;
|
||||
pub extern "c" fn read(fd: fd_t, buf: [*]u8, nbyte: usize) isize;
|
||||
pub extern "c" fn pread(fd: fd_t, buf: [*]u8, nbyte: usize, offset: u64) isize;
|
||||
@ -42,8 +44,9 @@ pub extern "c" fn pwritev(fd: c_int, iov: [*]const iovec, iovcnt: c_int, offset:
|
||||
pub extern "c" fn stat(noalias path: [*]const u8, noalias buf: *Stat) c_int;
|
||||
pub extern "c" fn write(fd: fd_t, buf: [*]const u8, nbyte: usize) isize;
|
||||
pub extern "c" fn pwrite(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: u64) isize;
|
||||
pub extern "c" fn mmap(addr: ?*c_void, len: usize, prot: c_int, flags: c_int, fd: fd_t, offset: isize) usize;
|
||||
pub extern "c" fn munmap(addr: ?*c_void, len: usize) c_int;
|
||||
pub extern "c" fn mmap(addr: ?*align(page_size) c_void, len: usize, prot: c_uint, flags: c_uint, fd: fd_t, offset: isize) *c_void;
|
||||
pub extern "c" fn munmap(addr: *align(page_size) c_void, len: usize) c_int;
|
||||
pub extern "c" fn mprotect(addr: *align(page_size) c_void, len: usize, prot: c_uint) c_int;
|
||||
pub extern "c" fn unlink(path: [*]const u8) c_int;
|
||||
pub extern "c" fn getcwd(buf: [*]u8, size: usize) ?[*]u8;
|
||||
pub extern "c" fn waitpid(pid: c_int, stat_loc: *c_int, options: c_int) c_int;
|
||||
|
@ -1011,7 +1011,7 @@ fn openSelfDebugInfoPosix(allocator: *mem.Allocator) !DwarfInfo {
|
||||
S.self_exe_file = try fs.openSelfExe();
|
||||
errdefer S.self_exe_file.close();
|
||||
|
||||
const self_exe_mmap_len = try S.self_exe_file.getEndPos();
|
||||
const self_exe_mmap_len = mem.alignForward(try S.self_exe_file.getEndPos(), mem.page_size);
|
||||
const self_exe_mmap = try os.mmap(
|
||||
null,
|
||||
self_exe_mmap_len,
|
||||
@ -1020,10 +1020,9 @@ fn openSelfDebugInfoPosix(allocator: *mem.Allocator) !DwarfInfo {
|
||||
S.self_exe_file.handle,
|
||||
0,
|
||||
);
|
||||
errdefer os.munmap(self_exe_mmap, self_exe_mmap_len);
|
||||
errdefer os.munmap(self_exe_mmap);
|
||||
|
||||
const file_mmap_slice = @intToPtr([*]const u8, self_exe_mmap)[0..self_exe_mmap_len];
|
||||
S.self_exe_mmap_seekable = io.SliceSeekableInStream.init(file_mmap_slice);
|
||||
S.self_exe_mmap_seekable = io.SliceSeekableInStream.init(self_exe_mmap);
|
||||
|
||||
return openElfDebugInfo(
|
||||
allocator,
|
||||
|
@ -595,8 +595,8 @@ pub const Dir = struct {
|
||||
}
|
||||
|
||||
while (true) {
|
||||
const rc = os.system.getdents64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len);
|
||||
switch (os.errno(rc)) {
|
||||
const rc = os.linux.getdents64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len);
|
||||
switch (os.linux.getErrno(rc)) {
|
||||
0 => {},
|
||||
os.EBADF => unreachable,
|
||||
os.EFAULT => unreachable,
|
||||
|
29
std/heap.zig
29
std/heap.zig
@ -104,35 +104,36 @@ pub const DirectAllocator = struct {
|
||||
}
|
||||
|
||||
const alloc_size = if (alignment <= mem.page_size) n else n + alignment;
|
||||
const addr = os.mmap(
|
||||
const slice = os.mmap(
|
||||
null,
|
||||
alloc_size,
|
||||
mem.alignForward(alloc_size, mem.page_size),
|
||||
os.PROT_READ | os.PROT_WRITE,
|
||||
os.MAP_PRIVATE | os.MAP_ANONYMOUS,
|
||||
-1,
|
||||
0,
|
||||
) catch return error.OutOfMemory;
|
||||
if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n];
|
||||
if (alloc_size == n) return slice;
|
||||
|
||||
const aligned_addr = mem.alignForward(addr, alignment);
|
||||
const aligned_addr = mem.alignForward(@ptrToInt(slice.ptr), alignment);
|
||||
|
||||
// Unmap the extra bytes that were only requested in order to guarantee
|
||||
// that the range of memory we were provided had a proper alignment in
|
||||
// it somewhere. The extra bytes could be at the beginning, or end, or both.
|
||||
const unused_start_len = aligned_addr - addr;
|
||||
const unused_start_len = aligned_addr - @ptrToInt(slice.ptr);
|
||||
if (unused_start_len != 0) {
|
||||
os.munmap(addr, unused_start_len);
|
||||
os.munmap(slice[0..unused_start_len]);
|
||||
}
|
||||
const aligned_end_addr = std.mem.alignForward(aligned_addr + n, mem.page_size);
|
||||
const unused_end_len = addr + alloc_size - aligned_end_addr;
|
||||
const aligned_end_addr = mem.alignForward(aligned_addr + n, mem.page_size);
|
||||
const unused_end_len = @ptrToInt(slice.ptr) + slice.len - aligned_end_addr;
|
||||
if (unused_end_len != 0) {
|
||||
os.munmap(aligned_end_addr, unused_end_len);
|
||||
os.munmap(@intToPtr([*]align(mem.page_size) u8, aligned_end_addr)[0..unused_end_len]);
|
||||
}
|
||||
|
||||
return @intToPtr([*]u8, aligned_addr)[0..n];
|
||||
}
|
||||
|
||||
fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
|
||||
fn shrink(allocator: *Allocator, old_mem_unaligned: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
|
||||
const old_mem = @alignCast(mem.page_size, old_mem_unaligned);
|
||||
if (os.windows.is_the_target) {
|
||||
const w = os.windows;
|
||||
if (new_size == 0) {
|
||||
@ -165,12 +166,14 @@ pub const DirectAllocator = struct {
|
||||
const new_addr_end = base_addr + new_size;
|
||||
const new_addr_end_rounded = mem.alignForward(new_addr_end, mem.page_size);
|
||||
if (old_addr_end > new_addr_end_rounded) {
|
||||
os.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded);
|
||||
const ptr = @intToPtr([*]align(mem.page_size) u8, new_addr_end_rounded);
|
||||
os.munmap(ptr[0 .. old_addr_end - new_addr_end_rounded]);
|
||||
}
|
||||
return old_mem[0..new_size];
|
||||
}
|
||||
|
||||
fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
|
||||
fn realloc(allocator: *Allocator, old_mem_unaligned: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
|
||||
const old_mem = @alignCast(mem.page_size, old_mem_unaligned);
|
||||
if (os.windows.is_the_target) {
|
||||
if (old_mem.len == 0) {
|
||||
return alloc(allocator, new_size, new_align);
|
||||
@ -231,7 +234,7 @@ pub const DirectAllocator = struct {
|
||||
const result = try alloc(allocator, new_size, new_align);
|
||||
if (old_mem.len != 0) {
|
||||
@memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
|
||||
os.munmap(@ptrToInt(old_mem.ptr), old_mem.len);
|
||||
os.munmap(old_mem);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
const std = @import("std.zig");
|
||||
const builtin = @import("builtin");
|
||||
const Os = builtin.Os;
|
||||
const c = std.c;
|
||||
|
||||
const math = std.math;
|
||||
const debug = std.debug;
|
||||
const assert = debug.assert;
|
||||
const os = std.os;
|
||||
const fs = std.fs;
|
||||
const mem = std.mem;
|
||||
const meta = std.meta;
|
||||
const trait = meta.trait;
|
||||
@ -985,7 +985,7 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
|
||||
}
|
||||
|
||||
pub const BufferedAtomicFile = struct {
|
||||
atomic_file: os.AtomicFile,
|
||||
atomic_file: fs.AtomicFile,
|
||||
file_stream: File.OutStream,
|
||||
buffered_stream: BufferedOutStream(File.WriteError),
|
||||
allocator: *mem.Allocator,
|
||||
@ -1001,7 +1001,7 @@ pub const BufferedAtomicFile = struct {
|
||||
};
|
||||
errdefer allocator.destroy(self);
|
||||
|
||||
self.atomic_file = try os.AtomicFile.init(dest_path, File.default_mode);
|
||||
self.atomic_file = try fs.AtomicFile.init(dest_path, File.default_mode);
|
||||
errdefer self.atomic_file.deinit();
|
||||
|
||||
self.file_stream = self.atomic_file.file.outStream();
|
||||
|
@ -37,7 +37,7 @@ pub const COutStream = struct {
|
||||
os.ENOSPC => return error.NoSpaceLeft,
|
||||
os.EPERM => return error.AccessDenied,
|
||||
os.EPIPE => return error.BrokenPipe,
|
||||
else => return os.unexpectedErrno(@intCast(usize, errno)),
|
||||
else => |err| return os.unexpectedErrno(@intCast(usize, err)),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
73
std/mem.zig
73
std/mem.zig
@ -585,14 +585,14 @@ pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian)
|
||||
test "comptime read/write int" {
|
||||
comptime {
|
||||
var bytes: [2]u8 = undefined;
|
||||
std.mem.writeIntLittle(u16, &bytes, 0x1234);
|
||||
const result = std.mem.readIntBig(u16, &bytes);
|
||||
writeIntLittle(u16, &bytes, 0x1234);
|
||||
const result = readIntBig(u16, &bytes);
|
||||
testing.expect(result == 0x3412);
|
||||
}
|
||||
comptime {
|
||||
var bytes: [2]u8 = undefined;
|
||||
std.mem.writeIntBig(u16, &bytes, 0x1234);
|
||||
const result = std.mem.readIntLittle(u16, &bytes);
|
||||
writeIntBig(u16, &bytes, 0x1234);
|
||||
const result = readIntLittle(u16, &bytes);
|
||||
testing.expect(result == 0x3412);
|
||||
}
|
||||
}
|
||||
@ -1053,7 +1053,7 @@ fn testReadIntImpl() void {
|
||||
}
|
||||
}
|
||||
|
||||
test "std.mem.writeIntSlice" {
|
||||
test "writeIntSlice" {
|
||||
testWriteIntImpl();
|
||||
comptime testWriteIntImpl();
|
||||
}
|
||||
@ -1184,7 +1184,7 @@ pub fn reverse(comptime T: type, items: []T) void {
|
||||
}
|
||||
}
|
||||
|
||||
test "std.mem.reverse" {
|
||||
test "reverse" {
|
||||
var arr = []i32{
|
||||
5,
|
||||
3,
|
||||
@ -1211,7 +1211,7 @@ pub fn rotate(comptime T: type, items: []T, amount: usize) void {
|
||||
reverse(T, items);
|
||||
}
|
||||
|
||||
test "std.mem.rotate" {
|
||||
test "rotate" {
|
||||
var arr = []i32{
|
||||
5,
|
||||
3,
|
||||
@ -1296,14 +1296,14 @@ pub fn asBytes(ptr: var) AsBytesReturnType(@typeOf(ptr)) {
|
||||
return @ptrCast(AsBytesReturnType(P), ptr);
|
||||
}
|
||||
|
||||
test "std.mem.asBytes" {
|
||||
test "asBytes" {
|
||||
const deadbeef = u32(0xDEADBEEF);
|
||||
const deadbeef_bytes = switch (builtin.endian) {
|
||||
builtin.Endian.Big => "\xDE\xAD\xBE\xEF",
|
||||
builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
|
||||
};
|
||||
|
||||
testing.expect(std.mem.eql(u8, asBytes(&deadbeef), deadbeef_bytes));
|
||||
testing.expect(eql(u8, asBytes(&deadbeef), deadbeef_bytes));
|
||||
|
||||
var codeface = u32(0xC0DEFACE);
|
||||
for (asBytes(&codeface).*) |*b|
|
||||
@ -1323,7 +1323,7 @@ test "std.mem.asBytes" {
|
||||
.c = 0xDE,
|
||||
.d = 0xA1,
|
||||
};
|
||||
testing.expect(std.mem.eql(u8, asBytes(&inst), "\xBE\xEF\xDE\xA1"));
|
||||
testing.expect(eql(u8, asBytes(&inst), "\xBE\xEF\xDE\xA1"));
|
||||
}
|
||||
|
||||
///Given any value, returns a copy of its bytes in an array.
|
||||
@ -1331,17 +1331,17 @@ pub fn toBytes(value: var) [@sizeOf(@typeOf(value))]u8 {
|
||||
return asBytes(&value).*;
|
||||
}
|
||||
|
||||
test "std.mem.toBytes" {
|
||||
test "toBytes" {
|
||||
var my_bytes = toBytes(u32(0x12345678));
|
||||
switch (builtin.endian) {
|
||||
builtin.Endian.Big => testing.expect(std.mem.eql(u8, my_bytes, "\x12\x34\x56\x78")),
|
||||
builtin.Endian.Little => testing.expect(std.mem.eql(u8, my_bytes, "\x78\x56\x34\x12")),
|
||||
builtin.Endian.Big => testing.expect(eql(u8, my_bytes, "\x12\x34\x56\x78")),
|
||||
builtin.Endian.Little => testing.expect(eql(u8, my_bytes, "\x78\x56\x34\x12")),
|
||||
}
|
||||
|
||||
my_bytes[0] = '\x99';
|
||||
switch (builtin.endian) {
|
||||
builtin.Endian.Big => testing.expect(std.mem.eql(u8, my_bytes, "\x99\x34\x56\x78")),
|
||||
builtin.Endian.Little => testing.expect(std.mem.eql(u8, my_bytes, "\x99\x56\x34\x12")),
|
||||
builtin.Endian.Big => testing.expect(eql(u8, my_bytes, "\x99\x34\x56\x78")),
|
||||
builtin.Endian.Little => testing.expect(eql(u8, my_bytes, "\x99\x56\x34\x12")),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1363,7 +1363,7 @@ pub fn bytesAsValue(comptime T: type, bytes: var) BytesAsValueReturnType(T, @typ
|
||||
return @ptrCast(BytesAsValueReturnType(T, @typeOf(bytes)), bytes);
|
||||
}
|
||||
|
||||
test "std.mem.bytesAsValue" {
|
||||
test "bytesAsValue" {
|
||||
const deadbeef = u32(0xDEADBEEF);
|
||||
const deadbeef_bytes = switch (builtin.endian) {
|
||||
builtin.Endian.Big => "\xDE\xAD\xBE\xEF",
|
||||
@ -1405,7 +1405,7 @@ test "std.mem.bytesAsValue" {
|
||||
pub fn bytesToValue(comptime T: type, bytes: var) T {
|
||||
return bytesAsValue(T, &bytes).*;
|
||||
}
|
||||
test "std.mem.bytesToValue" {
|
||||
test "bytesToValue" {
|
||||
const deadbeef_bytes = switch (builtin.endian) {
|
||||
builtin.Endian.Big => "\xDE\xAD\xBE\xEF",
|
||||
builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
|
||||
@ -1430,25 +1430,25 @@ pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubA
|
||||
return @ptrCast(ReturnType, &ptr[start]);
|
||||
}
|
||||
|
||||
test "std.mem.subArrayPtr" {
|
||||
test "subArrayPtr" {
|
||||
const a1 = "abcdef";
|
||||
const sub1 = subArrayPtr(&a1, 2, 3);
|
||||
testing.expect(std.mem.eql(u8, sub1.*, "cde"));
|
||||
testing.expect(eql(u8, sub1.*, "cde"));
|
||||
|
||||
var a2 = "abcdef";
|
||||
var sub2 = subArrayPtr(&a2, 2, 3);
|
||||
|
||||
testing.expect(std.mem.eql(u8, sub2, "cde"));
|
||||
testing.expect(eql(u8, sub2, "cde"));
|
||||
sub2[1] = 'X';
|
||||
testing.expect(std.mem.eql(u8, a2, "abcXef"));
|
||||
testing.expect(eql(u8, a2, "abcXef"));
|
||||
}
|
||||
|
||||
/// Round an address up to the nearest aligned address
|
||||
pub fn alignForward(addr: usize, alignment: usize) usize {
|
||||
return (addr + alignment - 1) & ~(alignment - 1);
|
||||
return alignBackward(addr + (alignment - 1), alignment);
|
||||
}
|
||||
|
||||
test "std.mem.alignForward" {
|
||||
test "alignForward" {
|
||||
testing.expect(alignForward(1, 1) == 1);
|
||||
testing.expect(alignForward(2, 1) == 2);
|
||||
testing.expect(alignForward(1, 2) == 2);
|
||||
@ -1462,3 +1462,30 @@ test "std.mem.alignForward" {
|
||||
testing.expect(alignForward(16, 8) == 16);
|
||||
testing.expect(alignForward(17, 8) == 24);
|
||||
}
|
||||
|
||||
pub fn alignBackward(addr: usize, alignment: usize) usize {
|
||||
// 000010000 // example addr
|
||||
// 000001111 // subtract 1
|
||||
// 111110000 // binary not
|
||||
return addr & ~(alignment - 1);
|
||||
}
|
||||
|
||||
pub fn isAligned(addr: usize, alignment: usize) bool {
|
||||
return alignBackward(addr, alignment) == addr;
|
||||
}
|
||||
|
||||
test "isAligned" {
|
||||
testing.expect(isAligned(0, 4));
|
||||
testing.expect(isAligned(1, 1));
|
||||
testing.expect(isAligned(2, 1));
|
||||
testing.expect(isAligned(2, 2));
|
||||
testing.expect(!isAligned(2, 4));
|
||||
testing.expect(isAligned(3, 1));
|
||||
testing.expect(!isAligned(3, 2));
|
||||
testing.expect(!isAligned(3, 4));
|
||||
testing.expect(isAligned(4, 4));
|
||||
testing.expect(isAligned(4, 2));
|
||||
testing.expect(isAligned(4, 1));
|
||||
testing.expect(!isAligned(4, 8));
|
||||
testing.expect(!isAligned(4, 16));
|
||||
}
|
||||
|
48
std/os.zig
48
std/os.zig
@ -251,7 +251,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
|
||||
// Linux can return EINVAL when read amount is > 0x7ffff000
|
||||
// See https://github.com/ziglang/zig/pull/743#issuecomment-363158274
|
||||
// TODO audit this. Shawn Landden says that this is not actually true.
|
||||
// if this logic should stay, move it to std.os.linux.sys
|
||||
// if this logic should stay, move it to std.os.linux
|
||||
const max_buf_len = 0x7ffff000;
|
||||
|
||||
var index: usize = 0;
|
||||
@ -260,8 +260,9 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
|
||||
const rc = system.read(fd, buf.ptr + index, want_to_read);
|
||||
switch (errno(rc)) {
|
||||
0 => {
|
||||
index += rc;
|
||||
if (rc == want_to_read) continue;
|
||||
const amt_read = @intCast(usize, rc);
|
||||
index += amt_read;
|
||||
if (amt_read == want_to_read) continue;
|
||||
// Read returned less than buf.len.
|
||||
return index;
|
||||
},
|
||||
@ -374,7 +375,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!void {
|
||||
// Linux can return EINVAL when write amount is > 0x7ffff000
|
||||
// See https://github.com/ziglang/zig/pull/743#issuecomment-363165856
|
||||
// TODO audit this. Shawn Landden says that this is not actually true.
|
||||
// if this logic should stay, move it to std.os.linux.sys
|
||||
// if this logic should stay, move it to std.os.linux
|
||||
const max_bytes_len = 0x7ffff000;
|
||||
|
||||
var index: usize = 0;
|
||||
@ -383,7 +384,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!void {
|
||||
const rc = system.write(fd, bytes.ptr + index, amt_to_write);
|
||||
switch (errno(rc)) {
|
||||
0 => {
|
||||
index += rc;
|
||||
index += @intCast(usize, rc);
|
||||
continue;
|
||||
},
|
||||
EINTR => continue,
|
||||
@ -1863,14 +1864,10 @@ pub const MProtectError = error{
|
||||
Unexpected,
|
||||
};
|
||||
|
||||
/// address and length must be page-aligned
|
||||
pub fn mprotect(address: usize, length: usize, protection: u32) MProtectError!void {
|
||||
const negative_page_size = @bitCast(usize, -isize(mem.page_size));
|
||||
const aligned_address = address & negative_page_size;
|
||||
const aligned_end = (address + length + mem.page_size - 1) & negative_page_size;
|
||||
assert(address == aligned_address);
|
||||
assert(length == aligned_end - aligned_address);
|
||||
switch (errno(system.mprotect(address, length, protection))) {
|
||||
/// `memory.len` must be page-aligned.
|
||||
pub fn mprotect(memory: [*]align(mem.page_size) u8, protection: u32) MProtectError!void {
|
||||
assert(mem.isAligned(memory.len, mem.page_size));
|
||||
switch (errno(system.mprotect(memory.ptr, memory.len, protection))) {
|
||||
0 => return,
|
||||
EINVAL => unreachable,
|
||||
EACCES => return error.AccessDenied,
|
||||
@ -1906,17 +1903,26 @@ pub const MMapError = error{
|
||||
|
||||
/// Map files or devices into memory.
|
||||
/// Use of a mapped region can result in these signals:
|
||||
/// `length` must be page-aligned.
|
||||
/// * SIGSEGV - Attempted write into a region mapped as read-only.
|
||||
/// * SIGBUS - Attempted access to a portion of the buffer that does not correspond to the file
|
||||
pub fn mmap(address: ?[*]u8, length: usize, prot: u32, flags: u32, fd: fd_t, offset: isize) MMapError!usize {
|
||||
pub fn mmap(
|
||||
ptr: ?[*]align(mem.page_size) u8,
|
||||
length: usize,
|
||||
prot: u32,
|
||||
flags: u32,
|
||||
fd: fd_t,
|
||||
offset: isize,
|
||||
) MMapError![]align(mem.page_size) u8 {
|
||||
assert(mem.isAligned(length, mem.page_size));
|
||||
const err = if (builtin.link_libc) blk: {
|
||||
const rc = system.mmap(address, length, prot, flags, fd, offset);
|
||||
if (rc != system.MMAP_FAILED) return rc;
|
||||
break :blk system._errno().*;
|
||||
const rc = std.c.mmap(ptr, length, prot, flags, fd, offset);
|
||||
if (rc != MAP_FAILED) return @ptrCast([*]align(mem.page_size) u8, @alignCast(mem.page_size, rc))[0..length];
|
||||
break :blk @intCast(usize, system._errno().*);
|
||||
} else blk: {
|
||||
const rc = system.mmap(address, length, prot, flags, fd, offset);
|
||||
const rc = system.mmap(ptr, length, prot, flags, fd, offset);
|
||||
const err = errno(rc);
|
||||
if (err == 0) return rc;
|
||||
if (err == 0) return @intToPtr([*]align(mem.page_size) u8, rc)[0..length];
|
||||
break :blk err;
|
||||
};
|
||||
switch (err) {
|
||||
@ -1940,8 +1946,8 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: u32, flags: u32, fd: fd_t, off
|
||||
/// Zig's munmap function does not, for two reasons:
|
||||
/// * It violates the Zig principle that resource deallocation must succeed.
|
||||
/// * The Windows function, VirtualFree, has this restriction.
|
||||
pub fn munmap(address: usize, length: usize) void {
|
||||
switch (errno(system.munmap(address, length))) {
|
||||
pub fn munmap(memory: []align(mem.page_size) u8) void {
|
||||
switch (errno(system.munmap(memory.ptr, memory.len))) {
|
||||
0 => return,
|
||||
EINVAL => unreachable, // Invalid parameters.
|
||||
ENOMEM => unreachable, // Attempted to unmap a region in the middle of an existing mapping.
|
||||
|
@ -1,4 +1,5 @@
|
||||
const std = @import("../../std.zig");
|
||||
const maxInt = std.math.maxInt;
|
||||
|
||||
pub use @import("linux/errno.zig");
|
||||
pub use switch (builtin.arch) {
|
||||
@ -39,7 +40,7 @@ pub const PROT_EXEC = 4;
|
||||
pub const PROT_GROWSDOWN = 0x01000000;
|
||||
pub const PROT_GROWSUP = 0x02000000;
|
||||
|
||||
pub const MAP_FAILED = maxInt(usize);
|
||||
pub const MAP_FAILED = @intToPtr(*c_void, maxInt(usize));
|
||||
pub const MAP_SHARED = 0x01;
|
||||
pub const MAP_PRIVATE = 0x02;
|
||||
pub const MAP_TYPE = 0x0f;
|
||||
|
@ -173,12 +173,12 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, of
|
||||
return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset));
|
||||
}
|
||||
|
||||
pub fn mprotect(address: usize, length: usize, protection: usize) usize {
|
||||
return syscall3(SYS_mprotect, address, length, protection);
|
||||
pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize {
|
||||
return syscall3(SYS_mprotect, @ptrToInt(address), length, protection);
|
||||
}
|
||||
|
||||
pub fn munmap(address: usize, length: usize) usize {
|
||||
return syscall2(SYS_munmap, address, length);
|
||||
pub fn munmap(address: [*]const u8, length: usize) usize {
|
||||
return syscall2(SYS_munmap, @ptrToInt(address), length);
|
||||
}
|
||||
|
||||
pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
|
||||
|
@ -237,7 +237,7 @@ pub fn allocateTLS(size: usize) usize {
|
||||
return @ptrToInt(&main_thread_tls_buffer);
|
||||
}
|
||||
|
||||
const addr = os.mmap(
|
||||
const slice = os.mmap(
|
||||
null,
|
||||
size,
|
||||
os.PROT_READ | os.PROT_WRITE,
|
||||
@ -246,5 +246,5 @@ pub fn allocateTLS(size: usize) usize {
|
||||
0,
|
||||
) catch @panic("out of memory");
|
||||
|
||||
return addr;
|
||||
return @ptrToInt(slice.ptr);
|
||||
}
|
||||
|
@ -318,7 +318,7 @@ fn testCastPtrOfArrayToSliceAndPtr() void {
|
||||
test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
|
||||
const window_name = [1][*]const u8{c"window name"};
|
||||
const x: [*]const ?[*]const u8 = &window_name;
|
||||
expect(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name"));
|
||||
expect(mem.eql(u8, std.mem.toSliceConst(u8, x[0].?), "window name"));
|
||||
}
|
||||
|
||||
test "@intCast comptime_int" {
|
||||
|
@ -2,7 +2,6 @@ const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqualSlices = std.testing.expectEqualSlices;
|
||||
const mem = std.mem;
|
||||
const cstr = std.cstr;
|
||||
const builtin = @import("builtin");
|
||||
const maxInt = std.math.maxInt;
|
||||
|
||||
@ -210,7 +209,7 @@ test "multiline C string" {
|
||||
c\\three
|
||||
;
|
||||
const s2 = c"one\ntwo)\nthree";
|
||||
expect(cstr.cmp(s1, s2) == 0);
|
||||
expect(std.cstr.cmp(s1, s2) == 0);
|
||||
}
|
||||
|
||||
test "type equality" {
|
||||
@ -363,7 +362,7 @@ test "C string concatenation" {
|
||||
const a = c"OK" ++ c" IT " ++ c"WORKED";
|
||||
const b = c"OK IT WORKED";
|
||||
|
||||
const len = cstr.len(b);
|
||||
const len = mem.len(u8, b);
|
||||
const len_with_null = len + 1;
|
||||
{
|
||||
var i: u32 = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user