Changeset 260
- Timestamp:
- 03/11/10 00:36:00 (2 years ago)
- Files:
-
- trunk/import/object.di (modified) (1 diff)
- trunk/src/core/dll_helper.d (added)
- trunk/src/core/thread.d (modified) (13 diffs)
- trunk/src/core/thread_helper.d (added)
- trunk/win32.mak (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/import/object.di
r258 r260 247 247 } 248 248 249 ModuleInfo*[] _moduleinfo_tlsdtors; 250 uint _moduleinfo_tlsdtors_i; 251 252 extern (C) void _moduleTlsCtor(); 253 extern (C) void _moduleTlsDtor(); 254 249 255 class Throwable : Object 250 256 { trunk/src/core/thread.d
r238 r260 99 99 import core.stdc.stdint : uintptr_t; // for _beginthreadex decl below 100 100 import core.sys.windows.windows; 101 import core.thread_helper; 101 102 102 103 const DWORD TLS_OUT_OF_INDEXES = 0xFFFFFFFF; … … 192 193 return 0; 193 194 } 194 195 195 196 196 // … … 1093 1093 version( Windows ) 1094 1094 { 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; 1096 1100 } 1097 1101 else version( Posix ) … … 1125 1129 } 1126 1130 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 } 1127 1149 1128 1150 /** … … 1479 1501 // 1480 1502 static void add( Context* c ) 1503 { 1504 synchronized( slock ) 1505 { 1506 add_nolock( c ); 1507 } 1508 } 1509 1510 static void add_nolock( Context* c ) 1481 1511 in 1482 1512 { … … 1486 1516 body 1487 1517 { 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; 1498 1525 } 1499 1526 … … 1538 1565 // 1539 1566 static void add( Thread t ) 1567 { 1568 synchronized( slock ) 1569 { 1570 add_nolock( t ); 1571 } 1572 } 1573 1574 static void add_nolock( Thread t ) 1540 1575 in 1541 1576 { … … 1546 1581 body 1547 1582 { 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; 1558 1590 } 1559 1591 … … 1567 1599 assert( t ); 1568 1600 assert( t.next || t.prev ); 1569 version( Windows)1601 version( none ) 1570 1602 { 1571 1603 // NOTE: This doesn't work for Posix as m_isRunning must be set to 1572 1604 // 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 1573 1607 assert( !t.isRunning ); 1574 1608 } … … 1694 1728 extern (C) void thread_attachThis() 1695 1729 { 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 */ 1748 extern (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 1767 extern (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 1696 1777 version( Windows ) 1697 1778 { 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; 1710 1800 } 1711 1801 else version( Posix ) 1712 1802 { 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; 1725 1812 } 1726 1813 version( OSX ) 1727 1814 { 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; 1734 1826 } 1735 1827 … … 1744 1836 } 1745 1837 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 */ 1842 extern (C) void thread_detach( Thread.ThreadAddr addr ) 1843 { 1844 Thread t = Thread.findThread( addr ); 1845 if( t ) 1846 Thread.remove( t ); 1847 } 1848 1746 1849 1747 1850 /** … … 1791 1894 // Used for needLock below. 1792 1895 private __gshared bool multiThreadedFlag = false; 1793 1794 1896 1795 1897 /** … … 1807 1909 } 1808 1910 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 1913 extern (C) void thread_setNeedLock(bool need) nothrow 1914 { 1915 multiThreadedFlag = need; 1916 } 1809 1917 1810 1918 // Used for suspendAll/resumeAll below. trunk/win32.mak
r235 r260 97 97 src/core/sync/semaphore.d \ 98 98 src/core/thread.d \ 99 src/core/thread_helper.d \ 100 src/core/dll_helper.d \ 99 101 src/core/threadasm.S \ 100 102 src/core/vararg.d \ … … 193 195 src\core\runtime.d \ 194 196 src\core\thread.d \ 197 src\core\thread_helper.d \ 198 src\core\dll_helper.d \ 195 199 src\core\vararg.d \ 196 200 \ … … 328 332 $(IMPDIR)\core\runtime.di \ 329 333 $(IMPDIR)\core\thread.di \ 334 $(IMPDIR)\core\thread_helper.di \ 335 $(IMPDIR)\core\dll_helper.di \ 330 336 $(IMPDIR)\core\vararg.di \ 331 337 \ … … 406 412 $(DMD) -c -d -o- -Iimport -Isrc -Hf$@ $** 407 413 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 408 420 $(IMPDIR)\core\vararg.di : src\core\vararg.d 409 421 $(DMD) -c -d -o- -Iimport -Isrc -Hf$@ $**
