VirtualBox

source: vbox/trunk/src/VBox/HostServices/testcase/TstHGCMMockUtils.cpp@ 98576

Last change on this file since 98576 was 98576, checked in by vboxsync, 22 months ago

HGCMMock*.h: Split out the code into .cpp files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.4 KB
Line 
1/* $Id: TstHGCMMockUtils.cpp 98576 2023-02-15 01:48:41Z vboxsync $ */
2/** @file
3 * TstHGCMMockUtils.cpp - Utility functions for the HGCM Mocking framework.
4 */
5
6/*
7 * Copyright (C) 2022-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
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <VBox/GuestHost/HGCMMockUtils.h>
33
34#include <iprt/err.h>
35#include <iprt/semaphore.h>
36#include <iprt/thread.h>
37#include <iprt/types.h>
38
39
40/*********************************************************************************************************************************
41* Context *
42*********************************************************************************************************************************/
43/**
44 * Initializes a HGCM Mock utils context.
45 *
46 * @param pCtx Context to intiialize.
47 * @param pSvc HGCM Mock service instance to use.
48 */
49void TstHGCMUtilsCtxInit(PTSTHGCMUTILSCTX pCtx, PTSTHGCMMOCKSVC pSvc)
50{
51 RT_BZERO(pCtx, sizeof(TSTHGCMUTILSCTX));
52
53 pCtx->pSvc = pSvc;
54}
55
56
57/*********************************************************************************************************************************
58* Tasks *
59*********************************************************************************************************************************/
60/**
61 * Returns the current task of a HGCM Mock utils context.
62 *
63 * @returns Current task of a HGCM Mock utils context. NULL if no current task found.
64 * @param pCtx HGCM Mock utils context.
65 */
66PTSTHGCMUTILSTASK TstHGCMUtilsTaskGetCurrent(PTSTHGCMUTILSCTX pCtx)
67{
68 /* Currently we only support one task at a time. */
69 return &pCtx->Task;
70}
71
72/**
73 * Initializes a HGCM Mock utils task.
74 *
75 * @returns VBox status code.
76 * @param pTask Task to initialize.
77 */
78int TstHGCMUtilsTaskInit(PTSTHGCMUTILSTASK pTask)
79{
80 pTask->pvUser = NULL;
81 pTask->rcCompleted = pTask->rcExpected = VERR_IPE_UNINITIALIZED_STATUS;
82 return RTSemEventCreate(&pTask->hEvent);
83}
84
85/**
86 * Destroys a HGCM Mock utils task.
87 *
88 * @returns VBox status code.
89 * @param pTask Task to destroy.
90 */
91void TstHGCMUtilsTaskDestroy(PTSTHGCMUTILSTASK pTask)
92{
93 RTSemEventDestroy(pTask->hEvent);
94}
95
96/**
97 * Waits for a HGCM Mock utils task to complete.
98 *
99 * @returns VBox status code.
100 * @param pTask Task to wait for.
101 * @param msTimeout Timeout (in ms) to wait.
102 */
103int TstHGCMUtilsTaskWait(PTSTHGCMUTILSTASK pTask, RTMSINTERVAL msTimeout)
104{
105 return RTSemEventWait(pTask->hEvent, msTimeout);
106}
107
108/**
109 * Returns if the HGCM Mock utils task has been completed successfully.
110 *
111 * @returns \c true if successful, \c false if not.
112 * @param pTask Task to check.
113 */
114bool TstHGCMUtilsTaskOk(PTSTHGCMUTILSTASK pTask)
115{
116 return pTask->rcCompleted == pTask->rcExpected;
117}
118
119/**
120 * Returns if the HGCM Mock utils task has been completed (failed or succeeded).
121 *
122 * @returns \c true if completed, \c false if (still) running.
123 * @param pTask Task to check.
124 */
125bool TstHGCMUtilsTaskCompleted(PTSTHGCMUTILSTASK pTask)
126{
127 return pTask->rcCompleted != VERR_IPE_UNINITIALIZED_STATUS;
128}
129
130/**
131 * Signals a HGCM Mock utils task to complete its operation.
132 *
133 * @param pTask Task to complete.
134 * @param rc Task result to set for completion.
135 */
136void TstHGCMUtilsTaskSignal(PTSTHGCMUTILSTASK pTask, int rc)
137{
138 AssertMsg(pTask->rcCompleted == VERR_IPE_UNINITIALIZED_STATUS, ("Task already completed\n"));
139 pTask->rcCompleted = rc;
140 int rc2 = RTSemEventSignal(pTask->hEvent);
141 AssertRC(rc2);
142}
143
144
145/*********************************************************************************************************************************
146 * Threading *
147 ********************************************************************************************************************************/
148
149/**
150 * Thread worker for the guest side thread.
151 *
152 * @returns VBox status code.
153 * @param hThread Thread handle.
154 * @param pvUser Pointer of type PTSTHGCMUTILSCTX.
155 *
156 * @note Runs in the guest thread.
157 */
158static DECLCALLBACK(int) tstHGCMUtilsGuestThread(RTTHREAD hThread, void *pvUser)
159{
160 RT_NOREF(hThread);
161 PTSTHGCMUTILSCTX pCtx = (PTSTHGCMUTILSCTX)pvUser;
162 AssertPtr(pCtx);
163
164 RTThreadUserSignal(hThread);
165
166 if (pCtx->Guest.pfnThread)
167 return pCtx->Guest.pfnThread(pCtx, pCtx->Guest.pvUser);
168
169 return VINF_SUCCESS;
170}
171
172/**
173 * Starts the guest side thread.
174 *
175 * @returns VBox status code.
176 * @param pCtx HGCM Mock utils context to start guest thread for.
177 * @param pFnThread Pointer to custom thread worker function to call within the guest side thread.
178 * @param pvUser User-supplied pointer to guest thread context data. Optional and can be NULL.
179 */
180int TstHGCMUtilsGuestThreadStart(PTSTHGCMUTILSCTX pCtx, PFNTSTHGCMUTILSTHREAD pFnThread, void *pvUser)
181{
182 pCtx->Guest.pfnThread = pFnThread;
183 pCtx->Guest.pvUser = pvUser;
184
185 int rc = RTThreadCreate(&pCtx->Guest.hThread, tstHGCMUtilsGuestThread, pCtx, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
186 "tstShClGst");
187 if (RT_SUCCESS(rc))
188 rc = RTThreadUserWait(pCtx->Guest.hThread, RT_MS_30SEC);
189
190 return rc;
191}
192
193/**
194 * Stops the guest side thread.
195 *
196 * @returns VBox status code.
197 * @param pCtx HGCM Mock utils context to stop guest thread for.
198 */
199int TstHGCMUtilsGuestThreadStop(PTSTHGCMUTILSCTX pCtx)
200{
201 ASMAtomicWriteBool(&pCtx->Guest.fShutdown, true);
202
203 int rcThread;
204 int rc = RTThreadWait(pCtx->Guest.hThread, RT_MS_30SEC, &rcThread);
205 if (RT_SUCCESS(rc))
206 rc = rcThread;
207 if (RT_SUCCESS(rc))
208 pCtx->Guest.hThread = NIL_RTTHREAD;
209
210 return rc;
211}
212
213/**
214 * Thread worker function for the host side HGCM service.
215 *
216 * @returns VBox status code.
217 * @param hThread Thread handle.
218 * @param pvUser Pointer of type PTSTHGCMUTILSCTX.
219 *
220 * @note Runs in the host service thread.
221 */
222static DECLCALLBACK(int) tstHGCMUtilsHostThreadWorker(RTTHREAD hThread, void *pvUser)
223{
224 RT_NOREF(hThread);
225 PTSTHGCMUTILSCTX pCtx = (PTSTHGCMUTILSCTX)pvUser;
226 AssertPtr(pCtx);
227
228 int rc = VINF_SUCCESS;
229
230 RTThreadUserSignal(hThread);
231
232 PTSTHGCMMOCKSVC const pSvc = TstHgcmMockSvcInst();
233
234 for (;;)
235 {
236 if (ASMAtomicReadBool(&pCtx->Host.fShutdown))
237 break;
238
239 /* Wait for a new (mock) HGCM client to connect. */
240 PTSTHGCMMOCKCLIENT pMockClient = TstHgcmMockSvcWaitForConnectEx(pSvc, 100 /* ms */);
241 if (pMockClient) /* Might be NULL when timed out. */
242 {
243 if (pCtx->Host.Callbacks.pfnOnClientConnected)
244 /* ignore rc */ pCtx->Host.Callbacks.pfnOnClientConnected(pCtx, pMockClient, pCtx->Host.pvUser);
245 }
246 }
247
248 return rc;
249}
250
251/**
252 * Starts the host side thread.
253 *
254 * @returns VBox status code.
255 * @param pCtx HGCM Mock utils context to start host thread for.
256 * @param pCallbacks Pointer to host callback table to use.
257 * @param pvUser User-supplied pointer to reach into the host thread callbacks.
258 */
259int TstHGCMUtilsHostThreadStart(PTSTHGCMUTILSCTX pCtx, PTSTHGCMUTILSHOSTCALLBACKS pCallbacks, void *pvUser)
260{
261 memcpy(&pCtx->Host.Callbacks, pCallbacks, sizeof(TSTHGCMUTILSHOSTCALLBACKS));
262 pCtx->Host.pvUser = pvUser;
263
264 int rc = RTThreadCreate(&pCtx->Host.hThread, tstHGCMUtilsHostThreadWorker, pCtx, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE,
265 "tstShClHst");
266 if (RT_SUCCESS(rc))
267 rc = RTThreadUserWait(pCtx->Host.hThread, RT_MS_30SEC);
268
269 return rc;
270}
271
272/**
273 * Stops the host side thread.
274 *
275 * @returns VBox status code.
276 * @param pCtx HGCM Mock utils context to stop host thread for.
277 */
278int TstHGCMUtilsHostThreadStop(PTSTHGCMUTILSCTX pCtx)
279{
280 ASMAtomicWriteBool(&pCtx->Host.fShutdown, true);
281
282 int rcThread;
283 int rc = RTThreadWait(pCtx->Host.hThread, RT_MS_30SEC, &rcThread);
284 if (RT_SUCCESS(rc))
285 rc = rcThread;
286 if (RT_SUCCESS(rc))
287 pCtx->Host.hThread = NIL_RTTHREAD;
288
289 return rc;
290}
291
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