aboutsummaryrefslogtreecommitdiff
path: root/lib/std/os
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-12-18 23:57:46 -0500
committerGitHub <noreply@github.com>2020-12-18 23:57:46 -0500
commit506af7e52e0985b410ea089bf5fa3247ab2377cb (patch)
tree2ec26d70f41a1382b736b606ebfa094ace62573e /lib/std/os
parentce65533985caa9e2da567948e36d7d4ba0185005 (diff)
parentf416535768fc30195cad6cd481f73fd1e80082aa (diff)
downloadzig-506af7e52e0985b410ea089bf5fa3247ab2377cb.tar.gz
zig-506af7e52e0985b410ea089bf5fa3247ab2377cb.zip
Merge pull request #7482 from ziglang/tlcsprng
std: introduce a thread-local CSPRNG for general use
Diffstat (limited to 'lib/std/os')
-rw-r--r--lib/std/os/bits/linux.zig22
-rw-r--r--lib/std/os/linux.zig4
-rw-r--r--lib/std/os/linux/tls.zig39
3 files changed, 50 insertions, 15 deletions
diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig
index 583240fd4e..2bcfc89ecf 100644
--- a/lib/std/os/bits/linux.zig
+++ b/lib/std/os/bits/linux.zig
@@ -2045,3 +2045,25 @@ pub const rlimit = extern struct {
/// Hard limit
max: rlim_t,
};
+
+pub const MADV_NORMAL = 0;
+pub const MADV_RANDOM = 1;
+pub const MADV_SEQUENTIAL = 2;
+pub const MADV_WILLNEED = 3;
+pub const MADV_DONTNEED = 4;
+pub const MADV_FREE = 8;
+pub const MADV_REMOVE = 9;
+pub const MADV_DONTFORK = 10;
+pub const MADV_DOFORK = 11;
+pub const MADV_MERGEABLE = 12;
+pub const MADV_UNMERGEABLE = 13;
+pub const MADV_HUGEPAGE = 14;
+pub const MADV_NOHUGEPAGE = 15;
+pub const MADV_DONTDUMP = 16;
+pub const MADV_DODUMP = 17;
+pub const MADV_WIPEONFORK = 18;
+pub const MADV_KEEPONFORK = 19;
+pub const MADV_COLD = 20;
+pub const MADV_PAGEOUT = 21;
+pub const MADV_HWPOISON = 100;
+pub const MADV_SOFT_OFFLINE = 101;
diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
index f840f6a255..f252a08fc9 100644
--- a/lib/std/os/linux.zig
+++ b/lib/std/os/linux.zig
@@ -1351,6 +1351,10 @@ pub fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: ?*const rlimit,
);
}
+pub fn madvise(address: [*]u8, len: usize, advice: u32) usize {
+ return syscall3(.madvise, @ptrToInt(address), len, advice);
+}
+
test "" {
if (builtin.os.tag == .linux) {
_ = @import("linux/test.zig");
diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig
index d956266114..6d61e60e95 100644
--- a/lib/std/os/linux/tls.zig
+++ b/lib/std/os/linux/tls.zig
@@ -327,34 +327,43 @@ pub fn prepareTLS(area: []u8) usize {
if (tls_tp_points_past_tcb) tls_image.data_offset else tls_image.tcb_offset;
}
-var main_thread_tls_buffer: [256]u8 = undefined;
+// The main motivation for the size chosen here is this is how much ends up being
+// requested for the thread local variables of the std.crypto.random implementation.
+// I'm not sure why it ends up being so much; the struct itself is only 64 bytes.
+// I think it has to do with being page aligned and LLVM or LLD is not smart enough
+// to lay out the TLS data in a space conserving way. Anyway I think it's fine
+// because it's less than 3 pages of memory, and putting it in the ELF like this
+// is equivalent to moving the mmap call below into the kernel, avoiding syscall
+// overhead.
+var main_thread_tls_buffer: [0x2100]u8 align(mem.page_size) = undefined;
pub fn initStaticTLS() void {
initTLS();
- const alloc_tls_area: []u8 = blk: {
- const full_alloc_size = tls_image.alloc_size + tls_image.alloc_align - 1;
-
+ const tls_area = blk: {
// Fast path for the common case where the TLS data is really small,
- // avoid an allocation and use our local buffer
- if (full_alloc_size < main_thread_tls_buffer.len)
- break :blk main_thread_tls_buffer[0..];
+ // avoid an allocation and use our local buffer.
+ if (tls_image.alloc_align <= mem.page_size and
+ tls_image.alloc_size <= main_thread_tls_buffer.len)
+ {
+ break :blk main_thread_tls_buffer[0..tls_image.alloc_size];
+ }
- break :blk os.mmap(
+ const alloc_tls_area = os.mmap(
null,
- full_alloc_size,
+ tls_image.alloc_size + tls_image.alloc_align - 1,
os.PROT_READ | os.PROT_WRITE,
os.MAP_PRIVATE | os.MAP_ANONYMOUS,
-1,
0,
) catch os.abort();
- };
- // Make sure the slice is correctly aligned
- const begin_addr = @ptrToInt(alloc_tls_area.ptr);
- const begin_aligned_addr = mem.alignForward(begin_addr, tls_image.alloc_align);
- const start = begin_aligned_addr - begin_addr;
- const tls_area = alloc_tls_area[start .. start + tls_image.alloc_size];
+ // Make sure the slice is correctly aligned.
+ const begin_addr = @ptrToInt(alloc_tls_area.ptr);
+ const begin_aligned_addr = mem.alignForward(begin_addr, tls_image.alloc_align);
+ const start = begin_aligned_addr - begin_addr;
+ break :blk alloc_tls_area[start .. start + tls_image.alloc_size];
+ };
const tp_value = prepareTLS(tls_area);
setThreadPointer(tp_value);