Changeset 260

Show
Ignore:
Timestamp:
03/11/10 00:36:00 (2 years ago)
Author:
walter
Message:

Rainer Schuetze's threading dll fix

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/import/object.di

    r258 r260  
    247247} 
    248248 
     249ModuleInfo*[] _moduleinfo_tlsdtors; 
     250uint          _moduleinfo_tlsdtors_i; 
     251 
     252extern (C) void _moduleTlsCtor(); 
     253extern (C) void _moduleTlsDtor(); 
     254 
    249255class Throwable : Object 
    250256{ 
  • trunk/src/core/thread.d

    r238 r260  
    9999        import core.stdc.stdint : uintptr_t; // for _beginthreadex decl below 
    100100        import core.sys.windows.windows; 
     101        import core.thread_helper; 
    101102 
    102103        const DWORD TLS_OUT_OF_INDEXES  = 0xFFFFFFFF; 
     
    192193            return 0; 
    193194        } 
    194  
    195195 
    196196        // 
     
    10931093        version( Windows ) 
    10941094        { 
    1095             return cast(Thread) TlsGetValue( sm_this ); 
     1095            Thread t = cast(Thread) TlsGetValue( sm_this ); 
     1096        if( t is null ) 
     1097        // if the thread has been attached from another thread, the tls value was not set 
     1098        setThis( t = findThread( GetCurrentThreadId() ) ); 
     1099        return t; 
    10961100        } 
    10971101        else version( Posix ) 
     
    11251129    } 
    11261130 
     1131    /** 
     1132     * Search the list of all threads for a thread with the given thread identifier 
     1133     * 
     1134     * Params: 
     1135     *  addr = The thread identifier to search for 
     1136     * Returns: 
     1137     *  the thread object associated with the thread identifier, null if not found 
     1138     */ 
     1139    static Thread findThread( ThreadAddr addr ) 
     1140    { 
     1141        synchronized( slock ) 
     1142        { 
     1143        foreach( Thread t; Thread ) 
     1144        if( t.m_addr == addr ) 
     1145            return t; 
     1146    } 
     1147    return null; 
     1148    } 
    11271149 
    11281150    /** 
     
    14791501    // 
    14801502    static void add( Context* c ) 
     1503    { 
     1504        synchronized( slock ) 
     1505        { 
     1506        add_nolock( c ); 
     1507    } 
     1508    } 
     1509 
     1510    static void add_nolock( Context* c ) 
    14811511    in 
    14821512    { 
     
    14861516    body 
    14871517    { 
    1488         synchronized( slock ) 
    1489         { 
    1490             if( sm_cbeg ) 
    1491             { 
    1492                 c.next = sm_cbeg; 
    1493                 sm_cbeg.prev = c; 
    1494             } 
    1495             sm_cbeg = c; 
    1496             ++sm_clen; 
    1497         } 
     1518        if( sm_cbeg ) 
     1519        { 
     1520            c.next = sm_cbeg; 
     1521            sm_cbeg.prev = c; 
     1522        } 
     1523        sm_cbeg = c; 
     1524        ++sm_clen; 
    14981525    } 
    14991526 
     
    15381565    // 
    15391566    static void add( Thread t ) 
     1567    { 
     1568        synchronized( slock ) 
     1569    { 
     1570        add_nolock( t ); 
     1571    } 
     1572    } 
     1573 
     1574    static void add_nolock( Thread t ) 
    15401575    in 
    15411576    { 
     
    15461581    body 
    15471582    { 
    1548         synchronized( slock ) 
    1549         { 
    1550             if( sm_tbeg ) 
    1551             { 
    1552                 t.next = sm_tbeg; 
    1553                 sm_tbeg.prev = t; 
    1554             } 
    1555             sm_tbeg = t; 
    1556             ++sm_tlen; 
    1557         } 
     1583    if( sm_tbeg ) 
     1584        { 
     1585            t.next = sm_tbeg; 
     1586            sm_tbeg.prev = t; 
     1587        } 
     1588        sm_tbeg = t; 
     1589        ++sm_tlen; 
    15581590    } 
    15591591 
     
    15671599        assert( t ); 
    15681600        assert( t.next || t.prev ); 
    1569         version( Windows
     1601        version( none
    15701602        { 
    15711603            // NOTE: This doesn't work for Posix as m_isRunning must be set to 
    15721604            //       false after the thread is removed during normal execution. 
     1605            // NOTE: This doesn't work for Windows either because remove is called 
     1606        //       from the thread itself 
    15731607            assert( !t.isRunning ); 
    15741608        } 
     
    16941728extern (C) void thread_attachThis() 
    16951729{ 
     1730    synchronized( Thread.slock ) 
     1731    { 
     1732    version( Windows ) 
     1733    { 
     1734        Thread thisThread = thread_attach_nolock( GetCurrentThreadId(), getStackBottom() ); 
     1735    } 
     1736    else version( Posix ) 
     1737    { 
     1738        Thread thisThread = thread_attach_nolock( pthread_self(), getStackBottom() ); 
     1739    } 
     1740    Thread.setThis( thisThread ); 
     1741    } 
     1742} 
     1743 
     1744/** 
     1745 * Registers the thread with the given identifier for use with the D Runtime.  If this routine 
     1746 * is called for a thread which is already registered, the result is undefined. 
     1747 */ 
     1748extern (C) Thread thread_attach( Thread.ThreadAddr addr ) 
     1749{ 
     1750    synchronized( Thread.slock ) 
     1751    { 
     1752    version( Windows ) 
     1753    { 
     1754        void* bstack = getThreadStackBottom( addr ); 
     1755    } 
     1756    else version( Posix ) 
     1757    { 
     1758        void* bstack = null; 
     1759        assert( false ); // not implemented 
     1760    } 
     1761    return thread_attach_nolock( addr, bstack ); 
     1762    // setThis cannot be called, because it sets the value in the current thread,  
     1763    //  not in the thread ew just attached to 
     1764    } 
     1765} 
     1766 
     1767extern (C) Thread thread_attach_nolock( Thread.ThreadAddr addr, void* bstack ) 
     1768{ 
     1769    // the gc should not be touched before attaching to the thread, because 
     1770    //  it might interfere with threads that use the GC, but won't suspend 
     1771    //  this thread. So we use a Thread object created by an attached thread. 
     1772    // This is not necessary for the main (first) thread, because there is no 
     1773    // concurrent thread. 
     1774    static __gshared Thread nextThread; 
     1775    Thread thisThread = nextThread ? nextThread : new Thread(); 
     1776 
    16961777    version( Windows ) 
    16971778    { 
    1698         Thread          thisThread  = new Thread(); 
    1699         Thread.Context* thisContext = &thisThread.m_main; 
    1700         assert( thisContext == thisThread.m_curr ); 
    1701  
    1702         thisThread.m_addr  = GetCurrentThreadId(); 
    1703         thisThread.m_hndl  = GetCurrentThreadHandle(); 
    1704         thisContext.bstack = getStackBottom(); 
    1705         thisContext.tstack = thisContext.bstack; 
    1706  
    1707         thisThread.m_isDaemon = true; 
    1708  
    1709         Thread.setThis( thisThread ); 
     1779    Thread.Context* thisContext = &thisThread.m_main; 
     1780    assert( thisContext == thisThread.m_curr ); 
     1781 
     1782    thisThread.m_addr  = addr; 
     1783    thisContext.bstack = bstack; 
     1784    thisContext.tstack = thisContext.bstack; 
     1785 
     1786    auto pstart = cast(void*) &_tlsstart; 
     1787    auto pend   = cast(void*) &_tlsend; 
     1788    if( addr == GetCurrentThreadId() ) 
     1789    { 
     1790        thisThread.m_tls = pstart[0 .. pend - pstart]; 
     1791        thisThread.m_hndl = GetCurrentThreadHandle(); 
     1792    } 
     1793    else 
     1794    { 
     1795        thisThread.m_hndl = OpenThreadHandle( addr ); 
     1796        thisThread.m_tls = GetTlsDataAddress( thisThread.m_hndl )[0 .. pend - pstart]; 
     1797    } 
     1798 
     1799    thisThread.m_isDaemon = true; 
    17101800    } 
    17111801    else version( Posix ) 
    17121802    { 
    1713         Thread          thisThread  = new Thread(); 
    1714         Thread.Context* thisContext = thisThread.m_curr; 
    1715         assert( thisContext == &thisThread.m_main ); 
    1716  
    1717         thisThread.m_addr  = pthread_self(); 
    1718         thisContext.bstack = getStackBottom(); 
    1719         thisContext.tstack = thisContext.bstack; 
    1720  
    1721         thisThread.m_isRunning = true; 
    1722         thisThread.m_isDaemon  = true; 
    1723  
    1724         Thread.setThis( thisThread ); 
     1803    Thread.Context* thisContext = thisThread.m_curr; 
     1804    assert( thisContext == &thisThread.m_main ); 
     1805 
     1806    thisThread.m_addr  = addr; 
     1807    thisContext.bstack = bstack; 
     1808    thisContext.tstack = thisContext.bstack; 
     1809 
     1810    thisThread.m_isRunning = true; 
     1811    thisThread.m_isDaemon  = true; 
    17251812    } 
    17261813    version( OSX ) 
    17271814    { 
    1728         thisThread.m_tmach = pthread_mach_thread_np( thisThread.m_addr ); 
    1729         assert( thisThread.m_tmach != thisThread.m_tmach.init ); 
    1730     }     
    1731  
    1732     Thread.add( thisThread ); 
    1733     Thread.add( thisContext ); 
     1815    thisThread.m_tmach = pthread_mach_thread_np( thisThread.m_addr ); 
     1816    assert( thisThread.m_tmach != thisThread.m_tmach.init ); 
     1817    } 
     1818 
     1819    Thread.add_nolock( thisThread ); 
     1820    Thread.add_nolock( thisContext ); 
     1821 
     1822    // Now it is safe to alloc anything from the GC 
     1823    nextThread = new Thread(); 
     1824 
     1825    return thisThread; 
    17341826} 
    17351827 
     
    17441836} 
    17451837 
     1838/** 
     1839 * Deregisters the thread with the given thread identifier from use with the runtime. 
     1840 * If this routine is called for a thread which is not registered, it does nothing. 
     1841 */ 
     1842extern (C) void thread_detach( Thread.ThreadAddr addr ) 
     1843{ 
     1844    Thread t = Thread.findThread( addr ); 
     1845    if( t ) 
     1846    Thread.remove( t ); 
     1847} 
     1848 
    17461849 
    17471850/** 
     
    17911894// Used for needLock below. 
    17921895private __gshared bool multiThreadedFlag = false; 
    1793  
    17941896 
    17951897/** 
     
    18071909} 
    18081910 
     1911// a DLL needs to set multiThreadedFlag, because threads might be 
     1912//  created from other parts of the program that are not under our control 
     1913extern (C) void thread_setNeedLock(bool need) nothrow 
     1914{ 
     1915    multiThreadedFlag = need; 
     1916} 
    18091917 
    18101918// Used for suspendAll/resumeAll below. 
  • trunk/win32.mak

    r235 r260  
    9797    src/core/sync/semaphore.d \ 
    9898    src/core/thread.d \ 
     99    src/core/thread_helper.d \ 
     100    src/core/dll_helper.d \ 
    99101    src/core/threadasm.S \ 
    100102    src/core/vararg.d \ 
     
    193195    src\core\runtime.d \ 
    194196    src\core\thread.d \ 
     197    src\core\thread_helper.d \ 
     198    src\core\dll_helper.d \ 
    195199    src\core\vararg.d \ 
    196200    \ 
     
    328332    $(IMPDIR)\core\runtime.di \ 
    329333    $(IMPDIR)\core\thread.di \ 
     334    $(IMPDIR)\core\thread_helper.di \ 
     335    $(IMPDIR)\core\dll_helper.di \ 
    330336    $(IMPDIR)\core\vararg.di \ 
    331337    \ 
     
    406412    $(DMD) -c -d -o- -Iimport -Isrc -Hf$@ $** 
    407413 
     414$(IMPDIR)\core\thread_helper.di : src\core\thread_helper.d 
     415    $(DMD) -c -d -o- -Iimport -Isrc -Hf$@ $** 
     416 
     417$(IMPDIR)\core\dll_helper.di : src\core\dll_helper.d 
     418    $(DMD) -c -d -o- -Iimport -Isrc -Hf$@ $** 
     419 
    408420$(IMPDIR)\core\vararg.di : src\core\vararg.d 
    409421    $(DMD) -c -d -o- -Iimport -Isrc -Hf$@ $**