VirtualBox

Changeset 83101 in vbox for trunk/src/VBox/Runtime/r3


Ignore:
Timestamp:
Feb 17, 2020 7:46:52 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
136162
Message:

IPRT: Simple TLS destructor implementation for windows.

Location:
trunk/src/VBox/Runtime/r3/win
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/win/dllmain-win.cpp

    r82968 r83101  
    8282
    8383        case DLL_THREAD_DETACH:
     84            rtTlsWinDetachThread();
    8485            rtThreadNativeDetach();
    8586            break;
  • trunk/src/VBox/Runtime/r3/win/tls-dllmain-win.cpp

    r83074 r83101  
    3333
    3434#include <iprt/thread.h>
     35#include <iprt/assert.h>
     36#include <iprt/critsect.h>
     37#include <iprt/errcore.h>
    3538#include <iprt/log.h>
    36 #include <iprt/assert.h>
    37 #include <iprt/errcore.h>
     39#include <iprt/mem.h>
     40#include <iprt/once.h>
    3841#include "internal/thread.h"
    3942
    4043
    41 AssertCompile(sizeof(RTTLS) >= sizeof(DWORD));
     44/*********************************************************************************************************************************
     45*   Structures and Typedefs                                                                                                      *
     46*********************************************************************************************************************************/
     47typedef struct RTTLSWINDTOR
     48{
     49    RTLISTNODE      ListEntry;
     50    DWORD           iTls;
     51    PFNRTTLSDTOR    pfnDestructor;
     52} RTTLSWINDTOR;
     53typedef RTTLSWINDTOR *PRTTLSWINDTOR;
     54
     55
     56/*********************************************************************************************************************************
     57*   Global Variables                                                                                                             *
     58*********************************************************************************************************************************/
     59/** Init once for the list and critical section. */
     60static RTONCE               g_Once = RTONCE_INITIALIZER;
     61/** Critical section protecting the TLS destructor list. */
     62static RTCRITSECTRW         g_CritSect;
     63/** List of TLS destrictors (RTTLSWINDTOR).  */
     64static RTLISTANCHOR         g_TlsDtorHead;
     65/** Number of desturctors in the list (helps putting of initialization). */
     66static uint32_t volatile    g_cTlsDtors = 0;
     67
     68
     69/**
     70 * @callback_method_impl{FNRTONCE}
     71 */
     72static DECLCALLBACK(int32_t) rtTlsWinInitLock(void *pvUser)
     73{
     74    RT_NOREF(pvUser);
     75    RTListInit(&g_TlsDtorHead);
     76    return RTCritSectRwInit(&g_CritSect);
     77}
    4278
    4379
    4480RTR3DECL(RTTLS) RTTlsAlloc(void)
    4581{
     82    AssertCompile(sizeof(RTTLS) >= sizeof(DWORD));
    4683    DWORD iTls = TlsAlloc();
    4784    return iTls != TLS_OUT_OF_INDEXES ? (RTTLS)iTls : NIL_RTTLS;
     
    5188RTR3DECL(int) RTTlsAllocEx(PRTTLS piTls, PFNRTTLSDTOR pfnDestructor)
    5289{
    53     AssertReturn(!pfnDestructor, VERR_NOT_SUPPORTED);
    54     DWORD iTls = TlsAlloc();
    55     if (iTls != TLS_OUT_OF_INDEXES)
    56     {
    57         Assert((RTTLS)iTls != NIL_RTTLS);
    58         *piTls = (RTTLS)iTls;
    59         Assert((DWORD)*piTls == iTls);
    60         return VINF_SUCCESS;
    61     }
    62 
    63     return VERR_NO_MEMORY;
     90    int rc;
     91    if (!pfnDestructor)
     92    {
     93        DWORD iTls = TlsAlloc();
     94        if (iTls != TLS_OUT_OF_INDEXES)
     95        {
     96            Assert((RTTLS)iTls != NIL_RTTLS);
     97            *piTls = (RTTLS)iTls;
     98            Assert((DWORD)*piTls == iTls);
     99            rc = VINF_SUCCESS;
     100        }
     101        else
     102            rc = VERR_NO_MEMORY;
     103    }
     104    else
     105    {
     106        rc = RTOnce(&g_Once, rtTlsWinInitLock, NULL);
     107        if (RT_SUCCESS(rc))
     108        {
     109            PRTTLSWINDTOR pDtor = (PRTTLSWINDTOR)RTMemAlloc(sizeof(*pDtor));
     110            if (pDtor)
     111            {
     112                DWORD iTls = TlsAlloc();
     113                if (iTls != TLS_OUT_OF_INDEXES)
     114                {
     115                    Assert((RTTLS)iTls != NIL_RTTLS);
     116                    *piTls = (RTTLS)iTls;
     117                    Assert((DWORD)*piTls == iTls);
     118
     119                    /*
     120                     * Add the destructor to the list.  We keep it sorted.
     121                     */
     122                    pDtor->iTls = iTls;
     123                    pDtor->pfnDestructor = pfnDestructor;
     124                    RTCritSectRwEnterExcl(&g_CritSect);
     125                    RTListAppend(&g_TlsDtorHead, &pDtor->ListEntry);
     126                    ASMAtomicIncU32(&g_cTlsDtors);
     127                    RTCritSectRwLeaveExcl(&g_CritSect);
     128
     129                    rc = VINF_SUCCESS;
     130                }
     131                else
     132                    rc = VERR_NO_MEMORY;
     133            }
     134            else
     135                rc = VERR_NO_MEMORY;
     136        }
     137    }
     138    return rc;
    64139}
    65140
     
    70145        return VINF_SUCCESS;
    71146    if (TlsFree((DWORD)iTls))
    72         return VINF_SUCCESS;
     147    {
     148        if (ASMAtomicReadU32(&g_cTlsDtors) > 0)
     149        {
     150            RTCritSectRwEnterExcl(&g_CritSect);
     151            PRTTLSWINDTOR pDtor;
     152            RTListForEach(&g_TlsDtorHead, pDtor, RTTLSWINDTOR, ListEntry)
     153            {
     154                if (pDtor->iTls == (DWORD)iTls)
     155                {
     156                    RTListNodeRemove(&pDtor->ListEntry);
     157                    ASMAtomicDecU32(&g_cTlsDtors);
     158                    RTMemFree(pDtor);
     159                    break;
     160                }
     161            }
     162            RTCritSectRwLeaveExcl(&g_CritSect);
     163        }
     164        return VINF_SUCCESS;
     165    }
    73166    return RTErrConvertFromWin32(GetLastError());
    74167}
     
    103196}
    104197
     198
     199/**
     200 * Called by dllmain-win.cpp when a thread detaches.
     201 */
     202DECLHIDDEN(void) rtTlsWinDetachThread(void)
     203{
     204    if (ASMAtomicReadU32(&g_cTlsDtors) > 0)
     205    {
     206        RTCritSectRwEnterShared(&g_CritSect);
     207        PRTTLSWINDTOR pDtor;
     208        RTListForEach(&g_TlsDtorHead, pDtor, RTTLSWINDTOR, ListEntry)
     209        {
     210            void *pvValue = TlsGetValue(pDtor->iTls);
     211            if (pvValue != NULL)
     212            {
     213                pDtor->pfnDestructor(pvValue);
     214                TlsSetValue(pDtor->iTls, NULL);
     215            }
     216        }
     217        RTCritSectRwLeaveShared(&g_CritSect);
     218    }
     219}
     220
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette