Index: trunk/src/emx/include/InnoTekLIBC/backend.h
===================================================================
--- trunk/src/emx/include/InnoTekLIBC/backend.h	(revision 1287)
+++ trunk/src/emx/include/InnoTekLIBC/backend.h	(revision 1287)
@@ -0,0 +1,81 @@
+/* $Id$ */
+/** @file
+ *
+ * LIBC - Backend header.
+ *
+ * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of InnoTek LIBC.
+ *
+ * InnoTek LIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * InnoTek LIBC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with InnoTek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __InnoTekLIBC_backend_h__
+#define __InnoTekLIBC_backend_h__
+
+#ifndef __LIBC_THREAD_DECLARED
+#define __LIBC_THREAD_DECLARED
+typedef struct __libc_thread *__LIBC_PTHREAD, **__LIBC_PPTHREAD;
+#endif
+
+
+/** @group __libc_Back_thread   LIBC Backend - Threads
+ * @{ */
+
+/**
+ * Initiatlize a new thread structure.
+ *
+ * @param   pThrd   Pointer to the thread structure.
+ */
+void __libc_Back_threadInit(__LIBC_PTHREAD pThrd);
+
+/**
+ * Called before the thread structure is freed so the backend
+ * can cleanup its members.
+ *
+ * @param   pThrd   Pointer to the thread in  question.
+ */
+void __libc_Back_threadCleanup(__LIBC_PTHREAD pThrd);
+
+/**
+ * Called in the context of the newly started thread to register
+ * exception handler and to do other init stuff.
+ *
+ * @param   pExpRegRec  Exception handler registration record on the stack.
+ *                      To be used for any exception handler registration.
+ */
+void __libc_Back_threadStartup(void *pExpRegRec);
+
+/**
+ * Called in the context of the thread which is to be terminated to
+ * unregister exception handler and to do other final term stuff.
+ *
+ * @param   pExpRegRec  Exception handler registration record on the stack.
+ *                      To be used for any exception handler registration.
+ * @remark  This is called after __libc_Back_threadCleanup().
+ * @remark  It is not called by thread which calls _endthread(), nor for the
+ *          main thread.
+ */
+void __libc_Back_threadEnd(void *pExpRegRec);
+
+/** @} */
+
+#if defined (__cplusplus)
+}
+#endif
+
+#endif /* not _EMX_SYSCALLS_H */
Index: trunk/src/emx/include/InnoTekLIBC/thread.h
===================================================================
--- trunk/src/emx/include/InnoTekLIBC/thread.h	(revision 1287)
+++ trunk/src/emx/include/InnoTekLIBC/thread.h	(revision 1287)
@@ -0,0 +1,266 @@
+/* $Id$ */
+/** @file
+ *
+ * LIBC Thread Handling.
+ *
+ * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of InnoTek LIBC.
+ *
+ * InnoTek LIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * InnoTek LIBC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with InnoTek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef __InnoTekLIBC_thread_h__
+#define __InnoTekLIBC_thread_h__
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** Maximum number of TLS variables supported by LIBC.
+ * The current limit (128) is higher than for instance WinNT. But if
+ * you think we're wasting space, look at the page padding of the thread
+ * structure... */
+#define __LIBC_TLS_MAX      128
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <sys/cdefs.h>
+#include <time.h>                       /* struct tm; */
+#include <signal.h>
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+struct _uheap;
+
+/**
+ * Per thread structure for LIBC.
+ *
+ * This structure contains buffers and variables which in a single threaded
+ * LIBC would be static.
+ *
+ * Members most frequently used have been put together at the front.
+ */
+typedef struct __libc_threadCurrentSlow
+{
+    /** errno value. (Comes first, see errnofun.s.) */
+    int             iErrNo;
+    /** Default tiled heap. */
+    struct _uheap * pTiledHeap;
+    /** Default regular heap. */
+    struct _uheap * pRegularHeap;
+    /** Old TLS variable. */
+    void           *pvThreadStoreVar;
+    /** New TLS variable array. */
+    void           *apvTLS[__LIBC_TLS_MAX];
+
+    /** Current rand() seed value. */
+    unsigned int    iRand;
+    /** Buffer used by asctime() and indirectly by ctime() . (Adds two 2 bytes for padding). */
+    char            szAscTimeAndCTimeBuf[26+2];
+    /** Buffer used by gmtime() and localtime(). */
+    struct tm       GmTimeAndLocalTimeBuf;
+    /** Buffer used by tmpnam(). */
+    char            szTmpNamBuf[16];
+    /** Current posistion of strtok(). */
+    unsigned char  *pszStrTokPos;
+    /** Buffer used by strerror() to format unknown error values. */
+    char            szStrErrorBuf[28];
+    /** Buffer used by _getvol(). */
+    char            szVolLabelBuf[12];
+    /** Buffer used by ttyname(). */
+    char            szTTYNameBuf[32];
+
+    /** Data used by the backends. */
+    union __libc_backend_data
+    {
+        struct __libc_sys
+        {
+            /** Blocked signal mask. */
+            sigset_t            sig_blocked;
+            /** Pending signal mask. */
+            sigset_t            sig_pending;
+            /** Signal actions. */
+            struct sigaction    signals[NSIG];
+
+            /** Directory find data entry.
+             * Used by __findfirst() and __findnext(). */
+            struct find_data
+            {
+                /** Directory handle. HDIR_CREATE if no session opened. */
+                unsigned long   hdir;
+                /** Type of buffer content. FIL_STANDARDL or FIL_STANDARD,
+                 * i.e. FILEFINDBUF3 or FILEFINDBUF3L. */
+                unsigned long   fType;
+                /** Number of files left in the buffer. */
+                unsigned long   cFiles;
+                /** Pointer to the next entry. Don't test on this, test on cFiles! */
+                const char     *pchNext;
+                /** Buffer. */
+                char            achBuffer[2048];
+            } fd;
+        } sys;
+    } b;
+
+    /** Data used in special periods of a threads life. */
+    union
+    {
+        struct __libc_thread_startup
+        {
+            /** Thread argument. */
+            void    *pvArg;
+            /** Thread routine. */
+            void   (*pfnStart)(void *pvArg);
+        } startup;
+    } u;
+} __LIBC_THREAD;
+
+#ifndef __LIBC_THREAD_DECLARED
+#define __LIBC_THREAD_DECLARED
+typedef struct __libc_threadCurrentSlow *__LIBC_PTHREAD, **__LIBC_PPTHREAD;
+#endif
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+__BEGIN_DECLS
+/** Pointer to the TLS ULONG (OS/2 rules) which will point to the LIBC thread
+ * structure for the current thread.
+ * The TLS ULONG is allocated by __init_dll(). The thread structure it points to
+ * is allocated on demand. */
+extern __LIBC_PPTHREAD  __libc_gpTLS;
+__END_DECLS
+
+
+/*******************************************************************************
+*   External Functions                                                         *
+*******************************************************************************/
+__BEGIN_DECLS
+/**
+ * Get the thread structure for the current thread.
+ *
+ * Will automatically allocate a thread structure if such is not yet done
+ * for the thread.
+ *
+ * @returns pointer to current thread struct.
+
+ * @remark  This API is considered to be internal to LIBC and is thus not
+ *          exposed in the shared library version of LIBC. Please don't call it.
+ *          External LIBs should use the __libc_TLS*() API.
+ */
+#define __libc_threadCurrent()   (*__libc_gpTLS ? *__libc_gpTLS : __libc_threadCurrentSlow())
+
+
+/**
+ * Get the thread structure for the current thread.
+ *
+ * Used by the __libc_threadCurrent() macro for allocating a thread structure for the
+ * current thread when such doesn't exist.
+ *
+ * @returns pointer to current thread struct.
+
+ * @remark  This API is considered to be internal to LIBC and is thus not
+ *          exposed in the shared library version of LIBC. Please don't call it.
+ *          External LIBs should use the __libc_TLS*() API.
+ */
+__LIBC_PTHREAD __libc_threadCurrentSlow(void);
+
+
+/**
+ * Get the thread structure for the current thread.
+ *
+ * Do not create anything automatically.
+ *
+ * @returns pointer to current thread struct.
+ * @returns NULL if not initiated.
+ *
+ * @remark  This API is considered to be internal to LIBC and is thus not
+ *          exposed in the shared library version of LIBC. Please don't call it.
+ *          External LIBs should use the __libc_TLS*() API.
+ */
+#define __libc_threadCurrentNoAuto()   (__libc_gpTLS ? *__libc_gpTLS : NULL)
+
+
+/**
+ * Allocate and initialize a thread structure for a thread which is yet
+ * to be created.
+ *
+ * @returns Pointer to thread structure.
+ * @returns NULL on error. errno set.
+ */
+__LIBC_PTHREAD __libc_threadAlloc(void);
+
+
+/**
+ * Free a thread structure.
+ *
+ * @param   pThrd   Pointer to the thread structure to free.
+ *                  Must be valid.
+ * @remark  If pThrd is for the current thread the thread must be
+ *          in the very final termination stage.
+ */
+void    __libc_threadFree(__LIBC_PTHREAD pThrd);
+
+
+/** @group InnoTek LIBC Thread Local Storage
+ * @{
+ */
+
+/**
+ * Allocates a TLS entry.
+ *
+ * @returns index of the allocated TLS index.
+ * @returns -1 on failure. errno set.
+ */
+int     __libc_TLSAlloc(void);
+
+/**
+ * Frees a TLS entry allocated by __libc_TLSAlloc().
+ *
+ * @returns 0 on success.
+ * @returns -1 on failure. errno set.
+ * @param   iTLSIndex   Value returned by __libc_TLSAlloc().
+ */
+int     __libc_TLSFree(int iIndex);
+
+/**
+ * Get the value stored in an allocated TLS entry.
+ *
+ * @returns value in given TLS entry.
+ * @returns NULL on failure with errno set.
+ * @param   iTLSIndex   Value returned by __libc_TLSAlloc().
+ */
+void *  __libc_TLSGet(int iIndex);
+
+/**
+ * Set the value stored in an allocated TLS entry.
+ *
+ * @returns 0 on success.
+ * @returns -1 on failure. errno set.
+ * @param   iTLSIndex   Value returned by __libc_TLSAlloc().
+ * @param   pvValue     Value to store.
+ */
+int     __libc_TLSSet(int iIndex, void *pvValue);
+
+/** @} */
+__END_DECLS
+
+#endif
Index: trunk/src/emx/include/emx/syscalls.h
===================================================================
--- trunk/src/emx/include/emx/syscalls.h	(revision 1286)
+++ trunk/src/emx/include/emx/syscalls.h	(revision 1287)
@@ -136,5 +136,5 @@
 int __dup (int handle);
 int __dup2 (int handle1, int handle2);
-int __endthread (int tid);
+int __endthread (void *pvThrd);
 int __execname (char *buf, size_t bufsize);
 void __exit (int ret) __attribute__ ((__noreturn__));
@@ -171,5 +171,4 @@
 int __imphandle (int handle);
 int __impsockhandle (int handle, int flags);
-int __initthread (void *preg);
 int __ioctl1 (int handle, int code);
 int __ioctl2 (int handle, unsigned long request, int arg);
@@ -226,6 +225,4 @@
 int __write (int handle, __const__ void *buf, size_t nbyte);
 
-
-
 #if defined (__cplusplus)
 }
Index: trunk/src/emx/include/emx/thread.h
===================================================================
--- trunk/src/emx/include/emx/thread.h	(revision 1286)
+++ trunk/src/emx/include/emx/thread.h	(revision 1287)
@@ -1,41 +1,1 @@
-/* emx/thread.h (emx+gcc) */
-
-#ifndef _EMX_THREAD_H
-#define _EMX_THREAD_H
-
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-#include <time.h> /* struct tm; */
-
-struct _uheap;
-
-struct _thread
-{
-  int             _th_errno;                /* comes first, cf. errnofun.s */
-  void          * _th_arg;
-  void          (*_th_start)(void *);
-  unsigned char * _th_strtok_ptr;
-  char            _th_asctime_buf[26+2];    /* 2 chars for padding */
-  char            _th_tmpnam_buf[16];       /* cf. stdio.h */
-  struct tm       _th_gmtime_buf;
-  unsigned int    _th_rand;                 /* Used by rand() */
-  void          * _th_store;                /* Pointer to user data */
-  char            _th_vollabel[12];         /* Used by _getvol() */
-  char            _th_error[28];            /* Used by strerror() */
-  struct _uheap * _th_rheap;                /* Default regular heap */
-  struct _uheap * _th_theap;                /* Default tiled heap */
-  char            _th_ttyname[32];          /* Used by ttyname() */
-  char            _th_inetntoa[16];         /* Used by inetntoa() */
-  int             _th_reserved[974];        /* 4096 bytes, total */
-};
-
-struct _thread *_thread (void);
-
-
-#if defined (__cplusplus)
-}
-#endif
-
-#endif /* not _EMX_THREAD_H */
+#error "This file is dead. use InnoTekLIBC/thread.h!"
Index: trunk/src/emx/include/emx/umalloc.h
===================================================================
--- trunk/src/emx/include/emx/umalloc.h	(revision 1286)
+++ trunk/src/emx/include/emx/umalloc.h	(revision 1287)
@@ -606,7 +606,7 @@
 /* Each thread has its own default heap. */
 
-#define _UM_DEFAULT_REGULAR_HEAP tp->_th_rheap
-#define _UM_DEFAULT_TILED_HEAP   tp->_th_theap
-#define _UM_MT_DECL              struct _thread *tp = _thread ();
+#define _UM_DEFAULT_REGULAR_HEAP pThrd->pRegularHeap
+#define _UM_DEFAULT_TILED_HEAP   pThrd->pTiledHeap
+#define _UM_MT_DECL              __LIBC_PTHREAD pThrd = __libc_threadCurrent();
 
 /* Note that _um_regular_heap is declared in <umalloc.h>.
Index: trunk/src/emx/src/lib/io/tmpnam.c
===================================================================
--- trunk/src/emx/src/lib/io/tmpnam.c	(revision 1286)
+++ trunk/src/emx/src/lib/io/tmpnam.c	(revision 1287)
@@ -4,5 +4,5 @@
 #include "libc-alias.h"
 #include <stdio.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 #include "_tmp.h"
 
@@ -12,6 +12,6 @@
   if (string == NULL)
     {
-      struct _thread *tp = _thread ();
-      string = tp->_th_tmpnam_buf;
+      __LIBC_PTHREAD pThrd = __libc_threadCurrent ();
+      string = pThrd->szTmpNamBuf;
     }
   if (_tmpidxnam (string) >= 0)
Index: trunk/src/emx/src/lib/io/ttyname.c
===================================================================
--- trunk/src/emx/src/lib/io/ttyname.c	(revision 1286)
+++ trunk/src/emx/src/lib/io/ttyname.c	(revision 1287)
@@ -4,12 +4,12 @@
 #include <unistd.h>
 #include <emx/syscalls.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 char *_STD(ttyname) (int handle)
 {
-  struct _thread *tp = _thread ();
+  __LIBC_PTHREAD pThrd = __libc_threadCurrent ();
 
-  if (__ttyname (handle, tp->_th_ttyname, sizeof (tp->_th_ttyname)) == 0)
-    return tp->_th_ttyname;
+  if (__ttyname (handle, pThrd->szTTYNameBuf, sizeof (pThrd->szTTYNameBuf)) == 0)
+    return pThrd->szTTYNameBuf;
   else
     return NULL;
Index: trunk/src/emx/src/lib/libc.def
===================================================================
--- trunk/src/emx/src/lib/libc.def	(revision 1286)
+++ trunk/src/emx/src/lib/libc.def	(revision 1287)
@@ -46,5 +46,5 @@
     "__streamv_rmutex" @26
     "__streamvec_head" @27
-    "__thread_tab" @28
+; fixme "" @28
     "__tmpidx" @29
     "__tzi" @30
@@ -76,5 +76,5 @@
     "__HUGE_VAL" @103
     "__LHUGE_VAL" @104
-    "___alloc_thread" @105
+; fixme    "___alloc_thread" @105
     "___atod" @106
     "___chdir" @107
@@ -89,5 +89,5 @@
     "___dup" @116
     "___dup2" @117
-    "___endthread" @118
+; fixme    "___endthread" @118
     "___exit" @119
     "___fcntl" @120
@@ -110,5 +110,5 @@
     "___init_app" @137
     "___init_dll" @138
-    "___initthread" @139
+; fixme    "___initthread" @139
     "___ioctl1" @140
     "___ioctl2" @141
@@ -134,5 +134,5 @@
     "___lseek" @161
     "___mkdir" @162
-    "___newthread" @163
+; fixme    "___newthread" @163
     "___open" @164
     "___pipe" @165
@@ -741,9 +741,9 @@
     "__swchar" @768
     "__sys_dump_heap_objs" @769
-    "__sys_exception" @770
+    "_sys_exception" @770
     "__tcalloc" @771
     "__tfree" @772
     "__theapmin" @773
-    "__thread" @774
+; fixme    "__thread" @774
     "__threadstore" @775
     "__tmalloc" @776
@@ -1078,4 +1078,12 @@
     "___umoddi3"                                @1103
     "__alloca"                                  @1104
+    "__std_usleep" @1105
 
-    "__std_usleep" @1105
+    "___libc_Back_threadCleanup" @1106
+    "___libc_Back_threadEnd" @1107
+    "___libc_Back_threadInit" @1108
+    "___libc_Back_threadStartup" @1109
+    "___libc_TLSAlloc" @1110
+    "___libc_TLSFree" @1111
+    "___libc_TLSGet" @1112
+    "___libc_TLSSet" @1113
Index: trunk/src/emx/src/lib/malloc/calloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/calloc.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/calloc.c	(revision 1287)
@@ -9,5 +9,5 @@
 #include <sys/rmutex.h>
 #include <emx/umalloc.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 void *_STD(calloc) (size_t count, size_t size)
Index: trunk/src/emx/src/lib/malloc/heapchk.c
===================================================================
--- trunk/src/emx/src/lib/malloc/heapchk.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/heapchk.c	(revision 1287)
@@ -9,5 +9,5 @@
 #include <sys/rmutex.h>
 #include <emx/umalloc.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 int _heapchk (void)
Index: trunk/src/emx/src/lib/malloc/heapmin.c
===================================================================
--- trunk/src/emx/src/lib/malloc/heapmin.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/heapmin.c	(revision 1287)
@@ -9,5 +9,5 @@
 #include <sys/rmutex.h>
 #include <emx/umalloc.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 int _heapmin (void)
Index: trunk/src/emx/src/lib/malloc/heapset.c
===================================================================
--- trunk/src/emx/src/lib/malloc/heapset.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/heapset.c	(revision 1287)
@@ -9,5 +9,5 @@
 #include <sys/rmutex.h>
 #include <emx/umalloc.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 int _heapset (unsigned fill)
Index: trunk/src/emx/src/lib/malloc/heapwalk.c
===================================================================
--- trunk/src/emx/src/lib/malloc/heapwalk.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/heapwalk.c	(revision 1287)
@@ -5,5 +5,5 @@
 #include <umalloc.h>
 #include <emx/umalloc.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 int _heap_walk (_um_callback1 *callback)
Index: trunk/src/emx/src/lib/malloc/initr.c
===================================================================
--- trunk/src/emx/src/lib/malloc/initr.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/initr.c	(revision 1287)
@@ -5,5 +5,5 @@
 #include <emx/umalloc.h>
 #include <sys/smutex.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 /** This is the default regular heap. */
Index: trunk/src/emx/src/lib/malloc/initt.c
===================================================================
--- trunk/src/emx/src/lib/malloc/initt.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/initt.c	(revision 1287)
@@ -4,5 +4,5 @@
 #include <emx/umalloc.h>
 #include <sys/smutex.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 /** This is the default tiled heap. */
Index: trunk/src/emx/src/lib/malloc/malloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/malloc.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/malloc.c	(revision 1287)
@@ -9,5 +9,5 @@
 #include <sys/rmutex.h>
 #include <emx/umalloc.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 void *_STD(malloc) (size_t size)
Index: trunk/src/emx/src/lib/malloc/posix_memalign.c
===================================================================
--- trunk/src/emx/src/lib/malloc/posix_memalign.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/posix_memalign.c	(revision 1287)
@@ -28,5 +28,5 @@
 #include <umalloc.h>
 #include <emx/umalloc.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 #include <assert.h>
 
Index: trunk/src/emx/src/lib/malloc/tcalloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/tcalloc.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/tcalloc.c	(revision 1287)
@@ -9,5 +9,5 @@
 #include <sys/rmutex.h>
 #include <emx/umalloc.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 void *_tcalloc (size_t count, size_t size)
Index: trunk/src/emx/src/lib/malloc/theapmin.c
===================================================================
--- trunk/src/emx/src/lib/malloc/theapmin.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/theapmin.c	(revision 1287)
@@ -9,5 +9,5 @@
 #include <sys/rmutex.h>
 #include <emx/umalloc.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 int _theapmin (void)
Index: trunk/src/emx/src/lib/malloc/tmalloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/tmalloc.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/tmalloc.c	(revision 1287)
@@ -9,5 +9,5 @@
 #include <sys/rmutex.h>
 #include <emx/umalloc.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 void *_tmalloc (size_t size)
Index: trunk/src/emx/src/lib/malloc/trealloc.c
===================================================================
--- trunk/src/emx/src/lib/malloc/trealloc.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/trealloc.c	(revision 1287)
@@ -9,5 +9,5 @@
 #include <sys/rmutex.h>
 #include <emx/umalloc.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 void *_trealloc (void *block, size_t new_size)
Index: trunk/src/emx/src/lib/malloc/udefault.c
===================================================================
--- trunk/src/emx/src/lib/malloc/udefault.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/udefault.c	(revision 1287)
@@ -9,5 +9,5 @@
 #include <sys/rmutex.h>
 #include <emx/umalloc.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 Heap_t _udefault (Heap_t h)
Index: trunk/src/emx/src/lib/malloc/utdefaul.c
===================================================================
--- trunk/src/emx/src/lib/malloc/utdefaul.c	(revision 1286)
+++ trunk/src/emx/src/lib/malloc/utdefaul.c	(revision 1287)
@@ -9,5 +9,5 @@
 #include <sys/rmutex.h>
 #include <emx/umalloc.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 Heap_t _utdefault (Heap_t h)
Index: trunk/src/emx/src/lib/misc/getvol.c
===================================================================
--- trunk/src/emx/src/lib/misc/getvol.c	(revision 1286)
+++ trunk/src/emx/src/lib/misc/getvol.c	(revision 1287)
@@ -4,5 +4,5 @@
 #include <stdlib.h>
 #include <string.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 #include <emx/syscalls.h>
 #define INCL_DOSFILEMGR
@@ -13,5 +13,5 @@
 char *_getvol (char drive)
 {
-  struct _thread *tp = _thread();
+  __LIBC_PTHREAD pThrd = __libc_threadCurrent();
   FS_VAR();
 
@@ -33,6 +33,4 @@
   if (rc != 0)
     return NULL;
-  strcpy (tp->_th_vollabel, fsinfo.vol.szVolLabel);
-
-  return tp->_th_vollabel;
+  return strcpy (pThrd->szVolLabelBuf, fsinfo.vol.szVolLabel);
 }
Index: trunk/src/emx/src/lib/misc/rand.c
===================================================================
--- trunk/src/emx/src/lib/misc/rand.c	(revision 1286)
+++ trunk/src/emx/src/lib/misc/rand.c	(revision 1287)
@@ -3,16 +3,16 @@
 #include "libc-alias.h"
 #include <stdlib.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 int _STD(rand) (void)
 {
-  struct _thread *tp = _thread();
-  tp->_th_rand = tp->_th_rand * 69069 + 5;
-  return (tp->_th_rand >> 16) & 0x7fff;
+  __LIBC_PTHREAD pThrd = __libc_threadCurrent();
+  pThrd->iRand = pThrd->iRand * 69069 + 5;
+  return (pThrd->iRand >> 16) & 0x7fff;
 }
 
 void _STD(srand) (unsigned int seed)
 {
-  struct _thread *tp = _thread();
-  tp->_th_rand = seed;
+  __LIBC_PTHREAD pThrd = __libc_threadCurrent();
+  pThrd->iRand = seed;
 }
Index: trunk/src/emx/src/lib/process/386/_errno.s
===================================================================
--- trunk/src/emx/src/lib/process/386/_errno.s	(revision 1286)
+++ trunk/src/emx/src/lib/process/386/_errno.s	(revision 1287)
@@ -12,8 +12,9 @@
 __errno:
 __errno_fun:
-	fs
-	movl    12, %eax                /* ptib2 */
-	movl    0(%eax), %eax           /* TID */
-	movl    __thread_tab(,%eax,4), %eax
-/	addl    $0, %eax                /* address of errno */
+    movl    ___libc_gpTLS, %eax
+    movl    (%eax), %eax
+    orl     %eax, %eax
+    jnz     done
+    call    ___libc_threadCurrentSlow
+done:
 	EPILOGUE(_errno)
Index: trunk/src/emx/src/lib/process/386/thread.s
===================================================================
--- trunk/src/emx/src/lib/process/386/thread.s	(revision 1286)
+++ 	(revision )
@@ -1,26 +1,0 @@
-/ thread.s (emx+gcc) -- Copyright (c) 1992-1996 by Eberhard Mattes
-
-#include <emx/asm386.h>
-
-	.globl  __thread
-
-	.text
-
-	ALIGN
-
-__thread:
-	fs
-	movl    12, %eax                /* ptib2 */
-	movl    0(%eax), %edx           /* TID */
-	movl    __thread_tab(,%edx,4), %eax
-	testl   %eax, %eax
-	jnz     Lreturn
-
-	pushl   %edx
-	call    ___alloc_thread
-	popl    %edx
-	testl   %eax, %eax
-	jz      Lreturn
-	movl    %eax, __thread_tab(,%edx,4)
-
-Lreturn:EPILOGUE(_thread)
Index: trunk/src/emx/src/lib/process/beginthr.c
===================================================================
--- trunk/src/emx/src/lib/process/beginthr.c	(revision 1286)
+++ trunk/src/emx/src/lib/process/beginthr.c	(revision 1287)
@@ -5,6 +5,4 @@
 #include <string.h>
 #include <errno.h>
-#include <emx/thread.h>
-#include <emx/syscalls.h>
 #define INCL_DOSPROCESS
 #define INCL_DOSERRORS
@@ -12,132 +10,88 @@
 #define INCL_FSMACROS
 #include <os2emx.h>
-
-#define MAX_THREADS 1024
-
-static struct _thread thread_1 =
-{
-  0,                            /* _th_errno */
-  NULL,                         /* _th_arg */
-  NULL,                         /* _th_start */
-  NULL,                         /* _th_strtok_ptr (must be NULL) */
-  {0},                          /* _th_asctime_buf */
-  {0},                          /* _th_tmpnam_buf */
-  {0},                          /* _th_gmtime_buf */
-  1,                            /* _th_rand */
-  NULL,                         /* _th_store */
-  "",                           /* _th_vollabel */
-  "",                           /* _th_error */
-  NULL,                         /* _th_rheap */
-  NULL,                         /* _th_theap */
-  ""                            /* _th_ttyname */
-};
-
-struct _thread *_thread_tab[MAX_THREADS+1] = {NULL, &thread_1};
+#include <emx/syscalls.h>
+#include <InnoTekLIBC/thread.h>
+#include <InnoTekLIBC/backend.h>
 
 
-struct _thread *__alloc_thread (void); /* used in thread.s */
+/**
+ * Thread wrapper routine.
+ *
+ * @param   pThrd   Pointer to thread structure allocated for this thread.
+ */
+static void _System threadWrapper(__LIBC_PTHREAD pThrd)
+{
+    int                         tid;
+    EXCEPTIONREGISTRATIONRECORD reg;
+    FS_VAR();
 
-struct _thread *__alloc_thread (void)
-{
-  struct _thread *tp;
-  ULONG rc;
-  FS_VAR();
+    __libc_Back_threadStartup(&reg);
+    pThrd->u.startup.pfnStart(pThrd->u.startup.pvArg);
 
-  FS_SAVE_LOAD();
-  rc = DosAllocMem ((PPVOID)&tp, sizeof (struct _thread),
-                    PAG_COMMIT|PAG_READ|PAG_WRITE);
-  FS_RESTORE();
-  if (rc != 0)
-    return NULL;
-  memset (tp, 0, sizeof (struct _thread));
-  tp->_th_rand = 1;             /* Initialize rand() */
-  return tp;
+    FS_SAVE_LOAD();
+    tid = _gettid();
+    __libc_threadFree(pThrd);
+    __libc_Back_threadEnd(&reg);
+    for (;;)
+        DosExit(tid == 1 ? EXIT_PROCESS : EXIT_THREAD, 0);
 }
 
 
-static void start_thread (struct _thread *tp)
+int _beginthread(void (*pfnStart)(void *), void *pvStack, unsigned cbStack, void *pvArg)
 {
-  EXCEPTIONREGISTRATIONRECORD reg;
+    APIRET          rc;
+    TID             tid;
+    __LIBC_PTHREAD  pThrd;
+    FS_VAR();
 
-  __initthread (&reg);
-  tp->_th_start (tp->_th_arg);
-  _endthread();
+    /*
+     * Allocate a thread structure.
+     */
+    pThrd = __libc_threadAlloc();
+    if (!pThrd)
+    {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    /*
+     * Set the startup thread info and create a new thread.
+     */
+    pThrd->u.startup.pfnStart = pfnStart;
+    pThrd->u.startup.pvArg    = pvArg;
+    FS_SAVE_LOAD();
+    rc = DosCreateThread(&tid,
+                         (PFNTHREAD)threadWrapper,
+                         (ULONG)pThrd,
+                         CREATE_READY | STACK_COMMITTED,
+                         cbStack);
+    FS_RESTORE();
+    if (!rc)
+        return tid;
+
+    /*
+     * Set errno and cleanup.
+     */
+    if (rc == ERROR_NOT_ENOUGH_MEMORY)
+        errno = ENOMEM;
+    else if (rc == ERROR_MAX_THRDS_REACHED)
+        errno = EAGAIN;
+    else
+        errno = EINVAL;
+    __libc_threadFree(pThrd);
+    return -1;
 }
 
 
-int _beginthread (void (*start)(void *arg), void *stack, unsigned stack_size,
-                  void *arg_list)
+void _endthread(void)
 {
-  ULONG rc;
-  TID tid;
-  struct _thread *tp;
-  FS_VAR();
+    __LIBC_PTHREAD  pThrd = __libc_threadCurrent();
+    int             tid;
+    FS_VAR();
 
-  tp = __alloc_thread ();
-  if (tp == NULL)
-    {
-      errno = ENOMEM;
-      return -1;
-    }
-  tp->_th_start = start;
-  tp->_th_arg = arg_list;
-  FS_SAVE_LOAD();
-  rc = DosCreateThread (&tid, (PFNTHREAD)start_thread, (ULONG)tp,
-                        CREATE_SUSPENDED | STACK_COMMITTED, stack_size);
-  if (rc != 0)
-    {
-      if (rc == ERROR_NOT_ENOUGH_MEMORY)
-        errno = ENOMEM;
-      else if (rc == ERROR_MAX_THRDS_REACHED)
-        errno = EAGAIN;
-      else
-        errno = EINVAL;
-      DosFreeMem (tp);
-      FS_RESTORE();
-      return -1;
-    }
-  if (tid > MAX_THREADS)
-    {
-      DosKillThread (tid);
-      errno = EAGAIN;
-      DosFreeMem (tp);
-      FS_RESTORE();
-      return -1;
-    }
-  if (__newthread (tid) != 0)
-    {
-      DosKillThread (tid);
-      DosFreeMem (tp);
-      FS_RESTORE();
-      return -1;
-    }
-  _thread_tab[tid] = tp;
-  rc = DosResumeThread (tid);
-  if (rc != 0)
-    {
-      errno = ESRCH;
-      DosFreeMem (tp);
-      FS_RESTORE();
-      return -1;
-    }
-  FS_RESTORE();
-  return tid;
+    FS_SAVE_LOAD();
+    tid = _gettid();
+    __libc_threadFree(pThrd);
+    for (;;)
+        DosExit(tid == 1 ? EXIT_PROCESS : EXIT_THREAD, 0);
 }
-
-
-void _endthread (void)
-{
-  struct _thread *tp;
-  int tid;
-  FS_VAR();
-
-  tid = _gettid ();
-  tp = _thread ();
-  FS_SAVE_LOAD();
-  if (tp != &thread_1)
-    DosFreeMem (tp);
-  _thread_tab[tid] = NULL;
-  __endthread (tid);
-  for (;;)
-    DosExit ((tid == 1 ? EXIT_PROCESS : EXIT_THREAD), 0);
-}
Index: trunk/src/emx/src/lib/process/thread_internals.c
===================================================================
--- trunk/src/emx/src/lib/process/thread_internals.c	(revision 1287)
+++ trunk/src/emx/src/lib/process/thread_internals.c	(revision 1287)
@@ -0,0 +1,119 @@
+/* $Id$ */
+/** @file
+ *
+ * LIBC - Thread internals.
+ *
+ * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of InnoTek LIBC.
+ *
+ * InnoTek LIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * InnoTek LIBC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with InnoTek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "libc-alias.h"
+#undef NDEBUG
+#include <assert.h>
+#include <string.h>
+#include <emx/umalloc.h>
+#include <emx/syscalls.h>
+#include <InnoTekLIBC/thread.h>
+#include <InnoTekLIBC/backend.h>
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** Preallocated thread structure. */
+static __LIBC_THREAD    gPreAllocThrd;
+/** Flags whether or not gPreAllocThrd is used. */
+static int              gfPreAllocThrd;
+
+
+/**
+ * Initialize a thread structure.
+ *
+ * @param   pThrd   Pointer to the thread structure which is to be initialized.
+ */
+static void threadInit(__LIBC_PTHREAD pThrd)
+{
+    memset(pThrd, 0, sizeof(*pThrd));
+    pThrd->iRand = 1;
+    __libc_Back_threadInit(pThrd);
+}
+
+
+__LIBC_PTHREAD __libc_threadCurrentSlow(void)
+{
+    if (!*__libc_gpTLS)
+    {
+        __LIBC_PTHREAD  pThrd;
+        /*
+         * Setup a temporary thread block on the stack so _hmalloc()
+         * can't end up calling us recursivly if something goes wrong
+         */
+        __LIBC_THREAD   Thrd;
+        threadInit(&Thrd);
+        *__libc_gpTLS   = &Thrd;
+
+        if (!__lxchg(&gfPreAllocThrd, 1))
+            pThrd = &gPreAllocThrd;
+        else
+        {
+            pThrd = _hmalloc(sizeof(__LIBC_THREAD));
+            assert(pThrd); /* deep, deep, depp, shit. abort the process in a controlled manner... */
+        }
+        *pThrd = Thrd;
+
+        *__libc_gpTLS = pThrd;
+    }
+
+    return *__libc_gpTLS;
+}
+
+
+__LIBC_PTHREAD __libc_threadAlloc(void)
+{
+    /*
+     * No need to use the pre allocated here since the current thread will
+     * most likely be using that one!
+     */
+    __LIBC_PTHREAD pThrd = _hmalloc(sizeof(__LIBC_THREAD));
+    if (pThrd)
+        threadInit(pThrd);
+    return pThrd;
+}
+
+
+void  __libc_threadFree(__LIBC_PTHREAD pThrd)
+{
+    /*
+     * Clean up members.
+     */
+    __libc_Back_threadCleanup(pThrd);
+
+    /*
+     * Release storage.
+     */
+    if (pThrd != &gPreAllocThrd)
+        free(pThrd);
+    else
+        __lxchg(&gfPreAllocThrd, 0);
+}
+
Index: trunk/src/emx/src/lib/process/threadst.c
===================================================================
--- trunk/src/emx/src/lib/process/threadst.c	(revision 1286)
+++ trunk/src/emx/src/lib/process/threadst.c	(revision 1287)
@@ -3,8 +3,11 @@
 #include "libc-alias.h"
 #include <stdlib.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
+/**
+ * @obsolete
+ */
 void **_threadstore (void)
 {
-  return &_thread()->_th_store;
+  return &__libc_threadCurrent()->pvThreadStoreVar;
 }
Index: trunk/src/emx/src/lib/startup/startup.c
===================================================================
--- trunk/src/emx/src/lib/startup/startup.c	(revision 1286)
+++ trunk/src/emx/src/lib/startup/startup.c	(revision 1287)
@@ -43,5 +43,5 @@
 
 
-/** @page Startup
+/** @page Startup   Startup
  *
  * Quick description of how we startup a process which modules uses LIBC.
@@ -57,8 +57,8 @@
  *          - __init_dll initiates _sys_pid and _sys_ppid globals.
  *          - __init_dll creates _sys_heap_fmutex and _sys_gmtxHimem.
- *          - __init_dll then initializes _sys_thread_table and calls __newthread() in
- *            sys/__newthread.c to create the thread 1 entry.
- *              - __newthread() will call __sys_newthread() which inits the high memory
- *                heap (or low if no high mem) when calling _hmalloc().
+ *          - __init_dll then initiates __libc_gpTLS with an allocated TLS ULONG.
+ *            The thread structure it self isn't initialized untill it's actually
+ *            referenced, and when it is there is static structure for the first
+ *            thread needing its per thread area.
  *          - __init_dll calls __init_environ() which initializes environ and _org_environ.
  *              - __init_environ() will call _hmalloc() thus initiating the high heap.
Index: trunk/src/emx/src/lib/str/strerror.c
===================================================================
--- trunk/src/emx/src/lib/str/strerror.c	(revision 1286)
+++ trunk/src/emx/src/lib/str/strerror.c	(revision 1287)
@@ -5,5 +5,5 @@
 #include <stdlib.h>
 #include <string.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 #include <sys/errno.h>
 
@@ -15,9 +15,9 @@
     {
       static char msg[] = "Unknown error ";
-      struct _thread *tp = _thread();
-      memcpy (tp->_th_error, msg, sizeof (msg) - 1);
-      _itoa (errnum, tp->_th_error + sizeof (msg) - 1, 10);
+      __LIBC_PTHREAD pThrd = __libc_threadCurrent();
+      memcpy (pThrd->szStrErrorBuf, msg, sizeof (msg) - 1);
+      _itoa (errnum, pThrd->szStrErrorBuf + sizeof (msg) - 1, 10);
       errno = EINVAL; /* this is actually an invalid error number. */
-      return tp->_th_error;
+      return pThrd->szStrErrorBuf;
     }
 }
Index: trunk/src/emx/src/lib/str/strerror_r.c
===================================================================
--- trunk/src/emx/src/lib/str/strerror_r.c	(revision 1286)
+++ trunk/src/emx/src/lib/str/strerror_r.c	(revision 1287)
@@ -27,5 +27,5 @@
 #include <stdlib.h>
 #include <string.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 #include <sys/errno.h>
 
Index: trunk/src/emx/src/lib/str/strtok.c
===================================================================
--- trunk/src/emx/src/lib/str/strtok.c	(revision 1286)
+++ trunk/src/emx/src/lib/str/strtok.c	(revision 1287)
@@ -3,5 +3,5 @@
 #include "libc-alias.h"
 #include <string.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 char *_STD(strtok) (char *string1, const char *string2)
@@ -9,12 +9,12 @@
   char table[256];
   unsigned char *p, *result;
-  struct _thread *tp = _thread ();
+  __LIBC_PTHREAD pThrd = __libc_threadCurrent ();
   if (string1 != NULL)
     p = (unsigned char *)string1;
   else
     {
-      if (tp->_th_strtok_ptr == NULL)
+      if (pThrd->pszStrTokPos == NULL)
         return NULL;
-      p = tp->_th_strtok_ptr;
+      p = pThrd->pszStrTokPos;
     }
   memset (table, 0, 256);
@@ -32,5 +32,5 @@
       if (p == result)
         {
-          tp->_th_strtok_ptr = NULL;
+          pThrd->pszStrTokPos = NULL;
           return NULL;
         }
@@ -38,5 +38,5 @@
   else
     *p++ = 0;
-  tp->_th_strtok_ptr = p;
+  pThrd->pszStrTokPos = p;
   return (char *)result;
 }
Index: trunk/src/emx/src/lib/sys/386/systhrea.s
===================================================================
--- trunk/src/emx/src/lib/sys/386/systhrea.s	(revision 1286)
+++ 	(revision )
@@ -1,31 +1,0 @@
-/ systhrea.s (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes
-
-        .globl  __sys_thread
-
-        .text
-
-        .align  2, 0x90
-
-__sys_thread:
-        /** @todo change this to use a TLS variable */
-        movl    %fs, %ecx
-        movl    $DosTIB, %eax
-        movl    %eax, %fs
-        fs
-        movl    12, %eax                /* ptib2 */
-        movl    0(%eax), %edx           /* TID */
-        movl    __sys_thread_table(,%edx,4), %eax
-        movl    %ecx, %fs
-        testl   %eax, %eax
-        jz      1f
-        ret
-
-        .align  2, 0x90
-1:      pushl   %edx
-        pushl   $0                      /* errnop */
-        pushl   %edx                    /* tid */
-        call    ___sys_newthread
-        addl    $8, %esp
-        popl    %edx
-        movl    __sys_thread_table(,%edx,4), %eax
-        ret
Index: trunk/src/emx/src/lib/sys/__endthread.c
===================================================================
--- trunk/src/emx/src/lib/sys/__endthread.c	(revision 1286)
+++ 	(revision )
@@ -1,30 +1,0 @@
-/* sys/endthrea.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
-
-#include "libc-alias.h"
-#include <stdlib.h>
-#define INCL_DOS
-#define INCL_FSMACROS
-#include <os2emx.h>
-#include <emx/syscalls.h>
-#include "syscalls.h"
-
-int __endthread (int tid)
-{
-  thread_data *tp;
-
-  if (tid < MAX_THREADS && _sys_thread_table[tid] != NULL)
-    {
-      tp = _sys_thread_table[tid];
-      if (tp->fd.hdir != HDIR_CREATE)
-        {
-          FS_VAR();
-          FS_SAVE_LOAD();
-          DosFindClose (tp->fd.hdir);
-          FS_RESTORE();
-          tp->fd.hdir = HDIR_CREATE;
-        }
-      free (tp);
-      _sys_thread_table[tid] = NULL;
-    }
-  return 0;
-}
Index: trunk/src/emx/src/lib/sys/__init.c
===================================================================
--- trunk/src/emx/src/lib/sys/__init.c	(revision 1286)
+++ trunk/src/emx/src/lib/sys/__init.c	(revision 1287)
@@ -25,4 +25,5 @@
 #include <emx/umalloc.h>
 #include <alloca.h>
+#include <InnoTekLIBC/thread.h>
 
 
@@ -77,5 +78,5 @@
     argc = 0; arg_size = 0;
     /* argv[0] */
-    PUTC(_ARG_NONZERO);
+    PUTC((char)_ARG_NONZERO);
     PUTV;
     for (;;)
@@ -94,5 +95,5 @@
             break;
         flag_ptr = pool;
-        PUTC(_ARG_NONZERO);
+        PUTC((char)_ARG_NONZERO);
         PUTV;
         bs = 0; quote = 0;
@@ -226,5 +227,5 @@
     _sys_init_ret(pStackFrame);
 
-failure:
+    failure:
     DosExit(EXIT_PROCESS, 255);
 }
@@ -233,81 +234,81 @@
 char const _sys_sig_valid[NSIG] =
 {
-  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1
+    0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1
 };
 
 struct sig_descr const sig_info[NSIG] =
 {
-  {"SIG0",     ST_TERM,   ST_TERM},
-  {"SIGHUP",   ST_TERM,   ST_IGNORE},
-  {"SIGINT",   ST_TERM,   ST_IGNORE},
-  {"SIGQUIT",  ST_TERM,   ST_IGNORE},
-  {"SIGILL",   ST_NEXT,   ST_NEXT},
-  {"SIGTRAP",  ST_NEXT,   ST_NEXT},
-  {"SIGABRT",  ST_TERM,   ST_TERM},
-  {"SIGEMT",   ST_TERM,   ST_TERM},
-  {"SIGFPE",   ST_NEXT,   ST_NEXT},
-  {"SIGKILL",  ST_TERM,   ST_TERM},
-  {"SIGBUS",   ST_TERM,   ST_TERM},
-  {"SIGSEGV",  ST_NEXT,   ST_NEXT},
-  {"SIGSYS",   ST_TERM,   ST_TERM},
-  {"SIGPIPE",  ST_TERM,   ST_IGNORE},
-  {"SIGALRM",  ST_TERM,   ST_IGNORE},
-  {"SIGTERM",  ST_NEXT,   ST_IGNORE},
-  {"SIGUSR1",  ST_IGNORE, ST_IGNORE},
-  {"SIGUSR2",  ST_IGNORE, ST_IGNORE},
-  {"SIGCLD",   ST_IGNORE, ST_IGNORE},
-  {"SIG19",    ST_TERM,   ST_TERM},
-  {"SIG20",    ST_TERM,   ST_TERM},
-  {"SIGBREAK", ST_TERM,   ST_IGNORE}
+    {"SIG0",     ST_TERM,   ST_TERM},
+    {"SIGHUP",   ST_TERM,   ST_IGNORE},
+    {"SIGINT",   ST_TERM,   ST_IGNORE},
+    {"SIGQUIT",  ST_TERM,   ST_IGNORE},
+    {"SIGILL",   ST_NEXT,   ST_NEXT},
+    {"SIGTRAP",  ST_NEXT,   ST_NEXT},
+    {"SIGABRT",  ST_TERM,   ST_TERM},
+    {"SIGEMT",   ST_TERM,   ST_TERM},
+    {"SIGFPE",   ST_NEXT,   ST_NEXT},
+    {"SIGKILL",  ST_TERM,   ST_TERM},
+    {"SIGBUS",   ST_TERM,   ST_TERM},
+    {"SIGSEGV",  ST_NEXT,   ST_NEXT},
+    {"SIGSYS",   ST_TERM,   ST_TERM},
+    {"SIGPIPE",  ST_TERM,   ST_IGNORE},
+    {"SIGALRM",  ST_TERM,   ST_IGNORE},
+    {"SIGTERM",  ST_NEXT,   ST_IGNORE},
+    {"SIGUSR1",  ST_IGNORE, ST_IGNORE},
+    {"SIGUSR2",  ST_IGNORE, ST_IGNORE},
+    {"SIGCLD",   ST_IGNORE, ST_IGNORE},
+    {"SIG19",    ST_TERM,   ST_TERM},
+    {"SIG20",    ST_TERM,   ST_TERM},
+    {"SIGBREAK", ST_TERM,   ST_IGNORE}
 };
 
 
-static void say (const char *msg)
-{
-  __write (2, msg, strlen (msg));
-};
-
-
-static void _sys_terminate (int signo)
-{
-  FS_VAR();
-  PPIB pPib;
-  PTIB pTib;
-  DosGetInfoBlocks (&pTib, &pPib);
-  say ("\r\n");
-  say (pPib->pib_pchcmd);
-  say (":");
-
-  if (signo == SIGABRT)
-    say ("\r\nAbnormal program termination\r\n");
-  else
-    {
-      say ("\r\nProcess terminated by ");
-      say (sig_info[signo].name);
-      say ("\r\n");
-    }
-  FS_SAVE_LOAD();
-  while (1)
-    DosExit (EXIT_PROCESS, 3);
-}
-
-
-static void _sys_signal_acknowledge (int signo)
-{
-  FS_VAR();
-  FS_SAVE_LOAD();
-  switch (signo)
-    {
-    case SIGINT:
-      DosAcknowledgeSignalException (XCPT_SIGNAL_INTR);
-      break;
-    case SIGTERM:
-      DosAcknowledgeSignalException (XCPT_SIGNAL_KILLPROC);
-      break;
-    case SIGBREAK:
-      DosAcknowledgeSignalException (XCPT_SIGNAL_BREAK);
-      break;
-    }
-  FS_RESTORE();
+static void say(const char *msg)
+{
+    __write(2, msg, strlen (msg));
+}
+
+
+static void _sys_terminate(int signo)
+{
+    PPIB    pPib;
+    PTIB    pTib;
+    FS_VAR();
+    DosGetInfoBlocks(&pTib, &pPib);
+    say("\r\n");
+    say(pPib->pib_pchcmd);
+    say(":");
+
+    if (signo == SIGABRT)
+        say("\r\nAbnormal program termination\r\n");
+    else
+    {
+        say("\r\nProcess terminated by ");
+        say(sig_info[signo].name);
+        say("\r\n");
+    }
+    FS_SAVE_LOAD();
+    while (1)
+        DosExit(EXIT_PROCESS, 3);
+}
+
+
+static void _sys_signal_acknowledge(int signo)
+{
+    FS_VAR();
+    FS_SAVE_LOAD();
+    switch (signo)
+    {
+        case SIGINT:
+            DosAcknowledgeSignalException(XCPT_SIGNAL_INTR);
+            break;
+        case SIGTERM:
+            DosAcknowledgeSignalException(XCPT_SIGNAL_KILLPROC);
+            break;
+        case SIGBREAK:
+            DosAcknowledgeSignalException(XCPT_SIGNAL_BREAK);
+            break;
+    }
+    FS_RESTORE();
 }
 
@@ -315,24 +316,22 @@
 /* Called from OS/2 exception handler for signal exceptions. */
 
-static ULONG _sys_signal (int signo)
-{
-  thread_data *tp;
-
-  tp = SYS_THREAD;
-  if (tp == NULL)
-    return XCPT_CONTINUE_SEARCH;
-  __sigaddset (&tp->sig_pending, signo);
-  _sys_signal_acknowledge (signo);
-  _sys_deliver_pending_signals (tp);
-  switch (sig_info[signo].fun_action)
-  {
-    case ST_TERM:
-      _sys_terminate (signo);
-    case ST_NEXT:
-      return XCPT_CONTINUE_SEARCH;
-    case ST_IGNORE:
-      return XCPT_CONTINUE_EXECUTION;
-  }
-  return XCPT_CONTINUE_SEARCH;  /* Keep the optimizer happy */
+static ULONG _sys_signal(int signo)
+{
+    __LIBC_PTHREAD pThrd = __libc_threadCurrentNoAuto();
+    if (pThrd == NULL)
+        return XCPT_CONTINUE_SEARCH;
+    __sigaddset (&pThrd->b.sys.sig_pending, signo);
+    _sys_signal_acknowledge(signo);
+    _sys_deliver_pending_signals(pThrd);
+    switch (sig_info[signo].fun_action)
+    {
+        case ST_TERM:
+            _sys_terminate(signo);
+        case ST_NEXT:
+            return XCPT_CONTINUE_SEARCH;
+        case ST_IGNORE:
+            return XCPT_CONTINUE_EXECUTION;
+    }
+    return XCPT_CONTINUE_SEARCH;  /* Keep the optimizer happy */
 }
 
@@ -340,69 +339,69 @@
 /* Called from OS/2 exception handler for traps. */
 
-static ULONG _sys_trap (int signo)
-{
-  thread_data *tp;
-  void (*handler)(int signo);
-
-  tp = SYS_THREAD;
-  if (tp == NULL)
-    return XCPT_CONTINUE_SEARCH;
-  handler = tp->signals[signo].sa_handler;
-  if (handler != SIG_IGN && handler != SIG_DFL)
-    handler (signo);
-  switch (sig_info[signo].fun_action)
-    {
-    case ST_TERM:
-      _sys_terminate (signo);
-    case ST_NEXT:
-      return XCPT_CONTINUE_SEARCH;
-    case ST_IGNORE:
-      return XCPT_CONTINUE_EXECUTION;
-    }
-  return XCPT_CONTINUE_SEARCH;  /* Keep the optimizer happy */
-}
-
-
-static void _sys_deliver_signal (thread_data *tp, int signo)
-{
-  struct sigaction *p;
-  void (*handler)(int signo);
-  sigset_t mask, old_blocked;
-
-  /* TODO: Critical section */
-
-  mask = _SIGMASK (signo);
-  p = &tp->signals[signo];
-
-  tp->sig_pending &= ~mask;
-  handler = p->sa_handler;
-
-  if (handler == SIG_IGN)
-    {
-      /* Ignore the signal. */
-    }
-  else if (handler == SIG_DFL)
-    {
-      if (sig_info[signo].dfl_action != ST_IGNORE)
-        _sys_terminate (signo);
-    }
-  else
-    {
-      if (p->sa_flags & SA_SYSV)
+static ULONG _sys_trap(int signo)
+{
+    __LIBC_PTHREAD  pThrd;
+    void          (*handler)(int signo);
+
+    pThrd = __libc_threadCurrentNoAuto();
+    if (pThrd == NULL)
+        return XCPT_CONTINUE_SEARCH;
+    handler = pThrd->b.sys.signals[signo].sa_handler;
+    if (handler != SIG_IGN && handler != SIG_DFL)
+        handler(signo);
+    switch (sig_info[signo].fun_action)
+    {
+        case ST_TERM:
+            _sys_terminate(signo);
+        case ST_NEXT:
+            return XCPT_CONTINUE_SEARCH;
+        case ST_IGNORE:
+            return XCPT_CONTINUE_EXECUTION;
+    }
+    return XCPT_CONTINUE_SEARCH;  /* Keep the optimizer happy */
+}
+
+
+static void _sys_deliver_signal(__LIBC_PTHREAD pThrd, int signo)
+{
+    struct sigaction *p;
+    void (*handler)(int signo);
+    sigset_t mask, old_blocked;
+
+    /* TODO: Critical section */
+
+    mask = _SIGMASK(signo);
+    p = &pThrd->b.sys.signals[signo];
+
+    pThrd->b.sys.sig_pending &= ~mask;
+    handler = p->sa_handler;
+
+    if (handler == SIG_IGN)
+    {
+        /* Ignore the signal. */
+    }
+    else if (handler == SIG_DFL)
+    {
+        if (sig_info[signo].dfl_action != ST_IGNORE)
+            _sys_terminate(signo);
+    }
+    else
+    {
+        if (p->sa_flags & SA_SYSV)
         {
-          p->sa_handler = SIG_DFL;
-          handler (signo);
+            p->sa_handler = SIG_DFL;
+            handler(signo);
         }
-      else if (p->sa_flags & SA_ACK)
+        else if (p->sa_flags & SA_ACK)
         {
-          tp->sig_blocked |= mask;
-          handler (signo);
+            pThrd->b.sys.sig_blocked |= mask;
+            handler(signo);
         }
-      else
+        else
         {
-          old_blocked = tp->sig_blocked;
-          SET_BLOCKED (tp, tp->sig_blocked | mask | p->sa_mask);
-          handler (signo);
-          tp->sig_blocked = old_blocked;
+            old_blocked = pThrd->b.sys.sig_blocked;
+            SET_BLOCKED(&pThrd->b.sys, pThrd->b.sys.sig_blocked | mask | p->sa_mask);
+            handler(signo);
+            pThrd->b.sys.sig_blocked = old_blocked;
         }
     }
@@ -410,19 +409,22 @@
 
 
-void _sys_deliver_pending_signals (thread_data *tp)
-{
-  int signo;
-
-  /* TODO: Critical section */
-  while ((tp->sig_pending & ~tp->sig_blocked) != 0)
-    {
-      for (signo = 1; signo < NSIG; ++signo)
-        if (tp->sig_pending & ~tp->sig_blocked & _SIGMASK (signo))
-          _sys_deliver_signal (tp, signo);
+void _sys_deliver_pending_signals(__LIBC_PTHREAD pThrd)
+{
+    int signo;
+
+    /* TODO: Critical section */
+    while ((pThrd->b.sys.sig_pending & ~pThrd->b.sys.sig_blocked) != 0)
+    {
+        for (signo = 1; signo < NSIG; ++signo)
+            if (pThrd->b.sys.sig_pending & ~pThrd->b.sys.sig_blocked & _SIGMASK(signo))
+                _sys_deliver_signal(pThrd, signo);
     }
 }
 
 /* from kLib/kHeapDbg.h */
-typedef enum { enmRead, enmWrite, enmUnknown } ENMACCESS;
+typedef enum
+{
+    enmRead, enmWrite, enmUnknown
+} ENMACCESS;
 extern BOOL _Optlink kHeapDbgException(void *    pvAccess,
                                        ENMACCESS enmAccess,
@@ -432,101 +434,86 @@
 asm (".weak kHeapDbgException");
 
-ULONG _sys_exception (PEXCEPTIONREPORTRECORD report,
-                      PEXCEPTIONREGISTRATIONRECORD registration,
-                      PCONTEXTRECORD context,
-                      PVOID whatever)
-{
-  __asm__ ("cld");              /* Don't trust */
-  if (report->fHandlerFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
+ULONG _System _sys_exception(PEXCEPTIONREPORTRECORD report,
+                             PEXCEPTIONREGISTRATIONRECORD registration,
+                             PCONTEXTRECORD context,
+                             PVOID whatever)
+{
+    __asm__ ("cld");              /* Don't trust */
+    if (report->fHandlerFlags & (EH_UNWINDING | EH_EXIT_UNWIND))
+        return XCPT_CONTINUE_SEARCH;
+    switch (report->ExceptionNum)
+    {
+        case XCPT_SIGNAL:
+            if (report->cParameters >= 1)
+            {
+                if (report->ExceptionInfo[0] == XCPT_SIGNAL_INTR)
+                    return _sys_signal(SIGINT);
+                else if (report->ExceptionInfo[0] == XCPT_SIGNAL_KILLPROC)
+                    return _sys_signal(SIGTERM);
+                else if (report->ExceptionInfo[0] == XCPT_SIGNAL_BREAK)
+                    return _sys_signal(SIGBREAK);
+            }
+            break;
+        case XCPT_ACCESS_VIOLATION:
+            /* If we're linking libc01.elh or someone is linking static libc
+               together with kLib the electric fence heap will get the opportunity
+               to check if any access violation was caused by someone touching any
+               of the electric fences. */
+            if (    kHeapDbgException
+                &&  (   report->ExceptionInfo[0] == XCPT_READ_ACCESS
+                        || report->ExceptionInfo[0] == XCPT_WRITE_ACCESS
+                        || report->ExceptionInfo[0] == XCPT_EXECUTE_ACCESS
+                        || report->ExceptionInfo[0] == XCPT_UNKNOWN_ACCESS)
+               )
+            {
+                ENMACCESS enmAccess = enmRead;
+                switch (report->ExceptionInfo[0])
+                {
+                    case XCPT_WRITE_ACCESS:     enmAccess = enmWrite; break;
+                    case XCPT_UNKNOWN_ACCESS:   enmAccess = enmUnknown; break;
+                }
+                /* This call returns true if the page was commited in order
+                   to workaround the immediate problem. If it returns false
+                   the default action should be taken. */
+                if (kHeapDbgException((void*)report->ExceptionInfo[1],
+                                      enmAccess,
+                                      report->ExceptionAddress,
+                                      report))
+                    return XCPT_CONTINUE_EXECUTION;
+            }
+        case XCPT_DATATYPE_MISALIGNMENT:
+            return _sys_trap(SIGSEGV);
+
+        case XCPT_INTEGER_DIVIDE_BY_ZERO:
+        case XCPT_INTEGER_OVERFLOW:
+        case XCPT_ARRAY_BOUNDS_EXCEEDED:
+        case XCPT_FLOAT_DENORMAL_OPERAND:
+        case XCPT_FLOAT_DIVIDE_BY_ZERO:
+        case XCPT_FLOAT_INEXACT_RESULT:
+        case XCPT_FLOAT_INVALID_OPERATION:
+        case XCPT_FLOAT_OVERFLOW:
+        case XCPT_FLOAT_STACK_CHECK:
+        case XCPT_FLOAT_UNDERFLOW:
+            return _sys_trap(SIGFPE);
+
+        case XCPT_ILLEGAL_INSTRUCTION:
+        case XCPT_INVALID_LOCK_SEQUENCE:
+        case XCPT_PRIVILEGED_INSTRUCTION:
+            return _sys_trap(SIGILL);
+    }
     return XCPT_CONTINUE_SEARCH;
-  switch (report->ExceptionNum)
-    {
-    case XCPT_SIGNAL:
-      if (report->cParameters >= 1)
-        {
-          if (report->ExceptionInfo[0] == XCPT_SIGNAL_INTR)
-            return _sys_signal (SIGINT);
-          else if (report->ExceptionInfo[0] == XCPT_SIGNAL_KILLPROC)
-            return _sys_signal (SIGTERM);
-          else if (report->ExceptionInfo[0] == XCPT_SIGNAL_BREAK)
-            return _sys_signal (SIGBREAK);
-        }
-      break;
-    case XCPT_ACCESS_VIOLATION:
-      /* If we're linking libc01.elh or someone is linking static libc
-         together with kLib the electric fence heap will get the opportunity
-         to check if any access violation was caused by someone touching any
-         of the electric fences. */
-      if (    kHeapDbgException
-          &&  (   report->ExceptionInfo[0] == XCPT_READ_ACCESS
-               || report->ExceptionInfo[0] == XCPT_WRITE_ACCESS
-               || report->ExceptionInfo[0] == XCPT_EXECUTE_ACCESS
-               || report->ExceptionInfo[0] == XCPT_UNKNOWN_ACCESS)
-          )
-        {
-          ENMACCESS enmAccess = enmRead;
-          switch (report->ExceptionInfo[0])
-          {
-            case XCPT_WRITE_ACCESS:     enmAccess = enmWrite; break;
-            case XCPT_UNKNOWN_ACCESS:   enmAccess = enmUnknown; break;
-          }
-          /* This call returns true if the page was commited in order
-             to workaround the immediate problem. If it returns false
-             the default action should be taken. */
-          if (kHeapDbgException((void*)report->ExceptionInfo[1],
-                                enmAccess,
-                                report->ExceptionAddress,
-                                report))
-                  return XCPT_CONTINUE_EXECUTION;
-        }
-    case XCPT_DATATYPE_MISALIGNMENT:
-      return _sys_trap (SIGSEGV);
-
-    case XCPT_INTEGER_DIVIDE_BY_ZERO:
-    case XCPT_INTEGER_OVERFLOW:
-    case XCPT_ARRAY_BOUNDS_EXCEEDED:
-    case XCPT_FLOAT_DENORMAL_OPERAND:
-    case XCPT_FLOAT_DIVIDE_BY_ZERO:
-    case XCPT_FLOAT_INEXACT_RESULT:
-    case XCPT_FLOAT_INVALID_OPERATION:
-    case XCPT_FLOAT_OVERFLOW:
-    case XCPT_FLOAT_STACK_CHECK:
-    case XCPT_FLOAT_UNDERFLOW:
-      return _sys_trap (SIGFPE);
-
-    case XCPT_ILLEGAL_INSTRUCTION:
-    case XCPT_INVALID_LOCK_SEQUENCE:
-    case XCPT_PRIVILEGED_INSTRUCTION:
-      return _sys_trap (SIGILL);
-    }
-  return XCPT_CONTINUE_SEARCH;
-}
-
-
-void _sys_get_clock (unsigned long *ms)
-{
-  ULONG val_ms;
-  FS_VAR();
-
-  FS_SAVE_LOAD();
-  DosQuerySysInfo (QSV_MS_COUNT, QSV_MS_COUNT, &val_ms, sizeof (val_ms));
-  FS_RESTORE();
-  *ms = val_ms;
-}
-
-
-void _sys_init_thread (thread_data *tp)
-{
-  int n;
-
-  __sigemptyset (&tp->sig_blocked);
-  __sigemptyset (&tp->sig_pending);
-  for (n = 0; n < NSIG; ++n)
-    {
-      tp->signals[n].sa_handler = SIG_DFL;
-      tp->signals[n].sa_flags   = SA_ACK;
-      __sigemptyset (&tp->signals[n].sa_mask);
-    }
-  tp->fd.hdir = HDIR_CREATE;
-  tp->fd.cFiles = 0;
-}
+}
+
+
+void _sys_get_clock(unsigned long *ms)
+{
+    ULONG val_ms;
+    FS_VAR();
+
+    FS_SAVE_LOAD();
+    DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &val_ms, sizeof (val_ms));
+    FS_RESTORE();
+    *ms = val_ms;
+}
+
+
Index: trunk/src/emx/src/lib/sys/__initdll.c
===================================================================
--- trunk/src/emx/src/lib/sys/__initdll.c	(revision 1286)
+++ trunk/src/emx/src/lib/sys/__initdll.c	(revision 1287)
@@ -11,9 +11,4 @@
 */
 
-
-/*******************************************************************************
-*   Defined Constants And Macros                                               *
-*******************************************************************************/
-#define SYS_PRIVATE_HEAP_SIZE 0x100000
 
 /*******************************************************************************
@@ -35,6 +30,6 @@
 #include <emx/umalloc.h>
 #include <alloca.h>
-
 #include "syscalls.h"
+#include <InnoTekLIBC/thread.h>
 
 /* Make this function an weak external. */
@@ -45,4 +40,6 @@
 *   Global Variables                                                           *
 *******************************************************************************/
+__LIBC_PPTHREAD     __libc_gpTLS;
+
 extern unsigned char _osminor;
 extern unsigned char _osmajor;
@@ -59,5 +56,4 @@
     PTIB    ptib;
     PPIB    ppib;
-    int     n;
     static int initialized = 0;
 
@@ -110,10 +106,12 @@
 
     /*
-     * Initialize thread table and entry for this thread.
+     * Initialize TLS.
      */
-    /** @todo Remove this table, replace it with a pointer backed by TLS memory. */
-    for (n = 0; n < MAX_THREADS; ++n)
-        _sys_thread_table[n] = NULL;
-    __newthread(ptib->tib_ptib2->tib2_ultid);
+    if (!__libc_gpTLS)                  /* !paranoia! */
+    {
+        rc = DosAllocThreadLocalMemory(1, (PULONG*)&__libc_gpTLS);
+        if (rc)
+            return -1;
+    }
 
     /*
Index: trunk/src/emx/src/lib/sys/__initthread.c
===================================================================
--- trunk/src/emx/src/lib/sys/__initthread.c	(revision 1286)
+++ 	(revision )
@@ -1,20 +1,0 @@
-/* sys/initthre.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
-
-#include "libc-alias.h"
-#include <errno.h>
-#define INCL_DOS
-#define INCL_FSMACROS
-#include <os2emx.h>
-#include <emx/syscalls.h>
-#include "syscalls.h"
-
-int __initthread (void *preg)
-{
-  FS_VAR();
-  ((PEXCEPTIONREGISTRATIONRECORD)preg)->prev_structure = NULL;
-  ((PEXCEPTIONREGISTRATIONRECORD)preg)->ExceptionHandler = _sys_exception;
-  FS_SAVE_LOAD();
-  DosSetExceptionHandler (preg);
-  FS_RESTORE();
-  return 0;
-}
Index: trunk/src/emx/src/lib/sys/__newthread.c
===================================================================
--- trunk/src/emx/src/lib/sys/__newthread.c	(revision 1286)
+++ 	(revision )
@@ -1,37 +1,0 @@
-/* sys/newthrea.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
-
-#include "libc-alias.h"
-#include <os2emx.h>
-#include <errno.h>
-#include <emx/syscalls.h>
-#include <emx/umalloc.h>
-#include "syscalls.h"
-int __sys_newthread (int tid, int *errnop); /* used in sys/386/systhrea.s */
-
-
-int __sys_newthread (int tid, int *errnop)
-{
-  void *data;
-
-  if (tid >= MAX_THREADS)
-    {
-      if (errnop != NULL)
-        *errnop = EAGAIN;
-      return -1;
-    }
-  data = _hmalloc (sizeof (thread_data));
-  if (!data)
-    {
-      errno = ENOMEM;
-      return -1;
-    }
-  _sys_thread_table[tid] = data;
-  _sys_init_thread (data);
-  return 0;
-}
-
-
-int __newthread (int tid)
-{
-  return __sys_newthread (tid, &errno);
-}
Index: trunk/src/emx/src/lib/sys/b_threadCleanup.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_threadCleanup.c	(revision 1287)
+++ trunk/src/emx/src/lib/sys/b_threadCleanup.c	(revision 1287)
@@ -0,0 +1,51 @@
+/* $Id$ */
+/** @file
+ *
+ * LIBC SYS Backend - Thread structure cleanup.
+ *
+ * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of InnoTek LIBC.
+ *
+ * InnoTek LIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * InnoTek LIBC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with InnoTek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "libc-alias.h"
+#define INCL_DOS
+#define INCL_FSMACROS
+#include <os2emx.h>
+#include "syscalls.h"
+#include <InnoTekLIBC/thread.h>
+#include <InnoTekLIBC/backend.h>
+
+void __libc_Back_threadCleanup(__LIBC_PTHREAD pThrd)
+{
+    if (!pThrd)
+        return;
+
+    if (pThrd->b.sys.fd.hdir != HDIR_CREATE)
+    {
+        FS_VAR();
+        FS_SAVE_LOAD();
+        DosFindClose(pThrd->b.sys.fd.hdir);
+        FS_RESTORE();
+        pThrd->b.sys.fd.hdir = HDIR_CREATE;
+    }
+}
Index: trunk/src/emx/src/lib/sys/b_threadEnd.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_threadEnd.c	(revision 1287)
+++ trunk/src/emx/src/lib/sys/b_threadEnd.c	(revision 1287)
@@ -0,0 +1,44 @@
+/* $Id$ *//* sys/initthre.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+/** @file
+ *
+ * LIBC SYS Backend - Thread end.
+ *
+ * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of InnoTek LIBC.
+ *
+ * InnoTek LIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * InnoTek LIBC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with InnoTek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "libc-alias.h"
+#include <errno.h>
+#define INCL_DOS
+#define INCL_FSMACROS
+#include <os2emx.h>
+#include <InnoTekLIBC/backend.h>
+
+void __libc_Back_threadEnd(void *pExpRegRec)
+{
+    FS_VAR();
+    FS_SAVE_LOAD();
+    DosUnsetExceptionHandler(pExpRegRec);
+    FS_RESTORE();
+}
Index: trunk/src/emx/src/lib/sys/b_threadInit.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_threadInit.c	(revision 1287)
+++ trunk/src/emx/src/lib/sys/b_threadInit.c	(revision 1287)
@@ -0,0 +1,54 @@
+/* $Id$ */
+/** @file
+ *
+ * LIBC SYS Backend - thread structure init.
+ *
+ * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of InnoTek LIBC.
+ *
+ * InnoTek LIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * InnoTek LIBC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with InnoTek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "libc-alias.h"
+#include <os2emx.h>
+#include <sys/signal.h>
+#include <emx/syscalls.h>
+#include "syscalls.h"
+#include <InnoTekLIBC/thread.h>
+#include <InnoTekLIBC/backend.h>
+
+
+void __libc_Back_threadInit(__LIBC_PTHREAD pThrd)
+{
+    unsigned        i;
+
+    __sigemptyset(&pThrd->b.sys.sig_blocked);
+    __sigemptyset(&pThrd->b.sys.sig_pending);
+    for (i = 0; i < NSIG; ++i)
+    {
+        pThrd->b.sys.signals[i].sa_handler = SIG_DFL;
+        pThrd->b.sys.signals[i].sa_flags   = SA_ACK;
+        __sigemptyset(&pThrd->b.sys.signals[i].sa_mask);
+    }
+    pThrd->b.sys.fd.hdir = HDIR_CREATE;
+    pThrd->b.sys.fd.cFiles = 0;
+}
+
Index: trunk/src/emx/src/lib/sys/b_threadStartup.c
===================================================================
--- trunk/src/emx/src/lib/sys/b_threadStartup.c	(revision 1287)
+++ trunk/src/emx/src/lib/sys/b_threadStartup.c	(revision 1287)
@@ -0,0 +1,47 @@
+/* $Id$ *//* sys/initthre.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */
+/** @file
+ *
+ * LIBC SYS Backend - Thread startup.
+ *
+ * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of InnoTek LIBC.
+ *
+ * InnoTek LIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * InnoTek LIBC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with InnoTek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include "libc-alias.h"
+#include <errno.h>
+#define INCL_DOS
+#define INCL_FSMACROS
+#include <os2emx.h>
+#include "syscalls.h"
+#include <InnoTekLIBC/backend.h>
+
+void __libc_Back_threadStartup(void *pExpRegRec)
+{
+    FS_VAR();
+    ((PEXCEPTIONREGISTRATIONRECORD)pExpRegRec)->ExceptionHandler = _sys_exception;
+    ((PEXCEPTIONREGISTRATIONRECORD)pExpRegRec)->prev_structure   = NULL;
+    FS_SAVE_LOAD();
+    DosSetExceptionHandler(pExpRegRec);
+    FS_RESTORE();
+}
Index: trunk/src/emx/src/lib/sys/filefind.c
===================================================================
--- trunk/src/emx/src/lib/sys/filefind.c	(revision 1286)
+++ trunk/src/emx/src/lib/sys/filefind.c	(revision 1287)
@@ -12,4 +12,5 @@
 #include <emx/syscalls.h>
 #include "syscalls.h"
+#include <InnoTekLIBC/thread.h>
 
 /**
@@ -114,5 +115,5 @@
 {
     ULONG               rc;
-    struct find_data   *pFD = &SYS_THREAD->fd;
+    struct find_data   *pFD = &__libc_threadCurrent()->b.sys.fd;
     FS_VAR();
 
@@ -145,5 +146,5 @@
     FS_SAVE_LOAD();
     memset(&pFD->achBuffer[0], 0, sizeof(pFD->achBuffer));
-    rc = DosFindFirst(pszName,
+    rc = DosFindFirst((PCSZ)pszName,
                       &pFD->hdir,
                       attr & (FILE_NORMAL | FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED),
@@ -181,5 +182,5 @@
 {
     ULONG               rc;
-    struct find_data   *pFD = &SYS_THREAD->fd;
+    struct find_data   *pFD = &__libc_threadCurrent()->b.sys.fd;
     FS_VAR();
 
Index: trunk/src/emx/src/lib/sys/raise.c
===================================================================
--- trunk/src/emx/src/lib/sys/raise.c	(revision 1286)
+++ trunk/src/emx/src/lib/sys/raise.c	(revision 1287)
@@ -7,26 +7,21 @@
 #include <errno.h>
 #include <emx/syscalls.h>
+#include <InnoTekLIBC/thread.h>
 #include "syscalls.h"
 
-int _STD(raise) (int signo)
+int _STD(raise)(int signo)
 {
-  thread_data *tp;
+    __LIBC_PTHREAD  pThrd = __libc_threadCurrent();
 
-  if (signo < 1 || signo >= NSIG || !_sys_sig_valid[signo])
+    if (signo < 1 || signo >= NSIG || !_sys_sig_valid[signo])
     {
-      errno = EINVAL;
-      return -1;
+        errno = EINVAL;
+        return -1;
     }
-  tp = SYS_THREAD;
-  if (tp == NULL)
+    if (pThrd->b.sys.signals[signo].sa_handler != SIG_IGN)
     {
-      errno = EINVAL;
-      return -1;
+        __sigaddset(&pThrd->b.sys.sig_pending, signo);
+        _sys_deliver_pending_signals(pThrd);
     }
-  if (tp->signals[signo].sa_handler != SIG_IGN)
-    {
-      __sigaddset (&tp->sig_pending, signo);
-      _sys_deliver_pending_signals (tp);
-    }
-  return 0;
+    return 0;
 }
Index: trunk/src/emx/src/lib/sys/sigaction.c
===================================================================
--- trunk/src/emx/src/lib/sys/sigaction.c	(revision 1286)
+++ trunk/src/emx/src/lib/sys/sigaction.c	(revision 1287)
@@ -6,41 +6,38 @@
 #include <errno.h>
 #include <emx/syscalls.h>
+#include <InnoTekLIBC/thread.h>
 #include "syscalls.h"
 
-int _STD(sigaction) (int signo, const struct sigaction *iact,
-  struct sigaction *oact)
+int _STD(sigaction)(int signo, const struct sigaction *iact,
+                    struct sigaction *oact)
 {
-  struct sigaction output, *s;
-  thread_data *tp;
+    struct sigaction    output;
+    struct sigaction   *s;
+    __LIBC_PTHREAD      pThrd;
 
-  if (signo < 1 || signo >= NSIG || signo == SIGKILL || !_sys_sig_valid[signo])
+    if (signo < 1 || signo >= NSIG || signo == SIGKILL || !_sys_sig_valid[signo])
     {
-      errno = EINVAL;
-      return -1;
+        errno = EINVAL;
+        return -1;
     }
-  if (signo == SIGKILL && iact != NULL)
+    if (signo == SIGKILL && iact != NULL)
     {
-      errno = EINVAL;
-      return -1;
+        errno = EINVAL;
+        return -1;
     }
-  tp = SYS_THREAD;
-  if (tp == NULL)
+    pThrd = __libc_threadCurrent();
+    s = &pThrd->b.sys.signals[signo];
+    output = *s;
+    if (iact != NULL)
     {
-      errno = EINVAL;
-      return -1;
-    }
-  s = &tp->signals[signo];
-  output = *s;
-  if (iact != NULL)
-    {
-      *s = *iact;
-      if ((s->sa_handler == SIG_DFL
-           && sig_info[signo].dfl_action != ST_IGNORE)
-          || s->sa_handler == SIG_IGN)
-        sigdelset (&tp->sig_pending, signo);
+        *s = *iact;
+        if (    (   s->sa_handler == SIG_DFL
+                 && sig_info[signo].dfl_action != ST_IGNORE)
+            ||  s->sa_handler == SIG_IGN)
+            sigdelset(&pThrd->b.sys.sig_pending, signo);
     }
 
-  if (oact != NULL)
-    *oact = output;
-  return 0;
+    if (oact != NULL)
+        *oact = output;
+    return 0;
 }
Index: trunk/src/emx/src/lib/sys/signal.c
===================================================================
--- trunk/src/emx/src/lib/sys/signal.c	(revision 1286)
+++ trunk/src/emx/src/lib/sys/signal.c	(revision 1287)
@@ -7,36 +7,37 @@
 #include <emx/syscalls.h>
 #include "syscalls.h"
+#include <InnoTekLIBC/thread.h>
 
-typedef void sigfun (int sig);
+typedef void sigfun(int sig);
 
-sigfun *_STD(signal) (int sig, sigfun *handler)
+sigfun *_STD(signal)(int sig, sigfun *handler)
 {
-  if (handler == SIG_ACK)
+    if (handler == SIG_ACK)
     {
-      thread_data *tp;
+        __LIBC_PTHREAD pThrd;
 
-      if (sig < 1 || sig >= NSIG || sig == SIGKILL || !_sys_sig_valid[sig])
+        if (sig < 1 || sig >= NSIG || sig == SIGKILL || !_sys_sig_valid[sig])
         {
-          errno = EINVAL;
-          return SIG_ERR;
+            errno = EINVAL;
+            return SIG_ERR;
         }
-      tp = SYS_THREAD;
-      if (tp == NULL)
-        return SIG_ERR;
-      sigdelset (&tp->sig_blocked, sig);
-      _sys_deliver_pending_signals (tp);
-      return tp->signals[sig].sa_handler;
+        pThrd = __libc_threadCurrent();
+        if (pThrd == NULL)
+            return SIG_ERR;
+        sigdelset(&pThrd->b.sys.sig_blocked, sig);
+        _sys_deliver_pending_signals(pThrd);
+        return pThrd->b.sys.signals[sig].sa_handler;
     }
-  else
+    else
     {
-      struct sigaction isa, osa;
+        struct sigaction isa, osa;
 
-      isa.sa_handler = handler;
-      isa.sa_mask = 0;
-      isa.sa_flags = SA_ACK;
-      if (sigaction (sig, &isa, &osa) != 0)
-        return SIG_ERR;
-      else
-        return osa.sa_handler;
+        isa.sa_handler = handler;
+        isa.sa_mask = 0;
+        isa.sa_flags = SA_ACK;
+        if (sigaction(sig, &isa, &osa) != 0)
+            return SIG_ERR;
+        else
+            return osa.sa_handler;
     }
 }
Index: trunk/src/emx/src/lib/sys/sigpending.c
===================================================================
--- trunk/src/emx/src/lib/sys/sigpending.c	(revision 1286)
+++ trunk/src/emx/src/lib/sys/sigpending.c	(revision 1287)
@@ -6,12 +6,11 @@
 #include <emx/syscalls.h>
 #include "syscalls.h"
+#include <InnoTekLIBC/thread.h>
 
 int _STD(sigpending) (sigset_t *set)
 {
-  thread_data *tp;
-
-  /* TODO: Critical section */
-  tp = SYS_THREAD;
-  *set = tp->sig_blocked & tp->sig_pending;
-  return 0;
+    /* TODO: Critical section */
+    __LIBC_PTHREAD  pThrd = __libc_threadCurrent();
+    *set = pThrd->b.sys.sig_blocked & pThrd->b.sys.sig_pending;
+    return 0;
 }
Index: trunk/src/emx/src/lib/sys/sigprocmask.c
===================================================================
--- trunk/src/emx/src/lib/sys/sigprocmask.c	(revision 1286)
+++ trunk/src/emx/src/lib/sys/sigprocmask.c	(revision 1287)
@@ -7,36 +7,36 @@
 #include <emx/syscalls.h>
 #include "syscalls.h"
+#include <InnoTekLIBC/thread.h>
 
-int _STD(sigprocmask) (int how, const sigset_t *iset, sigset_t *oset)
+int _STD(sigprocmask)(int how, const sigset_t *iset, sigset_t *oset)
 {
-  thread_data *tp;
-  sigset_t temp, output;
+    __LIBC_PTHREAD  pThrd = __libc_threadCurrent();
+    sigset_t temp, output;
 
-  tp = SYS_THREAD;
-  output = tp->sig_blocked;
-  if (iset != NULL)
+    output = pThrd->b.sys.sig_blocked;
+    if (iset != NULL)
     {
-      switch (how)
+        switch (how)
         {
-        case SIG_BLOCK:
-          temp = tp->sig_blocked | *iset;
-          break;
-        case SIG_UNBLOCK:
-          temp = tp->sig_blocked & ~*iset;
-          break;
-        case SIG_SETMASK:
-          temp = *iset;
-          break;
-        default:
-          errno = EINVAL;
-          return -1;
+            case SIG_BLOCK:
+                temp = pThrd->b.sys.sig_blocked | *iset;
+                break;
+            case SIG_UNBLOCK:
+                temp = pThrd->b.sys.sig_blocked & ~*iset;
+                break;
+            case SIG_SETMASK:
+                temp = *iset;
+                break;
+            default:
+                errno = EINVAL;
+                return -1;
         }
-      SET_BLOCKED (tp, temp);
+        SET_BLOCKED(&pThrd->b.sys, temp);
     }
 
-  if (oset != NULL)
-    *oset = output;
+    if (oset != NULL)
+        *oset = output;
 
-  _sys_deliver_pending_signals (tp);
-  return 0;
+    _sys_deliver_pending_signals(pThrd);
+    return 0;
 }
Index: trunk/src/emx/src/lib/sys/sigsuspend.c
===================================================================
--- trunk/src/emx/src/lib/sys/sigsuspend.c	(revision 1286)
+++ trunk/src/emx/src/lib/sys/sigsuspend.c	(revision 1287)
@@ -7,17 +7,17 @@
 #include <emx/syscalls.h>
 #include "syscalls.h"
+#include <InnoTekLIBC/thread.h>
 
 int _STD(sigsuspend) (const sigset_t *mask)
 {
-  sigset_t old_blocked;
-  thread_data *tp;
+    /* TODO: Critical section */
+    __LIBC_PTHREAD  pThrd = __libc_threadCurrent();
+    sigset_t        old_blocked;
 
-  /* TODO: Critical section */
-  tp = SYS_THREAD;
-  old_blocked = tp->sig_blocked;
-  SET_BLOCKED (tp, *mask);
-  pause ();
-  tp->sig_blocked = old_blocked;
-  errno = EINTR;
-  return -1;
+    old_blocked = pThrd->b.sys.sig_blocked;
+    SET_BLOCKED(&pThrd->b.sys, *mask);
+    pause();
+    pThrd->b.sys.sig_blocked = old_blocked;
+    errno = EINTR;
+    return -1;
 }
Index: trunk/src/emx/src/lib/sys/syscalls.h
===================================================================
--- trunk/src/emx/src/lib/sys/syscalls.h	(revision 1286)
+++ trunk/src/emx/src/lib/sys/syscalls.h	(revision 1287)
@@ -6,4 +6,10 @@
 #include "libc-alias.h"
 #include <sys/signal.h>
+
+#ifndef __LIBC_THREAD_DECLARED
+#define __LIBC_THREAD_DECLARED
+struct __libc_threadCurrentSlow;
+typedef struct __libc_threadCurrentSlow *__LIBC_PTHREAD, **__LIBC_PPTHREAD;
+#endif
 
 #if !defined (NULL)
@@ -102,32 +108,7 @@
 #define FDATEZEROP(x) (*(PUSHORT)&(x) == 0)
 
-/** Directory find data entry.
- * Used by __findfirst() and __findnext(). */
-struct find_data
-{
-    /** Directory handle. HDIR_CREATE if no session opened. */
-    HDIR        hdir;
-    /** Type of buffer content. FIL_STANDARDL or FIL_STANDARD,
-     * i.e. FILEFINDBUF3 or FILEFINDBUF3L. */
-    ULONG       fType;
-    /** Number of files left in the buffer. */
-    ULONG       cFiles;
-    /** Pointer to the next entry. Don't test on this, test on cFiles! */
-    const char *pchNext;
-    /** Buffer. */
-    char        achBuffer[2048];
-};
-
-typedef struct
-{
-  struct find_data fd;
-  sigset_t sig_blocked;
-  sigset_t sig_pending;
-  struct sigaction signals[NSIG];
-} thread_data;
-
 #if defined (INCL_DOSEXCEPTIONS)
 EXTERN PEXCEPTIONREGISTRATIONRECORD _sys_xreg INIT (NULL);
-ULONG _sys_exception (PEXCEPTIONREPORTRECORD report,
+ULONG _System _sys_exception (PEXCEPTIONREPORTRECORD report,
     PEXCEPTIONREGISTRATIONRECORD registration, PCONTEXTRECORD context,
     PVOID whatever);
@@ -154,14 +135,6 @@
 extern struct sig_descr const sig_info[NSIG];
 
-long _sys_p2t (FTIME t, FDATE d);
-void _sys_init_thread (thread_data *tp);
-void _sys_deliver_pending_signals (thread_data *tp);
-
-#define MAX_THREADS 1024
-
-EXTERN thread_data *_sys_thread_table[MAX_THREADS];
-
-thread_data *_sys_thread (void);
-#define SYS_THREAD (_sys_thread ())
+long _sys_p2t(FTIME t, FDATE d);
+void _sys_deliver_pending_signals(__LIBC_PTHREAD pThrd);
 
 #endif /* _OS2EMX_H */
Index: trunk/src/emx/src/lib/sys/tls.c
===================================================================
--- trunk/src/emx/src/lib/sys/tls.c	(revision 1287)
+++ trunk/src/emx/src/lib/sys/tls.c	(revision 1287)
@@ -0,0 +1,64 @@
+/* $Id$ */
+/** @file
+ *
+ * InnoTek LIBC - Thread Local Storage Implementation.
+ *
+ * Copyright (c) 2004 knut st. osmundsen <bird-srcspam@anduin.net>
+ *
+ *
+ * This file is part of InnoTek LIBC.
+ *
+ * InnoTek LIBC is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * InnoTek LIBC is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with InnoTek LIBC; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#include <InnoTekLIBC/thread.h>
+#include <errno.h>
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** TLS allocation bitmap map.
+ * Set means allocated, clear means free. Updated atomically. */
+static unsigned auchBitmap[(__LIBC_TLS_MAX + sizeof(unsigned) * 8 - 1) / (sizeof(unsigned) * 8)];
+/** Number of allocated TLS items.
+ * Updated atomically. Update before allocation and after free. */
+static unsigned cTLSFree;
+
+
+int     __libc_TLSAlloc(void)
+{
+    return -1;
+}
+
+int     __libc_TLSFree(int iIndex)
+{
+    return 0;
+}
+
+void *  __libc_TLSGet(int iIndex)
+{
+    return NULL;
+}
+
+int     __libc_TLSSet(int iIndex, void *pvValue)
+{
+    return 0;
+}
+
Index: trunk/src/emx/src/lib/time/asctime.c
===================================================================
--- trunk/src/emx/src/lib/time/asctime.c	(revision 1286)
+++ trunk/src/emx/src/lib/time/asctime.c	(revision 1287)
@@ -4,5 +4,5 @@
 #include <string.h>
 #include <time.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 
 static char const months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
@@ -13,6 +13,6 @@
 char *_STD(asctime) (const struct tm *t)
 {
-  struct _thread *tp = _thread();
-  return asctime_r(t, tp->_th_asctime_buf);
+  __LIBC_PTHREAD pThrd = __libc_threadCurrent();
+  return asctime_r(t, pThrd->szAscTimeAndCTimeBuf);
 }
 
Index: trunk/src/emx/src/lib/time/gmtime.c
===================================================================
--- trunk/src/emx/src/lib/time/gmtime.c	(revision 1286)
+++ trunk/src/emx/src/lib/time/gmtime.c	(revision 1287)
@@ -4,5 +4,5 @@
 #include <stdlib.h>
 #include <time.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 #include <emx/time.h>
 
@@ -69,5 +69,5 @@
 struct tm *_STD(gmtime)(const time_t *t)
 {
-    struct _thread *tp = _thread ();
-    return gmtime_r (t, &tp->_th_gmtime_buf);
+    __LIBC_PTHREAD pThrd = __libc_threadCurrent ();
+    return gmtime_r (t, &pThrd->GmTimeAndLocalTimeBuf);
 }
Index: trunk/src/emx/src/lib/time/localtim.c
===================================================================
--- trunk/src/emx/src/lib/time/localtim.c	(revision 1286)
+++ trunk/src/emx/src/lib/time/localtim.c	(revision 1287)
@@ -3,11 +3,11 @@
 #include "libc-alias.h"
 #include <time.h>
-#include <emx/thread.h>
+#include <InnoTekLIBC/thread.h>
 #include <emx/time.h>
 
 struct tm *_STD(localtime)(const time_t *t)
 {
-    struct _thread *tp = _thread();
-    return localtime_r(t, &tp->_th_gmtime_buf);
+    __LIBC_PTHREAD pThrd = __libc_threadCurrent();
+    return localtime_r(t, &pThrd->GmTimeAndLocalTimeBuf);
 }
 
Index: trunk/src/emx/testcase/loadthread2.c
===================================================================
--- trunk/src/emx/testcase/loadthread2.c	(revision 1286)
+++ trunk/src/emx/testcase/loadthread2.c	(revision 1287)
@@ -11,9 +11,9 @@
     APIRET  rc;
     szObj[0] = '\0';
-    rc = DosLoadModule(szObj, sizeof(szObj), "LIBC05.DLL", &hmod);
+    rc = DosLoadModule(szObj, sizeof(szObj), "LIBC06.DLL", &hmod);
     if (rc)
-        printf("DosLoadModule failed loading LIBC05.DLL. rc=%d szObj=%s\n", rc, szObj);
+        printf("DosLoadModule failed loading LIBC06.DLL. rc=%d szObj=%s\n", rc, szObj);
     else
-        printf("Successfully loaded LIBC05.DLL\n");
+        printf("Successfully loaded LIBC06.DLL\n");
     grc = rc;
 }
Index: trunk/src/emx/version.smak
===================================================================
--- trunk/src/emx/version.smak	(revision 1286)
+++ trunk/src/emx/version.smak	(revision 1287)
@@ -4,5 +4,5 @@
 VH = 0
 # Middle part of version number
-VM = 5
+VM = 6
 # Low part of version number
 VL = 0
