authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-06 18:32:41-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-06 18:32:41-05:00
log89ffb5819703c81514e4f29d2cadb5b74ea1f840
tree455eda3ef65b2a2f08f292586b219468aa755f06
parentd2602b442e7cdea2e74584f9529917d7a53625fd

implement Thread Local Storage on Windows


6 files changed, 70 insertions(+), 8 deletions(-)

CMakeLists.txt+1
......@@ -596,6 +596,7 @@ set(ZIG_STD_FILES
596596 "os/windows/ntdll.zig"
597597 "os/windows/ole32.zig"
598598 "os/windows/shell32.zig"
599 "os/windows/tls.zig"
599600 "os/windows/util.zig"
600601 "os/zen.zig"
601602 "pdb.zig"
src/codegen.cpp+8-6
......@@ -6365,6 +6365,12 @@ static void validate_inline_fns(CodeGen *g) {
63656365 report_errors_and_maybe_exit(g);
63666366}
63676367
6368static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
6369 if (var->is_thread_local && !g->is_single_threaded) {
6370 LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
6371 }
6372}
6373
63686374static void do_code_gen(CodeGen *g) {
63696375 assert(!g->errors.length);
63706376
......@@ -6449,9 +6455,7 @@ static void do_code_gen(CodeGen *g) {
64496455 maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
64506456 LLVMSetAlignment(global_value, var->align_bytes);
64516457 LLVMSetGlobalConstant(global_value, var->gen_is_const);
6452 if (var->is_thread_local && !g->is_single_threaded) {
6453 LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
6454 }
6458 set_global_tls(g, var, global_value);
64556459 }
64566460 } else {
64576461 bool exported = (var->linkage == VarLinkageExport);
......@@ -6477,9 +6481,7 @@ static void do_code_gen(CodeGen *g) {
64776481 }
64786482
64796483 LLVMSetGlobalConstant(global_value, var->gen_is_const);
6480 if (var->is_thread_local && !g->is_single_threaded) {
6481 LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
6482 }
6484 set_global_tls(g, var, global_value);
64836485 }
64846486
64856487 var->value_ref = global_value;
std/os/windows/index.zig+18-1
......@@ -49,7 +49,10 @@ pub const UNICODE = false;
4949pub const WCHAR = u16;
5050pub const WORD = u16;
5151pub const LARGE_INTEGER = i64;
52pub const LONG = c_long;
52pub const ULONG = u32;
53pub const LONG = i32;
54pub const ULONGLONG = u64;
55pub const LONGLONG = i64;
5356
5457pub const TRUE = 1;
5558pub const FALSE = 0;
......@@ -380,3 +383,17 @@ pub const COORD = extern struct {
380383};
381384
382385pub const CREATE_UNICODE_ENVIRONMENT = 1024;
386
387pub const TLS_OUT_OF_INDEXES = 4294967295;
388pub const IMAGE_TLS_DIRECTORY = extern struct {
389 StartAddressOfRawData: usize,
390 EndAddressOfRawData: usize,
391 AddressOfIndex: usize,
392 AddressOfCallBacks: usize,
393 SizeOfZeroFill: u32,
394 Characteristics: u32,
395};
396pub const IMAGE_TLS_DIRECTORY64 = IMAGE_TLS_DIRECTORY;
397pub const IMAGE_TLS_DIRECTORY32 = IMAGE_TLS_DIRECTORY;
398
399pub const PIMAGE_TLS_CALLBACK = ?extern fn(PVOID, DWORD, PVOID) void;
std/os/windows/kernel32.zig+4
......@@ -164,6 +164,10 @@ pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD) void;
164164
165165pub extern "kernel32" stdcallcc fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) BOOL;
166166
167pub extern "kernel32" stdcallcc fn TlsAlloc() DWORD;
168
169pub extern "kernel32" stdcallcc fn TlsFree(dwTlsIndex: DWORD) BOOL;
170
167171pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) DWORD;
168172
169173pub extern "kernel32" stdcallcc fn WriteFile(
std/os/windows/tls.zig created+36
......@@ -0,0 +1,36 @@
1const std = @import("../../index.zig");
2
3export var _tls_index: u32 = std.os.windows.TLS_OUT_OF_INDEXES;
4export var _tls_start: u8 linksection(".tls") = 0;
5export var _tls_end: u8 linksection(".tls$ZZZ") = 0;
6export var __xl_a: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") = null;
7export var __xl_z: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null;
8
9// TODO this is how I would like it to be expressed
10// TODO also note, ReactOS has a +1 on StartAddressOfRawData and AddressOfCallBacks. Investigate
11// why they do that.
12//export const _tls_used linksection(".rdata$T") = std.os.windows.IMAGE_TLS_DIRECTORY {
13// .StartAddressOfRawData = @ptrToInt(&_tls_start),
14// .EndAddressOfRawData = @ptrToInt(&_tls_end),
15// .AddressOfIndex = @ptrToInt(&_tls_index),
16// .AddressOfCallBacks = @ptrToInt(__xl_a),
17// .SizeOfZeroFill = 0,
18// .Characteristics = 0,
19//};
20// This is the workaround because we can't do @ptrToInt at comptime like that.
21pub const IMAGE_TLS_DIRECTORY = extern struct {
22 StartAddressOfRawData: *c_void,
23 EndAddressOfRawData: *c_void,
24 AddressOfIndex: *c_void,
25 AddressOfCallBacks: *c_void,
26 SizeOfZeroFill: u32,
27 Characteristics: u32,
28};
29export const _tls_used linksection(".rdata$T") = IMAGE_TLS_DIRECTORY {
30 .StartAddressOfRawData = &_tls_start,
31 .EndAddressOfRawData = &_tls_end,
32 .AddressOfIndex = &_tls_index,
33 .AddressOfCallBacks = &__xl_a,
34 .SizeOfZeroFill = 0,
35 .Characteristics = 0,
36};
std/special/bootstrap.zig+3-1
......@@ -45,7 +45,9 @@ nakedcc fn _start() noreturn {
4545
4646extern fn WinMainCRTStartup() noreturn {
4747 @setAlignStack(16);
48
48 if (!builtin.single_threaded) {
49 _ = @import("../os/windows/tls.zig");
50 }
4951 std.os.windows.ExitProcess(callMain());
5052}
5153