| |
| version(CRuntime_Microsoft) |
| { |
| extern(C) |
| { |
| extern __gshared uint _DP_beg; |
| extern __gshared uint _DP_end; |
| extern __gshared uint _TP_beg; |
| extern __gshared uint _TP_end; |
| } |
| alias _DPbegin = _DP_beg; |
| alias _DPend = _DP_end; |
| alias _TPbegin = _TP_beg; |
| alias _TPend = _TP_end; |
| |
| __gshared void[] dataSection; |
| shared static this() |
| { |
| import core.internal.traits : externDFunc; |
| alias findImageSection = externDFunc!("rt.sections_win64.findImageSection", |
| void[] function(string name) nothrow @nogc); |
| dataSection = findImageSection(".data"); |
| } |
| |
| void[] tlsRange; |
| static this() |
| { |
| import core.internal.traits : externDFunc; |
| alias initTLSRanges = externDFunc!("rt.sections_win64.initTLSRanges", |
| void[] function() nothrow @nogc); |
| tlsRange = initTLSRanges(); |
| } |
| |
| version = ptrref_supported; |
| } |
| else version(Win32) |
| { |
| extern(C) |
| { |
| extern __gshared void* _DPbegin; |
| extern __gshared void* _DPend; |
| extern __gshared uint _TPbegin; |
| extern __gshared uint _TPend; |
| extern int _tlsstart; |
| extern int _tlsend; |
| } |
| |
| void[] tlsRange; |
| static this() |
| { |
| tlsRange = (cast(void*)&_tlsstart)[0.. cast(void*)&_tlsend - cast(void*)&_tlsstart]; |
| } |
| |
| version = ptrref_supported; |
| } |
| |
| struct Struct |
| { |
| int x; |
| Struct* next; |
| } |
| |
| class Class |
| { |
| void* ptr; |
| } |
| |
| struct Struc(T) |
| { |
| static T vtls; |
| static __gshared T vgshared; |
| } |
| |
| __gshared Struct* gsharedStrctPtr2 = new Struct(7, new Struct(8, null)); |
| |
| int tlsInt; |
| void* tlsVar; |
| |
| shared int sharedInt; |
| shared void* sharedVar; |
| __gshared void* gsharedVar; |
| __gshared void* gsharedVar2; |
| immutable int[] arr = [1, 2, 3]; |
| string tlsStr; |
| |
| __gshared Struct gsharedStrct; |
| Struct[3] tlsStrcArr; |
| Class tlsClss; |
| |
| // expression initializers |
| string[] strArr = [ "a", "b" ]; |
| __gshared Class gsharedClss = new Class; |
| __gshared Struct* gsharedStrctPtr = new Struct(7, new Struct(8, null)); |
| |
| debug(PRINT) import core.stdc.stdio; |
| |
| void main() |
| { |
| version(ptrref_supported) |
| testRefPtr(); |
| } |
| |
| version(ptrref_supported): |
| |
| bool findTlsPtr(const(void)* ptr) |
| { |
| debug(PRINT) printf("findTlsPtr %p\n", ptr); |
| for (uint* p = &_TPbegin; p < &_TPend; p++) |
| { |
| void* addr = tlsRange.ptr + *p; |
| debug(PRINT) printf(" try %p\n", addr); |
| assert(*p < tlsRange.length); |
| if (addr == ptr) |
| return true; |
| } |
| return false; |
| } |
| |
| bool findDataPtr(const(void)* ptr) |
| { |
| debug(PRINT) printf("findDataPtr %p\n", ptr); |
| for (auto p = &_DPbegin; p < &_DPend; p++) |
| { |
| debug(PRINT) printf(" try %p\n", cast(void*) cast(size_t) *p); |
| version(CRuntime_Microsoft) |
| void* addr = dataSection.ptr + *p; |
| else |
| void* addr = *p; |
| |
| if (addr == ptr) |
| return true; |
| } |
| return false; |
| } |
| |
| void testRefPtr() |
| { |
| debug(PRINT) printf("&_DPbegin %p\n", &_DPbegin); |
| debug(PRINT) printf("&_DPend %p\n", &_DPend); |
| |
| debug(PRINT) printf("&_TPbegin %p\n", &_TPbegin); |
| debug(PRINT) printf("&_TPend %p\n", &_TPend); |
| |
| assert(!findDataPtr(cast(void*)&sharedInt)); |
| assert(!findTlsPtr(&tlsInt)); |
| |
| assert(findDataPtr(cast(void*)&sharedVar)); |
| assert(findDataPtr(&gsharedVar)); |
| assert(findDataPtr(&gsharedStrct.next)); |
| assert(findDataPtr(&(gsharedClss))); |
| assert(findDataPtr(&(gsharedClss.ptr))); |
| |
| assert(findTlsPtr(&tlsVar)); |
| assert(findTlsPtr(&tlsClss)); |
| assert(findTlsPtr(&tlsStrcArr[0].next)); |
| assert(findTlsPtr(&tlsStrcArr[1].next)); |
| assert(findTlsPtr(&tlsStrcArr[2].next)); |
| |
| assert(!findTlsPtr(cast(size_t*)&tlsStr)); // length |
| assert(findTlsPtr(cast(size_t*)&tlsStr + 1)); // ptr |
| |
| // monitor is manually managed |
| assert(!findDataPtr(cast(size_t*)cast(void*)Class.classinfo + 1)); |
| assert(!findDataPtr(cast(size_t*)cast(void*)Class.classinfo + 1)); |
| |
| assert(!findDataPtr(&arr)); |
| assert(!findTlsPtr(&arr)); |
| assert(!findDataPtr(cast(size_t*)&arr + 1)); |
| assert(!findTlsPtr(cast(size_t*)&arr + 1)); |
| |
| assert(findDataPtr(cast(size_t*)&strArr[0] + 1)); // ptr in _DATA! |
| assert(findDataPtr(cast(size_t*)&strArr[1] + 1)); // ptr in _DATA! |
| strArr[1] = "c"; |
| |
| assert(findDataPtr(&gsharedStrctPtr)); |
| assert(findDataPtr(&gsharedStrctPtr.next)); |
| assert(findDataPtr(&gsharedStrctPtr.next.next)); |
| |
| assert(findDataPtr(&(Struc!(int*).vgshared))); |
| assert(!findDataPtr(&(Struc!(int).vgshared))); |
| assert(findTlsPtr(&(Struc!(int*).vtls))); |
| assert(!findTlsPtr(&(Struc!(int).vtls))); |
| } |