diff --git a/include/thread.h b/include/thread.h
index 4426e0221848c043b1f8bd1c42a4ea4af769bac9..9dd985ee1dd2f3cd8dd7d6bc33ad23b18142e8ad 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -29,11 +29,11 @@ typedef struct _TEB
     WORD         flags;          /* 1c Flags */
     WORD         mutex_count;    /* 1e Win16 mutex count */
     DWORD        debug_context;  /* 20 Debug context */
-    DWORD       *ppriority;      /* 24 Pointer to current priority */
+    void        *tid;            /* 24 Thread id */
     HQUEUE16     queue;          /* 28 Message queue */
     WORD         pad1;           /* 2a */
     LPVOID      *tls_ptr;        /* 2c Pointer to TLS array */
-    struct _PDB *process;      /* 30 owning process (used by NT3.51 applets)*/
+    struct _PDB *process;        /* 30 owning process (used by NT3.51 applets)*/
 } TEB;
 
 /* Thread exception flags */
@@ -84,7 +84,6 @@ typedef struct _THDB
     /* The following are Wine-specific fields */
     int            socket;         /* Socket for server communication */
     unsigned int   seq;            /* Server sequence number */
-    void          *server_tid;     /* Server id for this thread */
     void         (*startup)(void); /* Thread startup routine */
     struct _THDB  *next;           /* Global thread list */
     DWORD          cleanup;        /* Cleanup service handle */
@@ -96,27 +95,38 @@ typedef struct _THDB
 /* The per-thread signal stack size */
 #define SIGNAL_STACK_SIZE  16384
 
-#ifdef __i386__
-/* On the i386, the current thread is in the %fs register */
-# define SET_CUR_THREAD(thdb) SET_FS((thdb)->teb_sel)
-#else
-extern THDB *pCurrentThread;
-# define SET_CUR_THREAD(thdb) (pCurrentThread = (thdb))
-#endif  /* __i386__ */
-
 
 /* scheduler/thread.c */
 extern THDB *THREAD_CreateInitialThread( struct _PDB *pdb, int server_fd );
 extern THDB *THREAD_Create( struct _PDB *pdb, DWORD flags, 
                             DWORD stack_size, BOOL alloc_stack16,
                             LPSECURITY_ATTRIBUTES sa, int *server_handle );
-extern THDB *THREAD_Current(void);
 extern BOOL THREAD_IsWin16( THDB *thdb );
 extern THDB *THREAD_IdToTHDB( DWORD id );
 
 /* scheduler/sysdeps.c */
 extern int SYSDEPS_SpawnThread( THDB *thread );
+extern void SYSDEPS_SetCurThread( THDB *thread );
 extern void SYSDEPS_ExitThread(void);
 extern TEB * WINAPI NtCurrentTeb(void);
 
+/* return the current thread TEB pointer */
+static inline TEB *CURRENT(void)
+{
+#ifdef __i386__
+    TEB *teb;
+    __asm__( ".byte 0x64\n\tmovl (0x18),%0" : "=r" (teb) );
+    return teb;
+#else
+    return NtCurrentTeb();
+#endif
+}
+
+/* return the current thread THDB pointer */
+static inline THDB *THREAD_Current(void)
+{
+    TEB *teb = CURRENT();
+    return (THDB *)((char *)teb - (int)&((THDB *)0)->teb);
+}
+
 #endif  /* __WINE_THREAD_H */
diff --git a/loader/task.c b/loader/task.c
index 61cb6df8ad57e01ec67537ff5bbbf63917430fac..8dca248c64903f3f4d8aa25fd270e5c51c556db2 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -66,8 +66,6 @@ static HANDLE TASK_ScheduleEvent = INVALID_HANDLE_VALUE;
 
 static void TASK_YieldToSystem( void );
 
-extern BOOL THREAD_InitDone;
-
 
 /***********************************************************************
  *	     TASK_InstallTHHook
@@ -239,7 +237,7 @@ static void TASK_CallToStart(void)
     NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
     SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
 
-    SET_CUR_THREAD( pTask->thdb );
+    SYSDEPS_SetCurThread( pTask->thdb );
     CLIENT_InitThread();
 
     /* Terminate the stack frame chain */
@@ -825,7 +823,7 @@ BOOL TASK_Reschedule(void)
     SYSLEVEL_ReleaseWin16Lock();
 
     hCurrentTask = hTask;
-    SET_CUR_THREAD( pNewTask->thdb );
+    SYSDEPS_SetCurThread( pNewTask->thdb );
     pNewTask->ss_sp = pNewTask->thdb->cur_stack;
 
     SYSLEVEL_RestoreWin16Lock();
@@ -1415,7 +1413,7 @@ void WINAPI GetTaskQueueES16( CONTEXT *context )
  */
 HTASK16 WINAPI GetCurrentTask(void)
 {
-    return THREAD_InitDone? PROCESS_Current()->task : 0;
+    return PROCESS_Current()->task;
 }
 
 DWORD WINAPI WIN16_GetCurrentTask(void)
diff --git a/scheduler/client.c b/scheduler/client.c
index 411427f5354143094daaf7adb8446b3be25f3b49..1ca19d2285288db2884ba96933838baa68910917 100644
--- a/scheduler/client.c
+++ b/scheduler/client.c
@@ -32,9 +32,9 @@
  *
  * Die on protocol errors or socket close
  */
-static void CLIENT_Die( THDB *thdb )
+static void CLIENT_Die(void)
 {
-    close( thdb->socket );
+    close( THREAD_Current()->socket );
     SYSDEPS_ExitThread();
 }
 
@@ -43,14 +43,13 @@ static void CLIENT_Die( THDB *thdb )
  */
 void CLIENT_ProtocolError( const char *err, ... )
 {
-    THDB *thdb = THREAD_Current();
     va_list args;
 
     va_start( args, err );
-    fprintf( stderr, "Client protocol error:%p: ", thdb->server_tid );
+    fprintf( stderr, "Client protocol error:%p: ", CURRENT()->tid );
     vfprintf( stderr, err, args );
     va_end( args );
-    CLIENT_Die( thdb );
+    CLIENT_Die();
 }
 
 
@@ -116,7 +115,11 @@ static void CLIENT_SendRequest_v( enum request req, int pass_fd,
 
     if ((ret = sendmsg( thdb->socket, &msghdr, 0 )) < len)
     {
-        if (ret == -1) perror( "sendmsg" );
+        if (ret == -1)
+        {
+            if (errno == EPIPE) CLIENT_Die();
+            perror( "sendmsg" );
+        }
         CLIENT_ProtocolError( "partial msg sent %d/%d\n", ret, len );
     }
     /* we passed the fd now we can close it */
@@ -193,10 +196,11 @@ static unsigned int CLIENT_WaitReply_v( int *len, int *passed_fd,
     while ((ret = recvmsg( thdb->socket, &msghdr, 0 )) == -1)
     {
         if (errno == EINTR) continue;
+        if (errno == EPIPE) CLIENT_Die();
         perror("recvmsg");
         CLIENT_ProtocolError( "recvmsg\n" );
     }
-    if (!ret) CLIENT_Die( thdb ); /* the server closed the connection; time to die... */
+    if (!ret) CLIENT_Die(); /* the server closed the connection; time to die... */
 
     /* sanity checks */
 
@@ -240,7 +244,7 @@ static unsigned int CLIENT_WaitReply_v( int *len, int *passed_fd,
 		    perror( "recv" );
 		    CLIENT_ProtocolError( "recv\n" );
 		}
-		if (!addlen) CLIENT_Die( thdb ); /* the server closed the connection; time to die... */
+		if (!addlen) CLIENT_Die(); /* the server closed the connection; time to die... */
 		if (len) *len += addlen;
 		remaining -= addlen;
 	    }
@@ -257,7 +261,7 @@ static unsigned int CLIENT_WaitReply_v( int *len, int *passed_fd,
             perror( "recv" );
             CLIENT_ProtocolError( "recv\n" );
         }
-        if (!addlen) CLIENT_Die( thdb ); /* the server closed the connection; time to die... */
+        if (!addlen) CLIENT_Die(); /* the server closed the connection; time to die... */
         remaining -= addlen;
     }
 
@@ -367,7 +371,7 @@ int CLIENT_InitThread(void)
     CLIENT_SendRequest( REQ_INIT_THREAD, -1, 1, &req, sizeof(req) );
     if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) return -1;
     thdb->process->server_pid = reply.pid;
-    thdb->server_tid = reply.tid;
+    thdb->teb.tid = reply.tid;
     return 0;
 }
 
diff --git a/scheduler/process.c b/scheduler/process.c
index 72a223151304cd0e06b28529bb929d3fc93a294f..eca3e0d34f656a537d20988b8284f9557ac8b470 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -606,7 +606,7 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
     if (!(thdb = THREAD_Create( pdb, 0L, size, hInstance == 0, tsa, &server_thandle ))) 
         goto error;
     info->hThread     = server_thandle;
-    info->dwThreadId  = (DWORD)thdb->server_tid;
+    info->dwThreadId  = (DWORD)thdb->teb.tid;
     thdb->startup     = PROCESS_Start;
 
     if (pModule->module32)
diff --git a/scheduler/sysdeps.c b/scheduler/sysdeps.c
index 4a0b21d39347f33b1fc7d4a8bfba29538da5782a..27d4734119efc521be85e80549ec09a33b4ab95c 100644
--- a/scheduler/sysdeps.c
+++ b/scheduler/sysdeps.c
@@ -54,6 +54,12 @@ extern int clone( int (*fn)(void *arg), void *stack, int flags, void *arg );
 # endif  /* CLONE_VM */
 #endif  /* HAVE_CLONE_SYSCALL */
 
+static int init_done;
+
+#ifndef __i386__
+static THDB *pCurrentThread;
+#endif
+
 
 #ifndef NO_REENTRANT_LIBC
 
@@ -72,11 +78,12 @@ int *__error()
 int *___errno()
 #endif
 {
-    THDB *thdb = THREAD_Current();
-    if (!thdb) return perrno;
+    THDB *thdb;
+    if (!init_done) return perrno;
+    thdb = THREAD_Current();
 #ifdef NO_REENTRANT_X11
     /* Use static libc errno while running in Xlib. */
-    if (X11DRV_CritSection.OwningThread == (HANDLE)thdb->server_tid)
+    if (X11DRV_CritSection.OwningThread == (HANDLE)thdb->teb.tid)
         return perrno;
 #endif
     return &thdb->thread_errno;
@@ -89,11 +96,12 @@ int *___errno()
  */
 int *__h_errno_location()
 {
-    THDB *thdb = THREAD_Current();
-    if (!thdb) return ph_errno;
+    THDB *thdb;
+    if (!init_done) return ph_errno;
+    thdb = THREAD_Current();
 #ifdef NO_REENTRANT_X11
     /* Use static libc h_errno while running in Xlib. */
-    if (X11DRV_CritSection.OwningThread == (HANDLE)thdb->server_tid)
+    if (X11DRV_CritSection.OwningThread == (HANDLE)thdb->teb.tid)
         return ph_errno;
 #endif
     return &thdb->thread_h_errno;
@@ -101,6 +109,23 @@ int *__h_errno_location()
 
 #endif /* NO_REENTRANT_LIBC */
 
+/***********************************************************************
+ *           SYSDEPS_SetCurThread
+ *
+ * Make 'thread' the current thread.
+ */
+void SYSDEPS_SetCurThread( THDB *thread )
+{
+#ifdef __i386__
+    /* On the i386, the current thread is in the %fs register */
+    SET_FS( thread->teb_sel );
+#else
+    /* FIXME: only works if there is no preemptive task-switching going on... */
+    pCurrentThread = thread;
+#endif  /* __i386__ */
+    init_done = 1;  /* now we can use threading routines */
+}
+
 /***********************************************************************
  *           SYSDEPS_StartThread
  *
@@ -108,10 +133,10 @@ int *__h_errno_location()
  */
 static void SYSDEPS_StartThread( THDB *thdb )
 {
-    SET_CUR_THREAD( thdb );
+    SYSDEPS_SetCurThread( thdb );
     CLIENT_InitThread();
     thdb->startup();
-    _exit(0);  /* should never get here */
+    SYSDEPS_ExitThread();  /* should never get here */
 }
 
 
@@ -197,12 +222,7 @@ void SYSDEPS_ExitThread(void)
 TEB * WINAPI NtCurrentTeb(void)
 {
 #ifdef __i386__
-    TEB *teb;
-
-    /* Get the TEB self-pointer */
-    __asm__( ".byte 0x64\n\tmovl (%1),%0"
-             : "=r" (teb) : "r" (&((TEB *)0)->self) );
-    return teb;
+    return CURRENT();
 #else
     return &pCurrentThread->teb;
 #endif  /* __i386__ */
diff --git a/scheduler/syslevel.c b/scheduler/syslevel.c
index 95c6eec117f910d21ca06abe1fe185417f541441..da715fe32bd1465e6abb47fb4d284c8243fb3b53 100644
--- a/scheduler/syslevel.c
+++ b/scheduler/syslevel.c
@@ -75,7 +75,7 @@ VOID WINAPI _EnterSysLevel(SYSLEVEL *lock)
     int i;
 
     TRACE("(%p, level %d): thread %p (fs %04x, pid %d) count before %ld\n", 
-                  lock, lock->level, thdb->server_tid, thdb->teb_sel, getpid(),
+                  lock, lock->level, thdb->teb.tid, thdb->teb_sel, getpid(),
                   thdb->sys_count[lock->level] );
 
     for ( i = 3; i > lock->level; i-- )
@@ -91,7 +91,7 @@ VOID WINAPI _EnterSysLevel(SYSLEVEL *lock)
     thdb->sys_mutex[lock->level] = lock;
 
     TRACE("(%p, level %d): thread %p (fs %04x, pid %d) count after  %ld\n",
-                  lock, lock->level, thdb->server_tid, thdb->teb_sel, getpid(), 
+                  lock, lock->level, thdb->teb.tid, thdb->teb_sel, getpid(), 
                   thdb->sys_count[lock->level] );
 
     if (lock == &Win16Mutex)
@@ -106,7 +106,7 @@ VOID WINAPI _LeaveSysLevel(SYSLEVEL *lock)
     THDB *thdb = THREAD_Current();
 
     TRACE("(%p, level %d): thread %p (fs %04x, pid %d) count before %ld\n", 
-                  lock, lock->level, thdb->server_tid, thdb->teb_sel, getpid(),
+                  lock, lock->level, thdb->teb.tid, thdb->teb_sel, getpid(),
                   thdb->sys_count[lock->level] );
 
     if ( thdb->sys_count[lock->level] <= 0 || thdb->sys_mutex[lock->level] != lock )
@@ -124,7 +124,7 @@ VOID WINAPI _LeaveSysLevel(SYSLEVEL *lock)
     LeaveCriticalSection( &lock->crst );
 
     TRACE("(%p, level %d): thread %p (fs %04x, pid %d) count after  %ld\n",
-                  lock, lock->level, thdb->server_tid, thdb->teb_sel, getpid(), 
+                  lock, lock->level, thdb->teb.tid, thdb->teb_sel, getpid(), 
                   thdb->sys_count[lock->level] );
 }
 
diff --git a/scheduler/thread.c b/scheduler/thread.c
index ee8bf3720a2bb19b8cda88462a5e0a90af68620f..6c184b14ae93ae08b23d957fc4b585ecb2c04fea 100644
--- a/scheduler/thread.c
+++ b/scheduler/thread.c
@@ -28,30 +28,12 @@
 
 DEFAULT_DEBUG_CHANNEL(thread)
 
-#ifndef __i386__
-THDB *pCurrentThread;
-#endif
-
-/* Is threading code initialized? */
-BOOL THREAD_InitDone = FALSE;
-
 /* THDB of the initial thread */
 static THDB initial_thdb;
 
 /* Global thread list (FIXME: not thread-safe) */
 THDB *THREAD_First = &initial_thdb;
 
-/***********************************************************************
- *           THREAD_Current
- *
- * Return the current thread THDB pointer.
- */
-THDB *THREAD_Current(void)
-{
-    if (!THREAD_InitDone) return NULL;
-    return (THDB *)((char *)NtCurrentTeb() - (int)&((THDB *)0)->teb);
-}
-
 /***********************************************************************
  *           THREAD_IsWin16
  */
@@ -72,7 +54,7 @@ THDB *THREAD_IdToTHDB( DWORD id )
     if (!id) return THREAD_Current();
     while (thdb)
     {
-        if ((DWORD)thdb->server_tid == id) return thdb;
+        if ((DWORD)thdb->teb.tid == id) return thdb;
         thdb = thdb->next;
     }
     /* Allow task handles to be used; convert to main thread */
@@ -202,8 +184,7 @@ THDB *THREAD_CreateInitialThread( PDB *pdb, int server_fd )
         MESSAGE("Could not allocate fs register for initial thread\n" );
         return NULL;
     }
-    SET_CUR_THREAD( &initial_thdb );
-    THREAD_InitDone = TRUE;
+    SYSDEPS_SetCurThread( &initial_thdb );
 
     /* Now proceed with normal initialization */
 
@@ -259,7 +240,7 @@ THDB *THREAD_Create( PDB *pdb, DWORD flags, DWORD stack_size, BOOL alloc_stack16
     request.inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
     CLIENT_SendRequest( REQ_NEW_THREAD, fd[1], 1, &request, sizeof(request) );
     if (CLIENT_WaitSimpleReply( &reply, sizeof(reply), NULL )) goto error;
-    thdb->server_tid = reply.tid;
+    thdb->teb.tid = reply.tid;
     *server_handle = reply.handle;
 
     /* Do the rest of the initialization */
@@ -321,7 +302,7 @@ HANDLE WINAPI CreateThread( SECURITY_ATTRIBUTES *sa, DWORD stack,
         CloseHandle( handle );
         return INVALID_HANDLE_VALUE;
     }
-    if (id) *id = (DWORD)thread->server_tid;
+    if (id) *id = (DWORD)thread->teb.tid;
     return handle;
 }
 
@@ -359,10 +340,7 @@ HANDLE WINAPI GetCurrentThread(void)
  */
 DWORD WINAPI GetCurrentThreadId(void)
 {
-    THDB *thdb = THREAD_Current();
-    assert( thdb );
-    assert( thdb->server_tid );
-    return (DWORD)thdb->server_tid;
+    return (DWORD)CURRENT()->tid;
 }
 
 
@@ -391,12 +369,8 @@ void WINAPI SetLastError(
     DWORD error) /* [in] Per-thread error code */
 {
     THDB *thread = THREAD_Current();
-    /* This one must work before we have a thread (FIXME) */
-
     TRACE("%p error=0x%lx\n",thread,error);
-
-    if (thread)
-      thread->last_error = error;
+    thread->last_error = error;
 }
 
 
diff --git a/windows/queue.c b/windows/queue.c
index d27ec951163cb8315481e16e5a8f5e2c173830bf..f4ae0d7d4f4958601811206d5a722234034776c8 100644
--- a/windows/queue.c
+++ b/windows/queue.c
@@ -1370,7 +1370,7 @@ DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
     if (!queue) return 0;
 
     if ( process ) *process = (DWORD)queue->thdb->process->server_pid;
-    retvalue = (DWORD)queue->thdb->server_tid;
+    retvalue = (DWORD)queue->thdb->teb.tid;
 
     QUEUE_Unlock( queue );
     return retvalue;
diff --git a/windows/winproc.c b/windows/winproc.c
index 4e4c351c346573be688dab95ea42794483550adb..1f0b4b1b7e4e5f35e8f87a7c1dd3286d91af4181 100644
--- a/windows/winproc.c
+++ b/windows/winproc.c
@@ -1114,7 +1114,7 @@ INT WINPROC_MapMsg16To32A( UINT16 msg16, WPARAM16 wParam16, UINT *pmsg32,
 	     message queues.
 	  */
 	  HTASK16 htask = (HTASK16) *plparam;
-	  DWORD idThread = (DWORD)((TDB*)GlobalLock16(htask))->thdb->server_tid;
+	  DWORD idThread = (DWORD)((TDB*)GlobalLock16(htask))->thdb->teb.tid;
 	  *plparam = (LPARAM) idThread;
 	}
 	return 1;