Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
fix Issue 4854 - Regression(2.047, Mac 10.5 only) writefln Segmentati…
Browse files Browse the repository at this point in the history
…on fault if no globals
  • Loading branch information
WalterBright committed Mar 8, 2012
1 parent b7bfe42 commit 73cf2c1
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 7 deletions.
96 changes: 90 additions & 6 deletions src/core/thread.d
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module core.thread;

public import core.time; // for Duration

//import core.stdc.stdio;

// this should be true for most architectures
version = StackGrowsDown;
Expand Down Expand Up @@ -279,6 +280,13 @@ else version( Posix )
}
}
else version( OSX )
{
extern (C)
{
__gshared void[][2] _tls_data_array;
}
}
else version(none)
{
extern (C)
{
Expand Down Expand Up @@ -355,7 +363,21 @@ else version( Posix )
obj.m_main.bstack = &obj;
obj.m_main.tstack = obj.m_main.bstack;

version( OSX )
version (OSX)
{
// NOTE: OSX does not support TLS, so we do it ourselves. The TLS
// data output by the compiler is bracketed by _tls_data_array[2],
// so make a copy of it for each thread.
const sz0 = (_tls_data_array[0].length + 15) & ~cast(size_t)15;
const sz2 = sz0 + _tls_data_array[1].length;
auto p = malloc( sz2 );
assert( p );
obj.m_tls = p[0 .. sz2];
memcpy( p, _tls_data_array[0].ptr, _tls_data_array[0].length );
memcpy( p + sz0, _tls_data_array[1].ptr, _tls_data_array[1].length );
scope (exit) { free( p ); obj.m_tls = null; }
}
else version (none)
{
// NOTE: OSX does not support TLS, so we do it ourselves. The TLS
// data output by the compiler is bracketed by _tls_beg and
Expand Down Expand Up @@ -1354,7 +1376,23 @@ private:
m_call = Call.NO;
m_curr = &m_main;

version( OSX )
version (OSX)
{
//printf("test2 %p %p\n", _tls_data_array[0].ptr, &_tls_data_array[1][length]);
//printf("test2 %p %p\n", &_tls_beg, &_tls_end);
// NOTE: OSX does not support TLS, so we do it ourselves. The TLS
// data output by the compiler is bracketed by _tls_data_array2],
// so make a copy of it for each thread.
const sz0 = (_tls_data_array[0].length + 15) & ~cast(size_t)15;
const sz2 = sz0 + _tls_data_array[1].length;
auto p = malloc( sz2 );
assert( p );
m_tls = p[0 .. sz2];
memcpy( p, _tls_data_array[0].ptr, _tls_data_array[0].length );
memcpy( p + sz0, _tls_data_array[1].ptr, _tls_data_array[1].length );
// The free must happen at program end, if anywhere.
}
else version (none)
{
// NOTE: OSX does not support TLS, so we do it ourselves. The TLS
// data output by the compiler is bracketed by _tls_beg and
Expand Down Expand Up @@ -1974,7 +2012,23 @@ extern (C) Thread thread_attachThis()
assert( thisThread.m_tmach != thisThread.m_tmach.init );
}

version( OSX )
version (OSX)
{
//printf("test3 %p %p\n", _tls_data_array[0].ptr, &_tls_data_array[1][length]);
//printf("test3 %p %p\n", &_tls_beg, &_tls_end);
// NOTE: OSX does not support TLS, so we do it ourselves. The TLS
// data output by the compiler is bracketed by _tls_data_array[2],
// so make a copy of it for each thread.
const sz0 = (_tls_data_array[0].length + 15) & ~cast(size_t)15;
const sz2 = sz0 + _tls_data_array[1].length;
auto p = gc_malloc( sz2 );
assert( p );
thisThread.m_tls = p[0 .. sz2];
memcpy( p, _tls_data_array[0].ptr, _tls_data_array[0].length );
memcpy( p + sz0, _tls_data_array[1].ptr, _tls_data_array[1].length );
// used gc_malloc so no need to free
}
else version (none)
{
// NOTE: OSX does not support TLS, so we do it ourselves. The TLS
// data output by the compiler is bracketed by _tls_beg and
Expand Down Expand Up @@ -2059,7 +2113,24 @@ version( Windows )
assert( thisThread.m_tmach != thisThread.m_tmach.init );
}

version( OSX )
version (OSX)
{
// NOTE: OSX does not support TLS, so we do it ourselves. The TLS
// data output by the compiler is bracketed by _tls_data_array[2],
// so make a copy of it for each thread.
const sz0 = (_tls_data_array[0].length + 15) & ~cast(size_t)15;
const sz2 = sz0 + _tls_data_array[1].length;
auto p = gc_malloc( sz2 );
assert( p );
obj.m_tls = p[0 .. sz2];
memcpy( p, _tls_data_array[0].ptr, _tls_data_array[0].length );
memcpy( p + sz0, _tls_data_array[1].ptr, _tls_data_array[1].length );
// used gc_malloc so no need to free

if( t.m_addr == pthread_self() )
Thread.setThis( thisThread );
}
else version (none)
{
// NOTE: OSX does not support TLS, so we do it ourselves. The TLS
// data output by the compiler is bracketed by _tls_beg and
Expand Down Expand Up @@ -4232,8 +4303,21 @@ version( OSX )
{
// NOTE: p is an address in the TLS static data emitted by the
// compiler. If it isn't, something is disastrously wrong.
assert( p >= cast(void*) &_tls_beg && p < cast(void*) &_tls_end );
auto obj = Thread.getThis();
return obj.m_tls.ptr + (p - cast(void*) &_tls_beg);

if (p >= _tls_data_array[0].ptr && p < &_tls_data_array[0][length])
{
return obj.m_tls.ptr + (p - _tls_data_array[0].ptr);
}
else if (p >= _tls_data_array[1].ptr && p < &_tls_data_array[1][length])
{
size_t sz = (_tls_data_array[0].length + 15) & ~cast(size_t)15;
return obj.m_tls.ptr + sz + (p - _tls_data_array[1].ptr);
}
else
assert(0);

//assert( p >= cast(void*) &_tls_beg && p < cast(void*) &_tls_end );
//return obj.m_tls.ptr + (p - cast(void*) &_tls_beg);
}
}
6 changes: 5 additions & 1 deletion src/rt/dmain2.d
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ version (OSX)
{
// The bottom of the stack
extern (C) __gshared void* __osx_stack_end = cast(void*)0xC0000000;

extern (C) extern (C) void _d_osx_image_init2();
}

/***********************************
Expand Down Expand Up @@ -348,6 +350,8 @@ extern (C) int main(int argc, char** argv)
* of the main thread's stack, so save the address of that.
*/
__osx_stack_end = cast(void*)&argv;

_d_osx_image_init2();
}

version (FreeBSD) version (D_InlineAsm_X86)
Expand Down Expand Up @@ -375,7 +379,7 @@ extern (C) int main(int argc, char** argv)
version (Windows)
{
wchar_t* wcbuf = GetCommandLineW();
size_t wclen = wcslen(wcbuf);
size_t wclen = wcslen(wcbuf);
int wargc = 0;
wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
assert(wargc == argc);
Expand Down
45 changes: 45 additions & 0 deletions src/rt/memory_osx.d
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import src.core.sys.osx.mach.getsect;

extern (C) extern __gshared ModuleInfo*[] _moduleinfo_array;
extern (C) extern __gshared ubyte[] _deh_eh_array;
extern (C) extern __gshared ubyte[][2] _tls_data_array;

extern (C) void gc_addRange( void* p, size_t sz );
extern (C) void gc_removeRange( void* p );
Expand Down Expand Up @@ -124,3 +125,47 @@ extern (C) void _d_osx_image_init()
_dyld_register_func_for_add_image( &onAddImage );
_dyld_register_func_for_remove_image( &onRemoveImage );
}

/*********************************
* The following is done separately because it must be done before Thread gets initialized.
*/

extern (C) void onAddImage2(in mach_header* h, intptr_t slide)
{
//printf("onAddImage2()\n");

if (auto sect = getSection(h, slide, "__DATA", "__tls_data"))
{
//printf(" tls_data %p %p\n", &sect[0], &sect[length]);
/* BUG: this will fail if there are multiple images with __tls_data
* sections. Not set up to handle that.
*/
if (!_tls_data_array[0].ptr)
_tls_data_array[0] = sect.ptr[0 .. sect.length];
}

if (auto sect = getSection(h, slide, "__DATA", "__tlscoal_nt"))
{
//printf(" tlscoal_nt %p %p\n", &sect[0], &sect[length]);
/* BUG: this will fail if there are multiple images with __tlscoal_nt
* sections. Not set up to handle that.
*/
if (!_tls_data_array[1].ptr)
_tls_data_array[1] = sect.ptr[0 .. sect.length];
}
}


extern (C) void onRemoveImage2(in mach_header* h, intptr_t slide)
{
//printf("onRemoveImage2()\n");
}


extern (C) void _d_osx_image_init2()
{
//printf("_d_osx_image_init2()\n");
_dyld_register_func_for_add_image( &onAddImage2 );
_dyld_register_func_for_remove_image( &onRemoveImage2 );
}

0 comments on commit 73cf2c1

Please sign in to comment.