VirtualBox

source: vbox/trunk/src/VBox/Runtime/generic/tls-generic.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 5.4 KB
Line 
1/* $Id: tls-generic.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Thread Local Storage (TSL), Generic Implementation.
4 */
5
6/*
7 * Copyright (C) 2008-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#define LOG_GROUP RTLOGGROUP_THREAD
42#include <iprt/thread.h>
43#include "internal/iprt.h"
44
45#include <iprt/errcore.h>
46#include <iprt/asm.h>
47#include <iprt/log.h>
48#include <iprt/assert.h>
49#include "internal/thread.h"
50
51
52/*********************************************************************************************************************************
53* Global Variables *
54*********************************************************************************************************************************/
55/** Allocation bitmap. Set bits indicates allocated entries. */
56static uint32_t volatile g_au32AllocatedBitmap[(RTTHREAD_TLS_ENTRIES + 31) / 32];
57/** Destructors for each of the TLS entries. */
58static PFNRTTLSDTOR g_apfnDestructors[RTTHREAD_TLS_ENTRIES];
59
60
61RTR3DECL(RTTLS) RTTlsAlloc(void)
62{
63 RTTLS iTls;
64 int rc = RTTlsAllocEx(&iTls, NULL);
65 return RT_SUCCESS(rc) ? iTls : NIL_RTTLS;
66}
67
68
69RTR3DECL(int) RTTlsAllocEx(PRTTLS piTls, PFNRTTLSDTOR pfnDestructor)
70{
71 for (unsigned i = 0; i < 128; i++)
72 {
73 int iTls = ASMBitFirstClear(&g_au32AllocatedBitmap[0], RTTHREAD_TLS_ENTRIES);
74 if (iTls < 0)
75 {
76 *piTls = NIL_RTTLS;
77 return VERR_NO_MEMORY;
78 }
79 if (!ASMAtomicBitTestAndSet(&g_au32AllocatedBitmap[0], iTls))
80 {
81 g_apfnDestructors[iTls] = pfnDestructor;
82 *piTls = iTls;
83 return VINF_SUCCESS;
84 }
85 }
86
87 AssertFailed();
88 return VERR_NO_MEMORY;
89}
90
91
92RTR3DECL(int) RTTlsFree(RTTLS iTls)
93{
94 if (iTls == NIL_RTTLS)
95 return VINF_SUCCESS;
96 if ( iTls < 0
97 || iTls >= RTTHREAD_TLS_ENTRIES
98 || !ASMBitTest(&g_au32AllocatedBitmap[0], iTls))
99 return VERR_INVALID_PARAMETER;
100
101 ASMAtomicWriteNullPtr(&g_apfnDestructors[iTls]);
102 rtThreadClearTlsEntry(iTls);
103 ASMAtomicBitClear(&g_au32AllocatedBitmap[0], iTls);
104 return VINF_SUCCESS;
105}
106
107
108RTR3DECL(void *) RTTlsGet(RTTLS iTls)
109{
110 void *pv;
111 int rc = RTTlsGetEx(iTls, &pv);
112 return RT_SUCCESS(rc) ? pv : NULL;
113}
114
115
116RTR3DECL(int) RTTlsGetEx(RTTLS iTls, void **ppvValue)
117{
118 if (RT_UNLIKELY( iTls < 0
119 || iTls >= RTTHREAD_TLS_ENTRIES
120 || !ASMBitTest(&g_au32AllocatedBitmap[0], iTls)))
121 return VERR_INVALID_PARAMETER;
122
123 PRTTHREADINT pThread = rtThreadGet(RTThreadSelf());
124 AssertReturn(pThread, VERR_NOT_SUPPORTED);
125 void *pv = pThread->apvTlsEntries[iTls];
126 rtThreadRelease(pThread);
127 *ppvValue = pv;
128 return VINF_SUCCESS;
129}
130
131
132RTR3DECL(int) RTTlsSet(RTTLS iTls, void *pvValue)
133{
134 if (RT_UNLIKELY( iTls < 0
135 || iTls >= RTTHREAD_TLS_ENTRIES
136 || !ASMBitTest(&g_au32AllocatedBitmap[0], iTls)))
137 return VERR_INVALID_PARAMETER;
138
139 PRTTHREADINT pThread = rtThreadGet(RTThreadSelf());
140 AssertReturn(pThread, VERR_NOT_SUPPORTED);
141 pThread->apvTlsEntries[iTls] = pvValue;
142 rtThreadRelease(pThread);
143 return VINF_SUCCESS;
144}
145
146
147
148/**
149 * Called at thread termination to invoke TLS destructors.
150 *
151 * @param pThread The current thread.
152 */
153DECLHIDDEN(void) rtThreadTlsDestruction(PRTTHREADINT pThread)
154{
155 for (RTTLS iTls = 0; iTls < RTTHREAD_TLS_ENTRIES; iTls++)
156 {
157 void *pv = pThread->apvTlsEntries[iTls];
158 if (pv)
159 {
160 PFNRTTLSDTOR pfnDestructor = (PFNRTTLSDTOR)(uintptr_t)ASMAtomicUoReadPtr((void * volatile *)(uintptr_t)&g_apfnDestructors[iTls]);
161 if (pfnDestructor)
162 {
163 pThread->apvTlsEntries[iTls] = NULL;
164 pfnDestructor(pv);
165 }
166 }
167 }
168}
169
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use