VirtualBox

source: vbox/trunk/src/VBox/Main/hgcm/HGCMObjects.cpp@ 1756

Last change on this file since 1756 was 1720, checked in by vboxsync, 18 years ago

fix/workaround for #1873

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.1 KB
Line 
1/** @file
2 *
3 * HGCM (Host-Guest Communication Manager):
4 * HGCMObjects - Host-Guest Communication Manager objects
5 */
6
7/*
8 * Copyright (C) 2006 InnoTek Systemberatung GmbH
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
21 */
22
23#define LOG_GROUP_MAIN_OVERRIDE LOG_GROUP_HGCM
24#include "Logging.h"
25
26#include "hgcm/HGCMObjects.h"
27
28#include <string.h>
29
30#include <VBox/err.h>
31
32
33static RTCRITSECT g_critsect;
34
35/* There are internal handles, which are not saved,
36 * and client handles, which are saved.
37 * They use different range of values:
38 * 1..7FFFFFFF for clients,
39 * 0x80000001..0xFFFFFFFF for other handles.
40 */
41static uint32_t volatile g_u32InternalHandleCount;
42static uint32_t volatile g_u32ClientHandleCount;
43
44static PAVLULNODECORE g_pTree;
45
46
47DECLINLINE(int) hgcmObjEnter (void)
48{
49 return RTCritSectEnter (&g_critsect);
50}
51
52DECLINLINE(void) hgcmObjLeave (void)
53{
54 RTCritSectLeave (&g_critsect);
55}
56
57int hgcmObjInit (void)
58{
59 int rc = VINF_SUCCESS;
60
61 LogFlow(("MAIN::hgcmObjInit\n"));
62
63 g_u32InternalHandleCount = 0x80000000;
64 g_u32ClientHandleCount = 0;
65 g_pTree = NULL;
66
67 rc = RTCritSectInit (&g_critsect);
68
69 LogFlow(("MAIN::hgcmObjInit: rc = %Vrc\n", rc));
70
71 return rc;
72}
73
74void hgcmObjUninit (void)
75{
76 if (RTCritSectIsInitialized (&g_critsect))
77 {
78 RTCritSectDelete (&g_critsect);
79 }
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 rc = hgcmObjEnter ();
89
90 if (VBOX_SUCCESS(rc))
91 {
92 ObjectAVLCore *pCore = &pObject->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 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 bRC = RTAvlULInsert(&g_pTree, &pCore->AvlCore);
136
137 /* Could not insert a handle. */
138 if (!bRC)
139 {
140 if (u32HandleIn == 0)
141 {
142 /* Try another generated handle. */
143 continue;
144 }
145 else
146 {
147 /* Could not use the specified handle. */
148 break;
149 }
150 }
151
152 /* Initialize backlink. */
153 pCore->pSelf = pObject;
154
155 /* Reference the object for time while it resides in the tree. */
156 pObject->Reference ();
157
158 /* Store returned handle. */
159 handle = Key;
160
161 Log(("Object key inserted 0x%08X\n", Key));
162
163 break;
164 }
165
166 hgcmObjLeave ();
167 }
168 else
169 {
170 AssertReleaseMsgFailed (("MAIN::hgcmObjGenerateHandle: Failed to acquire object pool semaphore"));
171 }
172
173 LogFlow(("MAIN::hgcmObjGenerateHandle: handle = 0x%08X, rc = %Vrc, return void\n", handle, rc));
174
175 return handle;
176}
177
178uint32_t hgcmObjGenerateHandle (HGCMObject *pObject)
179{
180 return hgcmObjMake (pObject, 0);
181}
182
183uint32_t hgcmObjAssignHandle (HGCMObject *pObject, uint32_t u32Handle)
184{
185 return hgcmObjMake (pObject, u32Handle);
186}
187
188void hgcmObjDeleteHandle (uint32_t handle)
189{
190 int rc = VINF_SUCCESS;
191
192 LogFlow(("MAIN::hgcmObjDeleteHandle: handle 0x%08X\n", handle));
193
194 if (handle)
195 {
196 rc = hgcmObjEnter ();
197
198 if (VBOX_SUCCESS(rc))
199 {
200 ObjectAVLCore *pCore = (ObjectAVLCore *)RTAvlULRemove (&g_pTree, handle);
201
202 if (pCore)
203 {
204 AssertRelease(pCore->pSelf);
205
206 pCore->pSelf->Dereference ();
207 }
208
209 hgcmObjLeave ();
210 }
211 else if (rc == VERR_SEM_DESTROYED)
212 {
213 // Should only occur on shutdown, just ignore this case here
214 }
215 else
216 {
217 AssertReleaseMsgFailed (("Failed to acquire object pool semaphore, rc = %Vrc", rc));
218 }
219 }
220
221 LogFlow(("MAIN::hgcmObjDeleteHandle: rc = %Vrc, return void\n", rc));
222
223 return;
224}
225
226HGCMObject *hgcmObjReference (uint32_t handle, HGCMOBJ_TYPE enmObjType)
227{
228 LogFlow(("MAIN::hgcmObjReference: handle 0x%08X\n", handle));
229
230 HGCMObject *pObject = NULL;
231
232 int rc = hgcmObjEnter ();
233
234 if (VBOX_SUCCESS(rc))
235 {
236 ObjectAVLCore *pCore = (ObjectAVLCore *)RTAvlULGet (&g_pTree, handle);
237
238 Assert(!pCore || (pCore->pSelf && pCore->pSelf->Type() == enmObjType));
239 if ( pCore
240 && pCore->pSelf
241 && pCore->pSelf->Type() == enmObjType)
242 {
243 pObject = pCore->pSelf;
244
245 AssertRelease(pObject);
246
247 pObject->Reference ();
248 }
249
250 hgcmObjLeave ();
251 }
252 else
253 {
254 AssertReleaseMsgFailed (("Failed to acquire object pool semaphore, rc = %Vrc", rc));
255 }
256
257 LogFlow(("MAIN::hgcmObjReference: return pObject %p\n", pObject));
258
259 return pObject;
260}
261
262void hgcmObjDereference (HGCMObject *pObject)
263{
264 LogFlow(("MAIN::hgcmObjDereference: pObject %p\n", pObject));
265
266 AssertRelease(pObject);
267
268 pObject->Dereference ();
269
270 LogFlow(("MAIN::hgcmObjDereference: return\n"));
271}
272
273uint32_t hgcmObjQueryHandleCount ()
274{
275 return g_u32ClientHandleCount;
276}
277
278void hgcmObjSetHandleCount (uint32_t u32ClientHandleCount)
279{
280 Assert(g_u32ClientHandleCount <= u32ClientHandleCount);
281
282 int rc = hgcmObjEnter ();
283
284 if (VBOX_SUCCESS(rc))
285 {
286 if (g_u32ClientHandleCount <= u32ClientHandleCount)
287 g_u32ClientHandleCount = u32ClientHandleCount;
288 hgcmObjLeave ();
289 }
290}
Note: See TracBrowser for help on using the repository browser.

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