zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 89ffb5819703c81514e4f29d2cadb5b74ea1f840 (tree)
parent d2602b442e7cdea2e74584f9529917d7a53625fd
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Wed,  6 Feb 2019 18:32:41 -0500

implement Thread Local Storage on Windows

Diffstat:
MCMakeLists.txt | 1+
Msrc/codegen.cpp | 14++++++++------
Mstd/os/windows/index.zig | 19++++++++++++++++++-
Mstd/os/windows/kernel32.zig | 4++++
Astd/os/windows/tls.zig | 36++++++++++++++++++++++++++++++++++++
Mstd/special/bootstrap.zig | 4+++-
6 files changed, 70 insertions(+), 8 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt @@ -596,6 +596,7 @@ set(ZIG_STD_FILES "os/windows/ntdll.zig" "os/windows/ole32.zig" "os/windows/shell32.zig" + "os/windows/tls.zig" "os/windows/util.zig" "os/zen.zig" "pdb.zig" diff --git a/src/codegen.cpp b/src/codegen.cpp @@ -6365,6 +6365,12 @@ static void validate_inline_fns(CodeGen *g) { report_errors_and_maybe_exit(g); } +static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) { + if (var->is_thread_local && !g->is_single_threaded) { + LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel); + } +} + static void do_code_gen(CodeGen *g) { assert(!g->errors.length); @@ -6449,9 +6455,7 @@ static void do_code_gen(CodeGen *g) { maybe_import_dll(g, global_value, GlobalLinkageIdStrong); LLVMSetAlignment(global_value, var->align_bytes); LLVMSetGlobalConstant(global_value, var->gen_is_const); - if (var->is_thread_local && !g->is_single_threaded) { - LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel); - } + set_global_tls(g, var, global_value); } } else { bool exported = (var->linkage == VarLinkageExport); @@ -6477,9 +6481,7 @@ static void do_code_gen(CodeGen *g) { } LLVMSetGlobalConstant(global_value, var->gen_is_const); - if (var->is_thread_local && !g->is_single_threaded) { - LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel); - } + set_global_tls(g, var, global_value); } var->value_ref = global_value; diff --git a/std/os/windows/index.zig b/std/os/windows/index.zig @@ -49,7 +49,10 @@ pub const UNICODE = false; pub const WCHAR = u16; pub const WORD = u16; pub const LARGE_INTEGER = i64; -pub const LONG = c_long; +pub const ULONG = u32; +pub const LONG = i32; +pub const ULONGLONG = u64; +pub const LONGLONG = i64; pub const TRUE = 1; pub const FALSE = 0; @@ -380,3 +383,17 @@ pub const COORD = extern struct { }; pub const CREATE_UNICODE_ENVIRONMENT = 1024; + +pub const TLS_OUT_OF_INDEXES = 4294967295; +pub const IMAGE_TLS_DIRECTORY = extern struct { + StartAddressOfRawData: usize, + EndAddressOfRawData: usize, + AddressOfIndex: usize, + AddressOfCallBacks: usize, + SizeOfZeroFill: u32, + Characteristics: u32, +}; +pub const IMAGE_TLS_DIRECTORY64 = IMAGE_TLS_DIRECTORY; +pub const IMAGE_TLS_DIRECTORY32 = IMAGE_TLS_DIRECTORY; + +pub const PIMAGE_TLS_CALLBACK = ?extern fn(PVOID, DWORD, PVOID) void; diff --git a/std/os/windows/kernel32.zig b/std/os/windows/kernel32.zig @@ -164,6 +164,10 @@ pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD) void; pub extern "kernel32" stdcallcc fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) BOOL; +pub extern "kernel32" stdcallcc fn TlsAlloc() DWORD; + +pub extern "kernel32" stdcallcc fn TlsFree(dwTlsIndex: DWORD) BOOL; + pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) DWORD; pub extern "kernel32" stdcallcc fn WriteFile( diff --git a/std/os/windows/tls.zig b/std/os/windows/tls.zig @@ -0,0 +1,36 @@ +const std = @import("../../index.zig"); + +export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES; +export var _tls_start: u8 linksection(".tls") = 0; +export var _tls_end: u8 linksection(".tls$ZZZ") = 0; +export var __xl_a: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") = null; +export var __xl_z: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null; + +// TODO this is how I would like it to be expressed +// TODO also note, ReactOS has a +1 on StartAddressOfRawData and AddressOfCallBacks. Investigate +// why they do that. +//export const _tls_used linksection(".rdata$T") = std.os.windows.IMAGE_TLS_DIRECTORY { +// .StartAddressOfRawData = @ptrToInt(&_tls_start), +// .EndAddressOfRawData = @ptrToInt(&_tls_end), +// .AddressOfIndex = @ptrToInt(&_tls_index), +// .AddressOfCallBacks = @ptrToInt(__xl_a), +// .SizeOfZeroFill = 0, +// .Characteristics = 0, +//}; +// This is the workaround because we can't do @ptrToInt at comptime like that. +pub const IMAGE_TLS_DIRECTORY = extern struct { + StartAddressOfRawData: *c_void, + EndAddressOfRawData: *c_void, + AddressOfIndex: *c_void, + AddressOfCallBacks: *c_void, + SizeOfZeroFill: u32, + Characteristics: u32, +}; +export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY { + .StartAddressOfRawData = &_tls_start, + .EndAddressOfRawData = &_tls_end, + .AddressOfIndex = &_tls_index, + .AddressOfCallBacks = &__xl_a, + .SizeOfZeroFill = 0, + .Characteristics = 0, +}; diff --git a/std/special/bootstrap.zig b/std/special/bootstrap.zig @@ -45,7 +45,9 @@ nakedcc fn _start() noreturn { extern fn WinMainCRTStartup() noreturn { @setAlignStack(16); - + if (!builtin.single_threaded) { + _ = @import("../os/windows/tls.zig"); + } std.os.windows.ExitProcess(callMain()); }