Index: std/thread.d
===================================================================
--- std/thread.d	(revision 1439)
+++ std/thread.d	(working copy)
@@ -139,28 +139,14 @@
 	    if (state != TS.INITIAL)
 		error("already started");
 
-	    for (int i = 0; 1; i++)
-	    {
-		if (i == allThreads.length)
-		    error("too many threads");
-		if (!allThreads[i])
-		{   allThreads[i] = this;
-		    idx = i;
-		    if (i >= allThreadsDim)
-			allThreadsDim = i + 1;
-		    break;
-		}
-	    }
-	    nthreads++;
+            add_thread();
 
 	    state = TS.RUNNING;
 	    hdl = _beginthreadex(null, cast(uint)stacksize, &threadstart, cast(void*)this, 0, &id);
 	    if (hdl == cast(thread_hdl)0)
 	    {
-		allThreads[idx] = null;
-		nthreads--;
+		del_thread();
 		state = TS.FINISHED;
-		idx = -1;
 		error("failed to start");
 	    }
 	}
@@ -299,13 +285,10 @@
     }
 
     /**
-     * Returns a reference to the Thread for the thread that called the
-     * function.
+     * Returns a reference to the Thread with the given id
      */
-    static Thread getThis()
+    static Thread _getThreadById(thread_id id)
     {
-	//printf("getThis(), allThreadsDim = %d\n", allThreadsDim);
-        thread_id id = GetCurrentThreadId();
         for (int i = 0; i < allThreadsDim; i++)
         {
             Thread t = allThreads[i];
@@ -314,6 +297,24 @@
                 return t;
             }
         }
+	return null;
+    }
+    /**
+     * Returns a reference to the Thread for the thread that called the
+     * function.
+     */
+    static Thread _getThis()
+    {
+	//printf("getThis(), allThreadsDim = %d\n", allThreadsDim);
+        thread_id id = GetCurrentThreadId();
+	return _getThreadById(id);
+    }
+
+    static Thread getThis()
+    {
+	Thread t = _getThis();
+	if(t)
+		return t;
 	printf("didn't find it\n");
 	assert(0);
     }
@@ -397,7 +398,7 @@
     /**
      *
      */
-    static uint nthreads = 1;
+    static uint nthreads = 0;
 
   private:
 
@@ -444,34 +445,124 @@
 	debug (thread) printf("Ending thread %d\n", t.idx);
         synchronized (Thread.classinfo)
         {
-            allThreads[t.idx] = null;
-            nthreads--;
+	    t.del_thread();
 	    t.state = TS.TERMINATED;
-            t.idx = -1;
         }
 	return result;
     }
 
+    /**************************************
+     * Add thread to array of all threads and set index into array
+     * call with synchronized (Thread.classinfo)
+     */
 
+    void add_thread()
+    {
+	// there might be threads that already exist when attaching all existing threads,
+	//  but still call DllMain with DLL_THREAD_ATTACH
+	if(_getThreadById(id))
+	    return;
+	
+	for (int i = 0; 1; i++)
+	{
+	    if (i == allThreads.length)
+		error("too many threads");
+	    if (!allThreads[i])
+	    {   allThreads[i] = this;
+		idx = i;
+		if (i >= allThreadsDim)
+		    allThreadsDim = i + 1;
+		break;
+	    }
+	}
+	nthreads++;
+    }
+
     /**************************************
+     * Delete thread from array of all threads
+     * call with synchronized (Thread.classinfo)
+     */
+
+    void del_thread()
+    {
+            assert(allThreads[idx] == this);
+
+            allThreads[idx] = null;
+            nthreads--;
+            idx = -1;
+
+            while(allThreadsDim > 0 && !allThreads[allThreadsDim - 1])
+		allThreadsDim--;            
+    }
+
+    /**************************************
      * Create a Thread for global main().
      */
 
     public static void thread_init()
     {
-	Thread t = new Thread();
+	assert(!allThreads[0]);
+	thread_attach();
+    }
 
+    /**************************************
+     * Attach to current thread
+     */
+
+    public static void thread_attach()
+    {
+	thread_attach(GetCurrentThreadId(), Thread.getCurrentThreadHandle(), os_query_stackBottom());
+    }
+
+    public static void thread_attach(thread_id id, thread_hdl hdl, void* bottom)
+    {
+	// the gc should not be touched before attaching to the thread, because
+	//  it might interfere with threads that use the GC, but won't suspend
+	//  this thread. So we use a Thread object created by an attached thread.
+	// This is not necessary for the main (first) thread, because there is no
+	// concurrent thread.
+	Thread t;
+	if(nextThread)
+	{
+	    t = nextThread;
+	    nextThread = null;
+	}
+	else
+	{
+	    t = new Thread();
+	}
+
 	t.state = TS.RUNNING;
-	t.id = GetCurrentThreadId();
-	t.hdl = Thread.getCurrentThreadHandle();
-	t.stackBottom = os_query_stackBottom();
+	t.id = id;
+	t.hdl = hdl;
+	t.stackBottom = bottom;
 
-	assert(!allThreads[0]);
-	allThreads[0] = t;
-	allThreadsDim = 1;
-	t.idx = 0;
+	synchronized (Thread.classinfo)
+	    t.add_thread();
+
+	nextThread = new Thread();
     }
 
+    static Thread nextThread; // preallocate thread to avoid allocation before attaching
+
+    /**************************************
+     * Detach from current thread
+     */
+
+    public static void thread_detach()
+    {
+	if(Thread t = _getThis())
+	    synchronized (Thread.classinfo)
+		t.del_thread();
+    }
+    
+    public static void thread_detach(thread_id id)
+    {
+	if(Thread t = _getThreadById(id))
+	    synchronized (Thread.classinfo)
+		t.del_thread();
+    }
+    
     static ~this()
     {
 	if (allThreadsDim)
@@ -590,21 +681,7 @@
 	    error("already started");
 
 	synchronized (Thread.classinfo)
-	{
-	    for (int i = 0; 1; i++)
-	    {
-		if (i == allThreads.length)
-		    error("too many threads");
-		if (!allThreads[i])
-		{   allThreads[i] = this;
-		    idx = i;
-		    if (i >= allThreadsDim)
-			allThreadsDim = i + 1;
-		    break;
-		}
-	    }
-	    nthreads++;
-	}
+	    idx = add_thread();
 
 	state = TS.RUNNING;
 	//printf("creating thread x%x\n", this);
@@ -884,7 +961,7 @@
 	sched_yield();
     }
 
-    static uint nthreads = 1;
+    static uint nthreads = 0;
 
   private:
 
Index: std/thread_helper.d
===================================================================
--- std/thread_helper.d	(revision 0)
+++ std/thread_helper.d	(revision 0)
@@ -0,0 +1,165 @@
+/**
+ * This module provides OS specific helper function for threads support
+ */
+
+module std.thread_helper;
+
+version( Windows )
+{
+    import std.c.windows.windows;
+    import std.c.stdlib;
+
+	public import std.thread;
+
+    ///////////////////////////////////////////////////////////////////
+
+    const SystemProcessInformation = 5;
+    const STATUS_INFO_LENGTH_MISMATCH = 0xc0000004;
+
+    // abbreviated versions of these structs
+    struct _SYSTEM_PROCESS_INFORMATION
+    {
+	int NextEntryOffset; // When this entry is 0, there are no more processes to be read.
+	int NumberOfThreads;
+	int[15] fill1;
+	int ProcessId;
+	int[28] fill2;
+    
+	// SYSTEM_THREAD_INFORMATION or SYSTEM_EXTENDED_THREAD_INFORMATION structures follow.
+    }
+
+    struct _SYSTEM_THREAD_INFORMATION
+    {
+	int[8] fill1;
+	int ProcessId;
+	int ThreadId;
+	int[6] fill2;
+    }
+
+    alias extern(Windows)
+    HRESULT fnNtQuerySystemInformation( uint SystemInformationClass, void* info, uint infoLength, uint* ReturnLength );
+
+    const ThreadBasicInformation = 0;
+
+    struct THREAD_BASIC_INFORMATION 
+    {
+	int    ExitStatus;
+	void** TebBaseAddress;
+	int    ProcessId;
+	int    ThreadId;
+	int    AffinityMask;
+	int    Priority;
+	int    BasePriority;
+    }
+
+    alias extern(Windows)
+    int fnNtQueryInformationThread( HANDLE ThreadHandle, uint ThreadInformationClass, void* buf, uint size, uint* ReturnLength );
+
+    ///////////////////////////////////////////////////////////////////
+    // support attaching to thread other than just executing
+    void** getTEB( HANDLE hnd )
+    {
+	HANDLE nthnd = GetModuleHandleA( "NTDLL" );
+	assert( nthnd, "cannot get module handle for ntdll" );
+	fnNtQueryInformationThread* fn = cast(fnNtQueryInformationThread*) GetProcAddress( nthnd, "NtQueryInformationThread" );
+	assert( fn, "cannot find NtQueryInformationThread in ntdll" );
+
+	THREAD_BASIC_INFORMATION tbi;
+	int Status = (*fn)(hnd, ThreadBasicInformation, &tbi, tbi.sizeof, null);
+	assert(Status == 0);
+	
+	return tbi.TebBaseAddress;
+    }
+
+    extern(Windows)
+    HANDLE OpenThread(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId);
+
+    const SYNCHRONIZE = 0x00100000;
+    const THREAD_GET_CONTEXT = 8;
+    const THREAD_QUERY_INFORMATION = 0x40;
+    const THREAD_SUSPEND_RESUME = 2;
+
+    void** getTEB( uint id )
+    {
+	HANDLE hnd = OpenThread( THREAD_QUERY_INFORMATION, FALSE, id );
+	assert( hnd, "OpenThread failed" );
+
+	void** teb = getTEB( hnd );
+	CloseHandle( hnd );
+	return teb;
+    }
+
+    void* getThreadStackBottom( HANDLE hnd )
+    {
+	void** teb = getTEB( hnd );
+	return teb[1];
+    }
+
+    void* getThreadStackBottom( uint id )
+    {
+	void** teb = getTEB( id );
+	return teb[1];
+    }
+
+    HANDLE OpenThreadHandle( uint id )
+    {
+	return OpenThread( SYNCHRONIZE|THREAD_GET_CONTEXT|THREAD_QUERY_INFORMATION|THREAD_SUSPEND_RESUME, FALSE, id );
+    }
+
+    ///////////////////////////////////////////////////////////////////
+    // support attaching to all running threads
+    // using unction instead of delegate here to avoid allocating closure
+    bool enumProcessThreads( uint procid, bool function( uint id, void* context ) dg, void* context )
+    {
+	HANDLE hnd = GetModuleHandleA( "NTDLL" );
+	fnNtQuerySystemInformation* fn = cast(fnNtQuerySystemInformation*) GetProcAddress( hnd, "NtQuerySystemInformation" );
+	if( !fn )
+	    return false;
+
+	uint sz = 16384;
+	uint retLength;
+	HRESULT rc;
+	char* buf;
+	for( ; ; )
+	{
+	    buf = cast(char*) std.c.stdlib.malloc(sz);
+	    if(!buf)
+	    	return false;
+	    rc = (*fn)( SystemProcessInformation, buf, sz, &retLength );
+	    if( rc != STATUS_INFO_LENGTH_MISMATCH )
+		break;
+	    std.c.stdlib.free( buf );
+	    sz *= 2;
+	}
+	scope(exit) std.c.stdlib.free( buf );
+
+	if(rc != 0)
+	    return false;
+
+	auto pinfo = cast(_SYSTEM_PROCESS_INFORMATION*) buf;
+	auto pend  = cast(_SYSTEM_PROCESS_INFORMATION*) (buf + retLength);
+	for( ; pinfo < pend; )
+	{
+	    if( pinfo.ProcessId == procid )
+	    {
+		auto tinfo = cast(_SYSTEM_THREAD_INFORMATION*)(pinfo + 1);
+		for( int i = 0; i < pinfo.NumberOfThreads; i++, tinfo++ )
+		    if( tinfo.ProcessId == procid )
+			if( !dg( tinfo.ThreadId, context ) )
+			    return false;
+	    }
+	    if( pinfo.NextEntryOffset == 0 )
+		break;
+	    pinfo = cast(_SYSTEM_PROCESS_INFORMATION*) (cast(char*) pinfo + pinfo.NextEntryOffset);
+	}
+	return true;
+    }
+
+    bool enumProcessThreads( bool function( uint id, void* context ) dg, void* context )
+    {
+	return enumProcessThreads( GetCurrentProcessId(), dg, context );
+    }
+
+
+}
+
Index: win32.mak
===================================================================
--- win32.mak	(revision 1439)
+++ win32.mak	(working copy)
@@ -76,7 +76,7 @@
         std\bitarray.d \
         std\signals.d std\typetuple.d std\traits.d std\bind.d \
         std\switcherr.d \
-        std\thread.d std\moduleinit.d std\boxer.d \
+        std\thread.d std\thread_helper.d std\moduleinit.d std\boxer.d \
         std\stream.d std\socket.d std\socketstream.d \
         std\perf.d std\openrj.d std\conv.d \
         std\zip.d std\cstream.d std\loader.d \
