Commit 89ffb58197

Andrew Kelley <andrew@ziglang.org>
2019-02-07 00:32:41
implement Thread Local Storage on Windows
1 parent d2602b4
Changed files (6)
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;
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;
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(
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,
+};
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());
 }
 
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"