//! Opting the process out of transparent huge pages. //! //! With THP set to `always`, the kernel backs any 2 MiB-aligned anonymous //! region with a huge page on first touch. Each worker thread's stack mapping //! qualifies, so a thread that touches a few KiB of stack can hold 2 MiB //! resident, and `std.Io.Threaded` never retires a worker: one burst on such a //! host left about 40 of 200 workers at 2 MiB each. nxdns's memory is sized //! for small pages, so the whole process opts out instead of chasing each //! mapping. const std = @import("std"); const linux = std.os.linux; pub const DisableError = error{ /// A kernel older than 3.15, which has no such switch. Unsupported, Unexpected, }; /// Sets `PR_SET_THP_DISABLE`, which covers every mapping of the process, /// existing and future, and is inherited across `fork`. pub fn disable() DisableError!void { const rc = linux.prctl(@intFromEnum(linux.PR.SET_THP_DISABLE), 1, 0, 0, 0); switch (linux.errno(rc)) { .SUCCESS => {}, .INVAL => return error.Unsupported, else => return error.Unexpected, } } test "disable takes effect for the process" { disable() catch |err| switch (err) { // qemu-user, which runs the aarch64 suite, rejects the option the way // a pre-3.15 kernel does. error.Unsupported => return error.SkipZigTest, error.Unexpected => return err, }; const rc = linux.prctl(@intFromEnum(linux.PR.GET_THP_DISABLE), 0, 0, 0, 0); try std.testing.expectEqual(linux.E.SUCCESS, linux.errno(rc)); try std.testing.expectEqual(@as(usize, 1), rc); }