Index: /trunk/src/3rdparty/os2/xsystray/xsystray.h
===================================================================
--- /trunk/src/3rdparty/os2/xsystray/xsystray.h	(revision 271)
+++ /trunk/src/3rdparty/os2/xsystray/xsystray.h	(revision 272)
@@ -39,6 +39,4 @@
 } SYSTRAYCMD;
 
-// NOTE: the idea is to fit SYSTRAYCTLDATA into a page (4K) since this is the
-// smallest piece DosAllocSharedMem() allocates anyway.
 typedef struct
 {
@@ -69,5 +67,5 @@
         {
             ULONG   ulId;
-            CHAR    szText[4000]; // occupy as much of 4K page as we can
+            CHAR    szText[512];
         } tooltip;
 
Index: /trunk/src/3rdparty/os2/xsystray/xsystray_api.c
===================================================================
--- /trunk/src/3rdparty/os2/xsystray/xsystray_api.c	(revision 271)
+++ /trunk/src/3rdparty/os2/xsystray/xsystray_api.c	(revision 272)
@@ -17,4 +17,5 @@
 #define INCL_DOSPROCESS
 #define INCL_WINWINDOWMGR
+#define INCL_WINERRORS
 #define INCL_WINATOM
 #define INCL_WINPOINTERS
@@ -26,10 +27,25 @@
 #include <string.h>
 #include <sys/builtin.h>        // atomics
-#include <InnotekLIBC/thread.h> // TLS
 
 static HWND G_hwndSysTray = NULLHANDLE;
-static int G_itlsSysTrayCtlData = -1;
-
-static HWND FindSysTrayWindow()
+            // window handle of the system tray server
+
+static PVOID G_pvMemoryPool = NULL;
+             // memory pool for SYSTRAYCTLDATA structs used by WM_XST_CONTROL
+             // messages. Note that once allocated, this memory is never freed:
+             // it is intentional since the memory is assumed to be always in
+             // need and that the system will free it when the application
+             // terminates
+
+#define MEMORYPOOL_SIZE 65536
+        // taking SYSTRAYCTLDATA size into account, this is enough for at least
+        // 64 threads sending WM_XST_CONTROL simultaneously, which sounds sane
+
+// @todo to be on the safe side with casting in __atomic_cmpxchg32() we need
+// compile-time assertions like this:
+// AssertCompile(sizeof(uint32_t) == sizeof(HWND));
+// AssertCompile(sizeof(uint32_t) == sizeof(PVOID));
+
+static HWND FindSysTrayServerWindow()
 {
     char buf[sizeof(WNDCLASS_WIDGET_XSYSTRAY_SERVER) + 1];
@@ -62,5 +78,5 @@
         {
             bTriedFind = TRUE;
-            HWND hwnd = FindSysTrayWindow();
+            HWND hwnd = FindSysTrayServerWindow();
             __atomic_cmpxchg32((uint32_t *)&G_hwndSysTray, hwnd, NULLHANDLE);
             if (G_hwndSysTray == NULLHANDLE)
@@ -72,5 +88,5 @@
             arc = ERROR_INVALID_HANDLE;
             if (WinQueryWindowProcess(G_hwndSysTray, &pid, &tid))
-                arc = DosGiveSharedMem(__libc_TLSGet(G_itlsSysTrayCtlData),
+                arc = DosGiveSharedMem(G_pvMemoryPool,
                                        pid, PAG_READ | PAG_WRITE);
             if (arc != NO_ERROR)
@@ -100,47 +116,47 @@
 }
 
-// This function returns a per-thread SYSTRAYCTLDATA pointer. We communicate
-// to the server thread using WinSendMsg() which allows us to reuse a single
-// memory block for all calls (WinSendMsg() doesn't return until the server is
-// done with processing the message).
-static PSYSTRAYCTLDATA GetSysTrayCtlDataPtr()
+// This function allocates a SYSTRAYCTLDATA struct in the pool of shared memory.
+// If there is no free space in the pool, it returns NULL. The allocated memory
+// must be freed by FreeSysTrayCtlDataPtr() when not needed.
+static PSYSTRAYCTLDATA AllocSysTrayCtlDataPtr()
 {
     APIRET arc;
-
-    // allocate a thread local storage entry if not done so
-    if (G_itlsSysTrayCtlData == -1)
-    {
-        // @todo does XWorkplace have its own TLS? Or is it built with GCC? Not?
-        // Use DosAllocThreadLocalMemory() directly then (though it's not nice
-        // due to the too limited amount of memory space in that area)
-        int itls = __libc_TLSAlloc();
-        if (!__atomic_cmpxchg32(&G_itlsSysTrayCtlData, itls, -1))
+    PVOID pvPool;
+    PSYSTRAYCTLDATA pData;
+
+    if (!G_pvMemoryPool)
+    {
+        // Note: we don't PAG_COMMIT, DosSubAllocMem will do so when needed
+        arc = DosAllocSharedMem((PVOID)&pvPool, NULL, MEMORYPOOL_SIZE,
+                                PAG_READ | PAG_WRITE | OBJ_GIVEABLE);
+        if (arc == NO_ERROR)
+            arc = DosSubSetMem(pvPool,
+                               DOSSUB_INIT | DOSSUB_SPARSE_OBJ,
+                               MEMORYPOOL_SIZE);
+        if (!__atomic_cmpxchg32((uint32_t *)&G_pvMemoryPool,
+                                (uint32_t)pvPool, (uint32_t)NULL))
         {
             // another thread has already got an entry, discard our try
-            if (itls != -1)
-                __libc_TLSFree(itls);
+            if (pvPool)
+                DosFreeMem(pvPool);
         }
-
-        if (G_itlsSysTrayCtlData == -1)
-            return NULL;
-    }
-
-    // allocate a SYSTRAYCTLDATA struct for this thread if not done so
-    PSYSTRAYCTLDATA pData = __libc_TLSGet(G_itlsSysTrayCtlData);
-    if (!pData)
-    {
-        arc = DosAllocSharedMem((PVOID)&pData, NULL, sizeof(SYSTRAYCTLDATA),
-                                PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GIVEABLE);
-        if (arc != NO_ERROR)
-            return NULL;
-
-        __libc_TLSSet(G_itlsSysTrayCtlData, pData);
-
-        // note that we don't ever free the allocated block since our API doesn't
-        // have a concept of initialization/termination and therefore it's fine
-        // if the memory stays allocated until application termination
-    }
+        else
+        {
+            // we could fail to allocate while being the first... give up
+            if (arc != NO_ERROR)
+                return NULL;
+        }
+    }
+
+    arc = DosSubAllocMem(G_pvMemoryPool, (PVOID)&pData, sizeof(SYSTRAYCTLDATA));
+    if (arc != NO_ERROR)
+        return NULL;
 
     return pData;
+}
+
+static VOID FreeSysTrayCtlDataPtr(PSYSTRAYCTLDATA pData)
+{
+    DosSubFreeMem(G_pvMemoryPool, pData, sizeof(SYSTRAYCTLDATA));
 }
 
@@ -166,5 +182,5 @@
 {
     BOOL brc;
-    PSYSTRAYCTLDATA pData = GetSysTrayCtlDataPtr();
+    PSYSTRAYCTLDATA pData = AllocSysTrayCtlDataPtr();
     if (!pData)
         return FALSE;
@@ -184,4 +200,6 @@
     }
 
+    FreeSysTrayCtlDataPtr(pData);
+
     return brc;
 }
@@ -224,5 +242,5 @@
     BOOL brc;
     PPIB ppib;
-    PSYSTRAYCTLDATA pData = GetSysTrayCtlDataPtr();
+    PSYSTRAYCTLDATA pData = AllocSysTrayCtlDataPtr();
     if (!pData)
         return FALSE;
@@ -230,18 +248,20 @@
     // give all processes temporary access to hIcon
     brc = WinSetPointerOwner(hIcon, 0, FALSE);
-    if (!brc)
-        return FALSE;
-
-    pData->ulCommand = SYSTRAYCMD_ADDICON;
-    pData->hwndSender = hwnd;
-    pData->u.icon.ulId = ulId;
-    pData->u.icon.hIcon = hIcon;
-    pData->u.icon.ulMsgId = ulMsgId;
-
-    brc = SendSysTrayCtlMsg(pData);
-
-    // revoke temporary access to hIcon
-    DosGetInfoBlocks(NULL, &ppib);
-    WinSetPointerOwner(hIcon, ppib->pib_ulpid, TRUE);
+    if (brc)
+    {
+        pData->ulCommand = SYSTRAYCMD_ADDICON;
+        pData->hwndSender = hwnd;
+        pData->u.icon.ulId = ulId;
+        pData->u.icon.hIcon = hIcon;
+        pData->u.icon.ulMsgId = ulMsgId;
+
+        brc = SendSysTrayCtlMsg(pData);
+
+        // revoke temporary access to hIcon
+        DosGetInfoBlocks(NULL, &ppib);
+        WinSetPointerOwner(hIcon, ppib->pib_ulpid, TRUE);
+    }
+
+    FreeSysTrayCtlDataPtr(pData);
 
     return brc;
@@ -260,5 +280,6 @@
                           ULONG ulId)   // in: icon ID to remove
 {
-    PSYSTRAYCTLDATA pData = GetSysTrayCtlDataPtr();
+    BOOL brc;
+    PSYSTRAYCTLDATA pData = AllocSysTrayCtlDataPtr();
     if (!pData)
         return FALSE;
@@ -268,5 +289,9 @@
     pData->u.icon.ulId = ulId;
 
-    return SendSysTrayCtlMsg(pData);
+    brc = SendSysTrayCtlMsg(pData);
+
+    FreeSysTrayCtlDataPtr(pData);
+
+    return brc;
 }
 
@@ -292,5 +317,6 @@
                               PSZ pszText)  // in: tooltip text
 {
-    PSYSTRAYCTLDATA pData = GetSysTrayCtlDataPtr();
+    BOOL brc;
+    PSYSTRAYCTLDATA pData = AllocSysTrayCtlDataPtr();
     if (!pData)
         return FALSE;
@@ -310,5 +336,9 @@
     }
 
-    return SendSysTrayCtlMsg(pData);
+    brc = SendSysTrayCtlMsg(pData);
+
+    FreeSysTrayCtlDataPtr(pData);
+
+    return brc;
 }
 
