implement Thread Local Storage on Windows
parent
d2602b442e
commit
89ffb58197
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
};
|
|
@ -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());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue