VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/HGCMObjects.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 Author Date Id Revision
File size: 7.0 KB
Line 
1/* $Id: HGCMObjects.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * HGCMObjects - Host-Guest Communication Manager objects
4 */
5
6/*
7 * Copyright (C) 2006-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 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#define LOG_GROUP LOG_GROUP_HGCM
29#include "LoggingNew.h"
30
31#include "HGCMObjects.h"
32
33#include <iprt/string.h>
34#include <iprt/errcore.h>
35
36
37static RTCRITSECT g_critsect;
38
39/* There are internal handles, which are not saved,
40 * and client handles, which are saved.
41 * They use different range of values:
42 * 1..7FFFFFFF for clients,
43 * 0x80000001..0xFFFFFFFF for other handles.
44 */
45static uint32_t volatile g_u32InternalHandleCount;
46static uint32_t volatile g_u32ClientHandleCount;
47
48static PAVLU32NODECORE g_pTree;
49
50
51DECLINLINE(int) hgcmObjEnter(void)
52{
53 return RTCritSectEnter(&g_critsect);
54}
55
56DECLINLINE(void) hgcmObjLeave(void)
57{
58 RTCritSectLeave(&g_critsect);
59}
60
61int hgcmObjInit(void)
62{
63 LogFlow(("MAIN::hgcmObjInit\n"));
64
65 g_u32InternalHandleCount = 0x80000000;
66 g_u32ClientHandleCount = 0;
67 g_pTree = NULL;
68
69 int vrc = RTCritSectInit(&g_critsect);
70
71 LogFlow(("MAIN::hgcmObjInit: vrc = %Rrc\n", vrc));
72
73 return vrc;
74}
75
76void hgcmObjUninit(void)
77{
78 if (RTCritSectIsInitialized(&g_critsect))
79 RTCritSectDelete(&g_critsect);
80}
81
82uint32_t hgcmObjMake(HGCMObject *pObject, uint32_t u32HandleIn)
83{
84 int handle = 0;
85
86 LogFlow(("MAIN::hgcmObjGenerateHandle: pObject %p\n", pObject));
87
88 int vrc = hgcmObjEnter();
89
90 if (RT_SUCCESS(vrc))
91 {
92 ObjectAVLCore *pCore = &pObject->m_core;
93
94 /* Generate a new handle value. */
95
96 uint32_t volatile *pu32HandleCountSource = pObject->Type () == HGCMOBJ_CLIENT?
97 &g_u32ClientHandleCount:
98 &g_u32InternalHandleCount;
99
100 uint32_t u32Start = *pu32HandleCountSource;
101
102 for (;;)
103 {
104 uint32_t Key;
105
106 if (u32HandleIn == 0)
107 {
108 Key = ASMAtomicIncU32(pu32HandleCountSource);
109
110 if (Key == u32Start)
111 {
112 /* Rollover. Something is wrong. */
113 AssertReleaseFailed();
114 break;
115 }
116
117 /* 0 and 0x80000000 are not valid handles. */
118 if ((Key & 0x7FFFFFFF) == 0)
119 {
120 /* Over the invalid value, reinitialize the source. */
121 *pu32HandleCountSource = pObject->Type () == HGCMOBJ_CLIENT?
122 0:
123 UINT32_C(0x80000000);
124 continue;
125 }
126 }
127 else
128 {
129 Key = u32HandleIn;
130 }
131
132 /* Insert object to AVL tree. */
133 pCore->AvlCore.Key = Key;
134
135 bool fRC = RTAvlU32Insert(&g_pTree, &pCore->AvlCore);
136
137 /* Could not insert a handle. */
138 if (!fRC)
139 {
140 if (u32HandleIn == 0)
141 {
142 /* Try another generated handle. */
143 continue;
144 }
145 /* Could not use the specified handle. */
146 break;
147 }
148
149 /* Initialize backlink. */
150 pCore->pSelf = pObject;
151
152 /* Reference the object for time while it resides in the tree. */
153 pObject->Reference();
154
155 /* Store returned handle. */
156 handle = Key;
157
158 Log(("Object key inserted 0x%08X\n", Key));
159
160 break;
161 }
162
163 hgcmObjLeave();
164 }
165 else
166 {
167 AssertReleaseMsgFailed(("MAIN::hgcmObjGenerateHandle: Failed to acquire object pool semaphore"));
168 }
169
170 LogFlow(("MAIN::hgcmObjGenerateHandle: handle = 0x%08X, vrc = %Rrc, return void\n", handle, vrc));
171
172 return handle;
173}
174
175uint32_t hgcmObjGenerateHandle(HGCMObject *pObject)
176{
177 return hgcmObjMake(pObject, 0);
178}
179
180uint32_t hgcmObjAssignHandle(HGCMObject *pObject, uint32_t u32Handle)
181{
182 return hgcmObjMake(pObject, u32Handle);
183}
184
185void hgcmObjDeleteHandle(uint32_t handle)
186{
187 int vrc = VINF_SUCCESS;
188
189 LogFlow(("MAIN::hgcmObjDeleteHandle: handle 0x%08X\n", handle));
190
191 if (handle)
192 {
193 vrc = hgcmObjEnter();
194
195 if (RT_SUCCESS(vrc))
196 {
197 ObjectAVLCore *pCore = (ObjectAVLCore *)RTAvlU32Remove(&g_pTree, handle);
198
199 if (pCore)
200 {
201 AssertRelease(pCore->pSelf);
202
203 pCore->pSelf->Dereference();
204 }
205
206 hgcmObjLeave();
207 }
208 else
209 {
210 AssertReleaseMsgFailed(("Failed to acquire object pool semaphore, vrc = %Rrc", vrc));
211 }
212 }
213
214 LogFlow(("MAIN::hgcmObjDeleteHandle: vrc = %Rrc, return void\n", vrc));
215}
216
217HGCMObject *hgcmObjReference (uint32_t handle, HGCMOBJ_TYPE enmObjType)
218{
219 LogFlow(("MAIN::hgcmObjReference: handle 0x%08X\n", handle));
220
221 HGCMObject *pObject = NULL;
222
223 if ((handle & UINT32_C(0x7FFFFFFF)) == 0)
224 {
225 return pObject;
226 }
227
228 int vrc = hgcmObjEnter();
229
230 if (RT_SUCCESS(vrc))
231 {
232 ObjectAVLCore *pCore = (ObjectAVLCore *)RTAvlU32Get(&g_pTree, handle);
233
234 Assert(!pCore || (pCore->pSelf && pCore->pSelf->Type() == enmObjType));
235 if ( pCore
236 && pCore->pSelf
237 && pCore->pSelf->Type() == enmObjType)
238 {
239 pObject = pCore->pSelf;
240
241 AssertRelease(pObject);
242
243 pObject->Reference();
244 }
245
246 hgcmObjLeave();
247 }
248 else
249 {
250 AssertReleaseMsgFailed(("Failed to acquire object pool semaphore, vrc = %Rrc", vrc));
251 }
252
253 LogFlow(("MAIN::hgcmObjReference: return pObject %p\n", pObject));
254
255 return pObject;
256}
257
258void hgcmObjDereference(HGCMObject *pObject)
259{
260 LogFlow(("MAIN::hgcmObjDereference: pObject %p\n", pObject));
261
262 AssertRelease(pObject);
263
264 pObject->Dereference();
265
266 LogFlow(("MAIN::hgcmObjDereference: return\n"));
267}
268
269uint32_t hgcmObjQueryHandleCount()
270{
271 return g_u32ClientHandleCount;
272}
273
274void hgcmObjSetHandleCount(uint32_t u32ClientHandleCount)
275{
276 Assert(g_u32ClientHandleCount <= u32ClientHandleCount);
277
278 int vrc = hgcmObjEnter();
279
280 if (RT_SUCCESS(vrc))
281 {
282 if (g_u32ClientHandleCount <= u32ClientHandleCount)
283 g_u32ClientHandleCount = u32ClientHandleCount;
284 hgcmObjLeave();
285 }
286}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use