Commit 41832aa1e6
Changed files (2)
lib
std
os
linux
lib/std/os/linux/x86_64.zig
@@ -395,3 +395,71 @@ pub const ucontext_t = extern struct {
sigmask: sigset_t,
fpregs_mem: [64]usize,
};
+
+fn gpRegisterOffset(comptime reg_index: comptime_int) usize {
+ return @offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "gregs") + @sizeOf(usize) * reg_index;
+}
+
+pub inline fn getcontext(context: *ucontext_t) usize {
+ asm volatile (
+ \\ movq %%r8, (%[r8_offset])(%[context])
+ \\ movq %%r9, (%[r9_offset])(%[context])
+ \\ movq %%r10, (%[r10_offset])(%[context])
+ \\ movq %%r11, (%[r11_offset])(%[context])
+ \\ movq %%r12, (%[r12_offset])(%[context])
+ \\ movq %%r13, (%[r13_offset])(%[context])
+ \\ movq %%r14, (%[r14_offset])(%[context])
+ \\ movq %%r15, (%[r15_offset])(%[context])
+ \\ movq %%rdi, (%[rdi_offset])(%[context])
+ \\ movq %%rsi, (%[rsi_offset])(%[context])
+ \\ movq %%rbp, (%[rbp_offset])(%[context])
+ \\ movq %%rbx, (%[rbx_offset])(%[context])
+ \\ movq %%rdx, (%[rdx_offset])(%[context])
+ \\ movq %%rax, (%[rax_offset])(%[context])
+ \\ movq %%rcx, (%[rcx_offset])(%[context])
+ \\ movq %%rsp, (%[rsp_offset])(%[context])
+ \\ leaq (%%rip), %%rcx
+ \\ movq %%rcx, (%[rip_offset])(%[context])
+ \\ pushfq
+ \\ popq (%[efl_offset])(%[context])
+ \\ leaq (%[fpmem_offset])(%[context]), %%rcx
+ \\ movq %%rcx, (%[fpstate_offset])(%[context])
+ \\ fnstenv (%%rcx)
+ \\ stmxcsr (%[mxcsr_offset])(%[context])
+ :
+ : [context] "{rdi}" (context),
+ [r8_offset] "p" (comptime gpRegisterOffset(REG.R8)),
+ [r9_offset] "p" (comptime gpRegisterOffset(REG.R9)),
+ [r10_offset] "p" (comptime gpRegisterOffset(REG.R10)),
+ [r11_offset] "p" (comptime gpRegisterOffset(REG.R11)),
+ [r12_offset] "p" (comptime gpRegisterOffset(REG.R12)),
+ [r13_offset] "p" (comptime gpRegisterOffset(REG.R13)),
+ [r14_offset] "p" (comptime gpRegisterOffset(REG.R14)),
+ [r15_offset] "p" (comptime gpRegisterOffset(REG.R15)),
+ [rdi_offset] "p" (comptime gpRegisterOffset(REG.RDI)),
+ [rsi_offset] "p" (comptime gpRegisterOffset(REG.RSI)),
+ [rbp_offset] "p" (comptime gpRegisterOffset(REG.RBP)),
+ [rbx_offset] "p" (comptime gpRegisterOffset(REG.RBX)),
+ [rdx_offset] "p" (comptime gpRegisterOffset(REG.RDX)),
+ [rax_offset] "p" (comptime gpRegisterOffset(REG.RAX)),
+ [rcx_offset] "p" (comptime gpRegisterOffset(REG.RCX)),
+ [rsp_offset] "p" (comptime gpRegisterOffset(REG.RSP)),
+ [rip_offset] "p" (comptime gpRegisterOffset(REG.RIP)),
+ [efl_offset] "p" (comptime gpRegisterOffset(REG.EFL)),
+ [fpstate_offset] "p" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")),
+ [fpmem_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem")),
+ [mxcsr_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem") + @offsetOf(fpstate, "mxcsr")),
+ : "memory", "rcx"
+ );
+
+ // TODO: Read GS/FS registers?
+
+ // TODO: `flags` isn't present in the getcontext man page, figure out what to write here
+ context.flags = 0;
+ context.link = null;
+
+ const altstack_result = linux.sigaltstack(null, &context.stack);
+ if (altstack_result != 0) return altstack_result;
+
+ return linux.sigprocmask(0, null, &context.sigmask);
+}
lib/std/os/linux.zig
@@ -86,6 +86,7 @@ pub const timeval = arch_bits.timeval;
pub const timezone = arch_bits.timezone;
pub const ucontext_t = arch_bits.ucontext_t;
pub const user_desc = arch_bits.user_desc;
+pub const getcontext = arch_bits.getcontext;
pub const tls = @import("linux/tls.zig");
pub const pie = @import("linux/start_pie.zig");
@@ -4694,7 +4695,7 @@ else
/// processes.
RTPRIO,
- /// Maximum CPU time in µs that a process scheduled under a real-time
+ /// Maximum CPU time in µs that a process scheduled under a real-time
/// scheduling policy may consume without making a blocking system
/// call before being forcibly descheduled.
RTTIME,