VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp@ 25605

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

tstDeadlock -> tstRTLockValidator.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.6 KB
Line 
1/* $Id: tstRTLockValidator.cpp 25605 2009-12-31 02:30:48Z vboxsync $ */
2/** @file
3 * IPRT Testcase - RTLockValidator.
4 */
5
6/*
7 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include <iprt/asm.h> /* for return addresses */
36#include <iprt/critsect.h>
37#include <iprt/lockvalidator.h>
38
39#include <iprt/err.h>
40#include <iprt/stream.h>
41#include <iprt/thread.h>
42#include <iprt/test.h>
43
44
45/*******************************************************************************
46* Global Variables *
47*******************************************************************************/
48static RTTEST g_hTest;
49
50static uint32_t g_cThreads;
51static RTTHREAD g_ahThreads[32];
52static RTCRITSECT g_aCritSects[32];
53
54
55/**
56 * Spin until someone else has taken ownership of the critical section.
57 *
58 * @returns true on success, false on abort.
59 * @param pCritSect The critical section.
60 */
61static bool testWaitForCritSectToBeOwned(PRTCRITSECT pCritSect)
62{
63 unsigned iLoop = 0;
64 while (!RTCritSectIsOwned(pCritSect))
65 {
66 if (!RTCritSectIsInitialized(pCritSect))
67 return false;
68 RTThreadSleep(iLoop > 256 ? 1 : 0);
69 iLoop++;
70 }
71 return true;
72}
73
74
75/**
76 * Waits for a thread to enter a sleeping state.
77 *
78 * @returns true on success, false on abort.
79 * @param hThread The thread.
80 */
81static bool testWaitForThreadToSleep(RTTHREAD hThread)
82{
83 for (unsigned iLoop = 0; ; iLoop++)
84 {
85 RTTHREADSTATE enmState = RTThreadGetState(hThread);
86 if (RTTHREAD_IS_SLEEPING(enmState))
87 return true;
88 if (enmState != RTTHREADSTATE_RUNNING)
89 return false;
90 RTThreadSleep(iLoop > 256 ? 1 : 0);
91 }
92}
93
94
95static DECLCALLBACK(int) test1Thread(RTTHREAD ThreadSelf, void *pvUser)
96{
97 uintptr_t i = (uintptr_t)pvUser;
98 PRTCRITSECT pMine = &g_aCritSects[i];
99 PRTCRITSECT pNext = &g_aCritSects[(i + 1) % g_cThreads];
100
101 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectEnter(pMine), VINF_SUCCESS, rcCheck);
102 if (testWaitForCritSectToBeOwned(pNext))
103 {
104 int rc;
105 if (i != g_cThreads - 1)
106 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VINF_SUCCESS);
107 else
108 {
109 /* the last thread triggers the deadlock. */
110 for (unsigned i = 0; i < g_cThreads - 1; i++)
111 RTTEST_CHECK_RET(g_hTest, testWaitForThreadToSleep(g_ahThreads[i]), VINF_SUCCESS);
112 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VERR_SEM_LV_DEADLOCK);
113 }
114 if (RT_SUCCESS(rc))
115 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectLeave(pNext), VINF_SUCCESS);
116 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(pMine), VINF_SUCCESS);
117 }
118 return VINF_SUCCESS;
119}
120
121
122static void test1(uint32_t cThreads)
123{
124 uint32_t i;
125 RTTestSubF(g_hTest, "critsect deadlock with %u threads", cThreads);
126 RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_ahThreads) >= cThreads);
127 RTTEST_CHECK_RETV(g_hTest, RT_ELEMENTS(g_aCritSects) >= cThreads);
128
129 g_cThreads = cThreads;
130 for (i = 0; i < cThreads; i++)
131 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectInit(&g_aCritSects[i]), VINF_SUCCESS);
132
133 for (i = 0; i < cThreads && g_ahThreads[i]; i++)
134 g_ahThreads[i] = NIL_RTTHREAD;
135 int rc = VINF_SUCCESS;
136 for (i = 0; i < cThreads && RT_SUCCESS(rc); i++)
137 RTTEST_CHECK_RC_OK(g_hTest, rc = RTThreadCreateF(&g_ahThreads[i], test1Thread, (void *)(uintptr_t)i, 0,
138 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "test1-%02u", i));
139 if (RT_SUCCESS(rc))
140 {
141 int rc2 = VINF_SUCCESS;
142 i = cThreads;
143 while (i-- > 0 && RT_SUCCESS(rc) && RT_SUCCESS(rc2))
144 {
145 RTTEST_CHECK_RC_OK(g_hTest, rc = RTThreadWait(g_ahThreads[i], 30*1000, &rc2));
146 if (RT_SUCCESS(rc))
147 g_ahThreads[i] = NIL_RTTHREAD;
148 }
149 }
150
151 for (uint32_t i = 0; i < cThreads; i++)
152 RTTEST_CHECK_RC_RETV(g_hTest, RTCritSectDelete(&g_aCritSects[i]), VINF_SUCCESS);
153 for (uint32_t i = 0; i < cThreads; i++)
154 if (g_ahThreads[i] != NIL_RTTHREAD)
155 {
156 RTTEST_CHECK_RC_OK(g_hTest, rc = RTThreadWait(g_ahThreads[i], 10*1000, NULL));
157 g_ahThreads[i] = NIL_RTTHREAD;
158 }
159}
160
161static bool testIsLockValidationCompiledIn(void)
162{
163 RTCRITSECT CritSect;
164 RTTEST_CHECK_RC_OK_RET(g_hTest, RTCritSectInit(&CritSect), false);
165 RTTEST_CHECK_RC_OK_RET(g_hTest, RTCritSectEnter(&CritSect), false);
166 bool fRet = CritSect.pValidatorRec
167 && CritSect.pValidatorRec->hThread == RTThreadSelf();
168 RTTEST_CHECK_RC_OK_RET(g_hTest, RTCritSectLeave(&CritSect), false);
169 RTTEST_CHECK_RC_OK_RET(g_hTest, RTCritSectDelete(&CritSect), false);
170
171 /* Add check for the other types as we add more scenarios. */
172 return fRet;
173}
174
175int main()
176{
177 /*
178 * Init.
179 */
180 int rc = RTTestInitAndCreate("tstRTLockValidator", &g_hTest);
181 if (rc)
182 return rc;
183 RTTestBanner(g_hTest);
184
185 RTLockValidatorSetEnabled(true);
186 RTLockValidatorSetMayPanic(false);
187 if (!testIsLockValidationCompiledIn())
188 return RTTestErrorCount(g_hTest) > 0
189 ? RTTestSummaryAndDestroy(g_hTest)
190 : RTTestSkipAndDestroy(g_hTest, "deadlock detection is not compiled in");
191
192 test1(2);
193 test1(3);
194 test1(15);
195 test1(30);
196
197 return RTTestSummaryAndDestroy(g_hTest);
198}
199
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