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...@@ -596,6 +596,7 @@ set(ZIG_STD_FILES
596 "os/windows/ntdll.zig"596 "os/windows/ntdll.zig"
597 "os/windows/ole32.zig"597 "os/windows/ole32.zig"
598 "os/windows/shell32.zig"598 "os/windows/shell32.zig"
599 "os/windows/tls.zig"
599 "os/windows/util.zig"600 "os/windows/util.zig"
600 "os/zen.zig"601 "os/zen.zig"
601 "pdb.zig"602 "pdb.zig"
src/codegen.cpp+8-6
...@@ -6365,6 +6365,12 @@ static void validate_inline_fns(CodeGen *g) {...@@ -6365,6 +6365,12 @@ static void validate_inline_fns(CodeGen *g) {
6365 report_errors_and_maybe_exit(g);6365 report_errors_and_maybe_exit(g);
6366}6366}
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
6368static void do_code_gen(CodeGen *g) {6374static void do_code_gen(CodeGen *g) {
6369 assert(!g->errors.length);6375 assert(!g->errors.length);
63706376
...@@ -6449,9 +6455,7 @@ static void do_code_gen(CodeGen *g) {...@@ -6449,9 +6455,7 @@ static void do_code_gen(CodeGen *g) {
6449 maybe_import_dll(g, global_value, GlobalLinkageIdStrong);6455 maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
6450 LLVMSetAlignment(global_value, var->align_bytes);6456 LLVMSetAlignment(global_value, var->align_bytes);
6451 LLVMSetGlobalConstant(global_value, var->gen_is_const);6457 LLVMSetGlobalConstant(global_value, var->gen_is_const);
6452 if (var->is_thread_local && !g->is_single_threaded) {6458 set_global_tls(g, var, global_value);
6453 LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
6454 }
6455 }6459 }
6456 } else {6460 } else {
6457 bool exported = (var->linkage == VarLinkageExport);6461 bool exported = (var->linkage == VarLinkageExport);
...@@ -6477,9 +6481,7 @@ static void do_code_gen(CodeGen *g) {...@@ -6477,9 +6481,7 @@ static void do_code_gen(CodeGen *g) {
6477 }6481 }
64786482
6479 LLVMSetGlobalConstant(global_value, var->gen_is_const);6483 LLVMSetGlobalConstant(global_value, var->gen_is_const);
6480 if (var->is_thread_local && !g->is_single_threaded) {6484 set_global_tls(g, var, global_value);
6481 LLVMSetThreadLocalMode(global_value, LLVMGeneralDynamicTLSModel);
6482 }
6483 }6485 }
64846486
6485 var->value_ref = global_value;6487 var->value_ref = global_value;
std/os/windows/index.zig+18-1
...@@ -49,7 +49,10 @@ pub const UNICODE = false;...@@ -49,7 +49,10 @@ pub const UNICODE = false;
49pub const WCHAR = u16;49pub const WCHAR = u16;
50pub const WORD = u16;50pub const WORD = u16;
51pub const LARGE_INTEGER = i64;51pub 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
54pub const TRUE = 1;57pub const TRUE = 1;
55pub const FALSE = 0;58pub const FALSE = 0;
...@@ -380,3 +383,17 @@ pub const COORD = extern struct {...@@ -380,3 +383,17 @@ pub const COORD = extern struct {
380};383};
381384
382pub const CREATE_UNICODE_ENVIRONMENT = 1024;385pub 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;...@@ -164,6 +164,10 @@ pub extern "kernel32" stdcallcc fn Sleep(dwMilliseconds: DWORD) void;
164164
165pub extern "kernel32" stdcallcc fn TerminateProcess(hProcess: HANDLE, uExitCode: UINT) BOOL;165pub 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
167pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) DWORD;171pub extern "kernel32" stdcallcc fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) DWORD;
168172
169pub extern "kernel32" stdcallcc fn WriteFile(173pub 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 {...@@ -45,7 +45,9 @@ nakedcc fn _start() noreturn {
4545
46extern fn WinMainCRTStartup() noreturn {46extern fn WinMainCRTStartup() noreturn {
47 @setAlignStack(16);47 @setAlignStack(16);
4848 if (!builtin.single_threaded) {
49 _ = @import("../os/windows/tls.zig");
50 }
49 std.os.windows.ExitProcess(callMain());51 std.os.windows.ExitProcess(callMain());
50}52}
5153