authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-12 10:43:26+02:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2026-10-12 10:43:26+02:00
log04624c10801cd9d10971a634f3b25db3d3def87e
treeb0cc31a05c16f750e87ba12c754ecfd3d7053be1
parent12816808f6853cdda1acf43b19f9aac9e339cb20
signature Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.os.linux.tls: manual backport of https://codeberg.org/ziglang/zig/pulls/37186


1 files changed, 42 insertions(+), 35 deletions(-)

lib/std/os/linux/tls.zig+42-35
......@@ -142,30 +142,14 @@ const current_dtv_offset = switch (native_arch) {
142142
143143/// Per-thread storage for the ELF TLS ABI.
144144const AbiTcb = switch (current_variant) {
145 .I_original, .I_modified => switch (native_arch) {
146 .aarch64,
147 .aarch64_be,
148 .alpha,
149 .arm,
150 .armeb,
151 .hppa,
152 .microblaze,
153 .microblazeel,
154 .sh,
155 .sheb,
156 .thumb,
157 .thumbeb,
158 .xtensa,
159 .xtensaeb,
160 => extern struct {
161 /// This is offset by `current_dtv_offset`.
162 dtv: usize,
163 _reserved: ?*anyopaque,
164 },
165 else => extern struct {
166 /// This is offset by `current_dtv_offset`.
167 dtv: usize,
168 },
145 .I_original => extern struct {
146 /// This is offset by `current_dtv_offset`.
147 dtv: usize,
148 _reserved: ?*anyopaque,
149 },
150 .I_modified => extern struct {
151 /// This is offset by `current_dtv_offset`.
152 dtv: usize,
169153 },
170154 .II => extern struct {
171155 /// This is self-referential.
......@@ -500,7 +484,7 @@ fn computeAreaDesc(phdrs: []elf.ElfN.Phdr) void {
500484 var block_size: usize = undefined;
501485
502486 if (tls_phdr) |phdr| {
503 align_factor = phdr.@"align";
487 align_factor = @max(phdr.@"align", 1);
504488
505489 // The effective size in memory is represented by `memsz`; the length of the data stored
506490 // in the `PT.TLS` segment is `filesz` and may be less than the former.
......@@ -727,6 +711,11 @@ comptime {
727711 // the linker should be able to relax every TLS access to the LE model and therefore
728712 // eliminate all calls to this function, but that isn't guaranteed.
729713 const Fns = struct {
714 fn __m68k_read_tp() callconv(.c) ?*anyopaque {
715 comptime assert(native_arch == .m68k);
716
717 return @ptrFromInt(getThreadPointer());
718 }
730719 const TlsIndex = switch (native_arch) {
731720 .x86_64 => extern struct { module: u64, offset: u64 }, // Even for x32...
732721 else => extern struct { module: usize, offset: usize }, // ...but not MIPS N32!
......@@ -736,14 +725,25 @@ comptime {
736725
737726 assert(ti.module == 1); // The executable's module ID is always 1
738727 const tp = getThreadPointer();
739 const block: [*]u8 = switch (current_variant) {
740 .I_original => @ptrFromInt(tp -% area_desc.abi_tcb.offset +% area_desc.block.offset),
741 .I_modified => @ptrFromInt(tp -% current_tp_offset),
728 const block = switch (current_variant) {
729 .I_original => tp -% area_desc.abi_tcb.offset +% area_desc.block.offset,
730 .I_modified => tp -% current_tp_offset,
742731 // The `.I_original` approach would also work for `.II`, but there is an
743732 // alternative strategy which is one less operation:
744 .II => @ptrFromInt(tp -% area_desc.block.size),
733 .II => tp -% area_desc.abi_tcb.offset,
745734 };
746 return block[@intCast(ti.offset)..];
735 return @ptrFromInt(block +% current_dtv_offset +% @as(usize, @intCast(ti.offset)));
736 }
737 fn ___tls_get_addr() callconv(.naked) *anyopaque {
738 comptime assert(native_arch == .x86);
739
740 // We receive the `TlsIndex` pointer in eax.
741 comptime assert(@sizeOf(AbiTcb) + @sizeOf(ZigTcb) + @offsetOf(Dtv, "tls_block") == 12);
742 asm volatile (
743 \\ mov 4(%%eax), %%eax
744 \\ add %%gs:12, %%eax
745 \\ ret
746 );
747747 }
748748 fn __tls_get_offset() callconv(.naked) noreturn {
749749 comptime assert(native_arch == .s390x);
......@@ -752,18 +752,25 @@ comptime {
752752 asm volatile (
753753 \\ la %%r1, 0(%%r12, %%r2)
754754 \\ lg %%r2, 8(%%r1)
755 \\ lgrl %%r0, %[block_size]
755 \\ lgrl %%r0, %[abi_tcb_offset]
756756 \\ sgr %%r2, %%r0
757757 \\ br %%r14
758758 :
759 : [block_size] "s" (&area_desc.block.size),
759 : [abi_tcb_offset] "s" (&area_desc.abi_tcb.offset),
760760 );
761761 }
762762 };
763763
764 if (native_arch == .s390x)
765 @export(&Fns.__tls_get_offset, .{ .name = "__tls_get_offset" })
766 else
764 if (native_arch == .s390x) {
765 @export(&Fns.__tls_get_offset, .{ .name = "__tls_get_offset" });
766 } else {
767767 @export(&Fns.__tls_get_addr, .{ .name = "__tls_get_addr" });
768 if (native_arch == .m68k) {
769 @export(&Fns.__m68k_read_tp, .{ .name = "__m68k_read_tp" });
770 }
771 if (native_arch == .x86) {
772 @export(&Fns.___tls_get_addr, .{ .name = "___tls_get_addr" });
773 }
774 }
768775 }
769776}