VirtualBox

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

Last change on this file since 36363 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.4 KB
Line 
1/* $Id: tstRTR0SemMutex.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
2/** @file
3 * IPRT R0 Testcase - Mutex Semaphores.
4 */
5
6/*
7 * Copyright (C) 2009-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#include <iprt/semaphore.h>
31
32#include <iprt/err.h>
33#include <VBox/sup.h>
34#include <iprt/string.h>
35#include <iprt/time.h>
36#include <iprt/thread.h>
37#include "tstRTR0SemMutex.h"
38
39
40/*******************************************************************************
41* Global Variables *
42*******************************************************************************/
43/** The mutex used in test #2. */
44static RTSEMMUTEX g_hMtxTest2 = NIL_RTSEMMUTEX;
45
46
47
48/**
49 * Service request callback function.
50 *
51 * @returns VBox status code.
52 * @param pSession The caller's session.
53 * @param u64Arg 64-bit integer argument.
54 * @param pReqHdr The request header. Input / Output. Optional.
55 */
56DECLEXPORT(int) TSTRTR0SemMutexSrvReqHandler(PSUPDRVSESSION pSession, uint32_t uOperation,
57 uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr)
58{
59 if (!VALID_PTR(pReqHdr))
60 return VERR_INVALID_PARAMETER;
61 char *pszErr = (char *)(pReqHdr + 1);
62 size_t cchErr = pReqHdr->cbReq - sizeof(*pReqHdr);
63 if (cchErr < 32 || cchErr >= 0x10000)
64 return VERR_INVALID_PARAMETER;
65 *pszErr = '\0';
66
67#define SET_ERROR(szFmt) do { if (!*pszErr) RTStrPrintf(pszErr, cchErr, "!" szFmt); } while (0)
68#define SET_ERROR1(szFmt, a1) do { if (!*pszErr) RTStrPrintf(pszErr, cchErr, "!" szFmt, a1); } while (0)
69#define SET_ERROR2(szFmt, a1, a2) do { if (!*pszErr) RTStrPrintf(pszErr, cchErr, "!" szFmt, a1, a2); } while (0)
70#define SET_ERROR3(szFmt, a1, a2, a3) do { if (!*pszErr) RTStrPrintf(pszErr, cchErr, "!" szFmt, a1, a2, a3); } while (0)
71#define CHECK_RC_BREAK(rc, rcExpect, szOp) \
72 if ((rc) != (rcExpect)) \
73 { \
74 RTStrPrintf(pszErr, cchErr, "!%s -> %Rrc, expected %Rrc. line %u", szOp, rc, rcExpect, __LINE__); \
75 SUPR0Printf("%s -> %d, expected %d. line %u", szOp, rc, rcExpect, __LINE__); \
76 break; \
77 }
78
79 /*
80 * Set up test timeout (when applicable).
81 */
82 if (u64Arg > 120)
83 {
84 SET_ERROR1("Timeout is too large (max 120): %lld", u64Arg);
85 return VINF_SUCCESS;
86 }
87 uint64_t const StartTS = RTTimeSystemMilliTS();
88 uint32_t const cMsMax = (uint32_t)u64Arg * 1000;
89
90 /*
91 * The big switch.
92 */
93 RTSEMMUTEX hMtx;
94 int rc;
95 switch (uOperation)
96 {
97 case TSTRTR0SEMMUTEX_SANITY_OK:
98 break;
99
100 case TSTRTR0SEMMUTEX_SANITY_FAILURE:
101 SET_ERROR1("42failure42%1024s", "");
102 break;
103
104 case TSTRTR0SEMMUTEX_BASIC:
105 rc = RTSemMutexCreate(&hMtx);
106 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexCreate");
107 do
108 {
109 /*
110 * The interruptible version first.
111 */
112 /* simple request and release, polling. */
113 rc = RTSemMutexRequestNoResume(hMtx, 0);
114 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume");
115 rc = RTSemMutexRelease(hMtx);
116 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
117
118 /* simple request and release, wait for ever. */
119 rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
120 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(indef_wait)");
121 rc = RTSemMutexRelease(hMtx);
122 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
123
124 /* simple request and release, wait a tiny while. */
125 rc = RTSemMutexRequestNoResume(hMtx, 133);
126 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(133)");
127 rc = RTSemMutexRelease(hMtx);
128 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
129
130 /* nested request and release. */
131 rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
132 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume#1");
133 rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
134 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume#2");
135 rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
136 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume#3");
137 rc = RTSemMutexRelease(hMtx);
138 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#3");
139 rc = RTSemMutexRequestNoResume(hMtx, RT_INDEFINITE_WAIT);
140 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume#3b");
141 rc = RTSemMutexRelease(hMtx);
142 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#3b");
143 rc = RTSemMutexRelease(hMtx);
144 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#2");
145 rc = RTSemMutexRelease(hMtx);
146 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#1");
147
148 /*
149 * The uninterruptible variant.
150 */
151 /* simple request and release, polling. */
152 rc = RTSemMutexRequest(hMtx, 0);
153 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest");
154 rc = RTSemMutexRelease(hMtx);
155 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
156
157 /* simple request and release, wait for ever. */
158 rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
159 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest(indef_wait)");
160 rc = RTSemMutexRelease(hMtx);
161 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
162
163 /* simple request and release, wait a tiny while. */
164 rc = RTSemMutexRequest(hMtx, 133);
165 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest(133)");
166 rc = RTSemMutexRelease(hMtx);
167 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
168
169 /* nested request and release. */
170 rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
171 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest#1");
172 rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
173 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest#2");
174 rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
175 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest#3");
176 rc = RTSemMutexRelease(hMtx);
177 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#3");
178 rc = RTSemMutexRequest(hMtx, RT_INDEFINITE_WAIT);
179 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequest#3b");
180 rc = RTSemMutexRelease(hMtx);
181 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#3b");
182 rc = RTSemMutexRelease(hMtx);
183 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#2");
184 rc = RTSemMutexRelease(hMtx);
185 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease#1");
186
187 } while (false);
188
189 rc = RTSemMutexDestroy(hMtx);
190 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexDestroy");
191 break;
192
193 case TSTRTR0SEMMUTEX_TEST2_SETUP:
194 case TSTRTR0SEMMUTEX_TEST3_SETUP:
195 case TSTRTR0SEMMUTEX_TEST4_SETUP:
196 rc = RTSemMutexCreate(&g_hMtxTest2);
197 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexCreate");
198 break;
199
200 case TSTRTR0SEMMUTEX_TEST2_DO:
201 for (unsigned i = 0; i < 200; i++)
202 {
203 if (i & 1)
204 {
205 rc = RTSemMutexRequestNoResume(g_hMtxTest2, RT_INDEFINITE_WAIT);
206 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(,indef_wait)");
207 }
208 else
209 {
210 rc = RTSemMutexRequestNoResume(g_hMtxTest2, 30000);
211 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(,30000)");
212 }
213 RTThreadSleep(1);
214 rc = RTSemMutexRelease(g_hMtxTest2);
215 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
216
217 if ((i % 16) == 15 && RTTimeSystemMilliTS() - StartTS >= cMsMax)
218 break;
219 }
220 break;
221
222
223 case TSTRTR0SEMMUTEX_TEST3_DO:
224 for (unsigned i = 0; i < 1000000; i++)
225 {
226 if (i & 1)
227 {
228 rc = RTSemMutexRequestNoResume(g_hMtxTest2, RT_INDEFINITE_WAIT);
229 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(,indef_wait)");
230 }
231 else
232 {
233 rc = RTSemMutexRequestNoResume(g_hMtxTest2, 30000);
234 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume(,30000)");
235 }
236 rc = RTSemMutexRelease(g_hMtxTest2);
237 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
238
239 if ((i % 256) == 255 && RTTimeSystemMilliTS() - StartTS >= cMsMax)
240 break;
241 }
242 break;
243
244 case TSTRTR0SEMMUTEX_TEST4_DO:
245 for (unsigned i = 0; i < 1024; i++)
246 {
247 rc = RTSemMutexRequestNoResume(g_hMtxTest2, (i % 32));
248 if (rc != VERR_TIMEOUT)
249 {
250 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRequestNoResume");
251 RTThreadSleep(1000);
252
253 rc = RTSemMutexRelease(g_hMtxTest2);
254 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexRelease");
255 }
256
257 if (RTTimeSystemMilliTS() - StartTS >= cMsMax)
258 break;
259 }
260 break;
261
262 case TSTRTR0SEMMUTEX_TEST2_CLEANUP:
263 case TSTRTR0SEMMUTEX_TEST3_CLEANUP:
264 case TSTRTR0SEMMUTEX_TEST4_CLEANUP:
265 rc = RTSemMutexDestroy(g_hMtxTest2);
266 CHECK_RC_BREAK(rc, VINF_SUCCESS, "RTSemMutexCreate");
267 g_hMtxTest2 = NIL_RTSEMMUTEX;
268 break;
269
270
271 default:
272 SET_ERROR1("Unknown test #%d", uOperation);
273 break;
274 }
275
276 /* The error indicator is the '!' in the message buffer. */
277 return VINF_SUCCESS;
278}
279
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