VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTR0SemMutex.cpp@ 100762

Last change on this file since 100762 was 98103, checked in by vboxsync, 2 years ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.0 KB
Line 
1/* $Id: tstRTR0SemMutex.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT R0 Testcase - Mutex Semaphores.
4 */
5
6/*
7 * Copyright (C) 2009-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#include <iprt/semaphore.h>
42
43#include <iprt/errcore.h>
44#include <VBox/sup.h>
45#include <iprt/string.h>
46#include <iprt/time.h>
47#include <iprt/thread.h>
48#include "tstRTR0SemMutex.h"
49
50
51/*********************************************************************************************************************************
52* Global Variables *
53*********************************************************************************************************************************/
54/** The mutex used in test #2. */
55static RTSEMMUTEX g_hMtxTest2 = NIL_RTSEMMUTEX;
56
57
58
59/**
60 * Service request callback function.
61 *
62 * @returns VBox status code.
63 * @param pSession The caller's session.
64 * @param u64Arg 64-bit integer argument.
65 * @param pReqHdr The request header. Input / Output. Optional.
66 */
67DECLEXPORT(int) TSTRTR0SemMutexSrvReqHandler(PSUPDRVSESSION pSession, uint32_t uOperation,
68 uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr)
69{
70 NOREF(pSession);
71 if (!RT_VALID_PTR(pReqHdr))
72 return VERR_INVALID_PARAMETER;
73 char *pszErr = (char *)(pReqHdr + 1);
74 size_t cchErr = pReqHdr->cbReq - sizeof(*pReqHdr);
75 if (cchErr < 32 || cchErr >= 0x10000)
76 return VERR_INVALID_PARAMETER;
77 *pszErr = '\0';
78
79#define SET_ERROR(szFmt) do { if (!*pszErr) RTStrPrintf(pszErr, cchErr, "!" szFmt); } while (0)
80#define SET_ERROR1(szFmt, a1) do { if (!*pszErr) RTStrPrintf(pszErr, cchErr, "!" szFmt, a1); } while (0)
81#define SET_ERROR2(szFmt, a1, a2) do { if (!*pszErr) RTStrPrintf(pszErr, cchErr, "!" szFmt, a1, a2); } while (0)
82#define SET_ERROR3(szFmt, a1, a2, a3) do { if (!*pszErr) RTStrPrintf(pszErr, cchErr, "!" szFmt, a1, a2, a3); } while (0)
83#define CHECK_RC_BREAK(rc, rcExpect, szOp) \
84 if ((rc) != (rcExpect)) \
85 { \
86 RTStrPrintf(pszErr, cchErr, "!%s -> %Rrc, expected %Rrc. line %u", szOp, rc, rcExpect, __LINE__); \
87 SUPR0Printf("%s -> %d, expected %d. line %u", szOp, rc, rcExpect, __LINE__); \
88 break; \
89 }
90
91 /*
92 * Set up test timeout (when applicable).
93 */
94 if (u64Arg > 120)
95 {
96 SET_ERROR1("Timeout is too large (max 120): %lld", u64Arg);
97 return VINF_SUCCESS;
98 }
99 uint64_t const StartTS = RTTimeSystemMilliTS();
100 uint32_t const cMsMax = (uint32_t)u64Arg * 1000;
101
102 /*
103 * The big switch.
104 */
105 RTSEMMUTEX hMtx;
106 int rc;
107 switch (uOperation)
108 {
109 case TSTRTR0SEMMUTEX_SANITY_OK:
110 break;
111
112 case TSTRTR0SEMMUTEX_SANITY_FAILURE:
113 SET_ERROR1("42failure42%1024s", "");
114 break;
115
116 case TSTRTR0SEMMUTEX_BASIC:
117 rc = RTSemMutexCreate(&hMtx);
118 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexCreate");
119 do
120 {
121 /*
122 * The interruptible version first.
123 */
124 /* simple request and release, polling. */
125 rc = RTSemMutexRequestNoResume(hMtx, 0);
126 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume");
127 rc = RTSemMutexRelease(hMtx);
128 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
129
130 /* simple request and release, wait for ever. */
131 rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
132 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(indef_wait)");
133 rc = RTSemMutexRelease(hMtx);
134 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
135
136 /* simple request and release, wait a tiny while. */
137 rc = RTSemMutexRequestNoResume(hMtx, 133);
138 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(133)");
139 rc = RTSemMutexRelease(hMtx);
140 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
141
142 /* nested request and release. */
143 rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
144 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume#1");
145 rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
146 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume#2");
147 rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
148 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume#3");
149 rc = RTSemMutexRelease(hMtx);
150 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#3");
151 rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
152 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume#3b");
153 rc = RTSemMutexRelease(hMtx);
154 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#3b");
155 rc = RTSemMutexRelease(hMtx);
156 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#2");
157 rc = RTSemMutexRelease(hMtx);
158 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#1");
159
160 /*
161 * The uninterruptible variant.
162 */
163 /* simple request and release, polling. */
164 rc = RTSemMutexRequest(hMtx, 0);
165 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest");
166 rc = RTSemMutexRelease(hMtx);
167 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
168
169 /* simple request and release, wait for ever. */
170 rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
171 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest(indef_wait)");
172 rc = RTSemMutexRelease(hMtx);
173 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
174
175 /* simple request and release, wait a tiny while. */
176 rc = RTSemMutexRequest(hMtx, 133);
177 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest(133)");
178 rc = RTSemMutexRelease(hMtx);
179 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
180
181 /* nested request and release. */
182 rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
183 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest#1");
184 rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
185 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest#2");
186 rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
187 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest#3");
188 rc = RTSemMutexRelease(hMtx);
189 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#3");
190 rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
191 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest#3b");
192 rc = RTSemMutexRelease(hMtx);
193 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#3b");
194 rc = RTSemMutexRelease(hMtx);
195 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#2");
196 rc = RTSemMutexRelease(hMtx);
197 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#1");
198
199 } while (false);
200
201 rc = RTSemMutexDestroy(hMtx);
202 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexDestroy");
203 break;
204
205 case TSTRTR0SEMMUTEX_TEST2_SETUP:
206 case TSTRTR0SEMMUTEX_TEST3_SETUP:
207 case TSTRTR0SEMMUTEX_TEST4_SETUP:
208 rc = RTSemMutexCreate(&g_hMtxTest2);
209 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexCreate");
210 break;
211
212 case TSTRTR0SEMMUTEX_TEST2_DO:
213 for (unsigned i = 0; i < 200; i++)
214 {
215 if (i & 1)
216 {
217 rc = RTSemMutexRequestNoResume(g_hMtxTest2, RT_INDEFINITE_WAIT);
218 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(,indef_wait)");
219 }
220 else
221 {
222 rc = RTSemMutexRequestNoResume(g_hMtxTest2, 30000);
223 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(,30000)");
224 }
225 RTThreadSleep(1);
226 rc = RTSemMutexRelease(g_hMtxTest2);
227 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
228
229 if ((i % 16) == 15 && RTTimeSystemMilliTS() - StartTS >= cMsMax)
230 break;
231 }
232 break;
233
234
235 case TSTRTR0SEMMUTEX_TEST3_DO:
236 for (unsigned i = 0; i < 1000000; i++)
237 {
238 if (i & 1)
239 {
240 rc = RTSemMutexRequestNoResume(g_hMtxTest2, RT_INDEFINITE_WAIT);
241 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(,indef_wait)");
242 }
243 else
244 {
245 rc = RTSemMutexRequestNoResume(g_hMtxTest2, 30000);
246 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(,30000)");
247 }
248 rc = RTSemMutexRelease(g_hMtxTest2);
249 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
250
251 if ((i % 256) == 255 && RTTimeSystemMilliTS() - StartTS >= cMsMax)
252 break;
253 }
254 break;
255
256 case TSTRTR0SEMMUTEX_TEST4_DO:
257 for (unsigned i = 0; i < 1024; i++)
258 {
259 rc = RTSemMutexRequestNoResume(g_hMtxTest2, (i % 32));
260 if (rc != VERR_TIMEOUT)
261 {
262 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume");
263 RTThreadSleep(1000);
264
265 rc = RTSemMutexRelease(g_hMtxTest2);
266 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
267 }
268
269 if (RTTimeSystemMilliTS() - StartTS >= cMsMax)
270 break;
271 }
272 break;
273
274 case TSTRTR0SEMMUTEX_TEST2_CLEANUP:
275 case TSTRTR0SEMMUTEX_TEST3_CLEANUP:
276 case TSTRTR0SEMMUTEX_TEST4_CLEANUP:
277 rc = RTSemMutexDestroy(g_hMtxTest2);
278 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexCreate");
279 g_hMtxTest2 = NIL_RTSEMMUTEX;
280 break;
281
282
283 default:
284 SET_ERROR1("Unknown test #%d", uOperation);
285 break;
286 }
287
288 /* The error indicator is the '!' in the message buffer. */
289 return VINF_SUCCESS;
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