VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstOnce.cpp@ 100108

Last change on this file since 100108 was 98103, checked in by vboxsync, 23 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.2 KB
Line 
1/* $Id: tstOnce.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT Testcase - RTOnce.
4 */
5
6/*
7 * Copyright (C) 2008-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/once.h>
42#include <iprt/stream.h>
43#include <iprt/initterm.h>
44#include <iprt/thread.h>
45#include <iprt/semaphore.h>
46#include <iprt/string.h>
47#include <iprt/errcore.h>
48#include <iprt/asm.h>
49
50
51/*********************************************************************************************************************************
52* Global Variables *
53*********************************************************************************************************************************/
54static int g_cErrors = 0;
55static bool g_fOnceCB1 = false;
56static uint32_t volatile g_cOnce2CB = 0;
57static bool volatile g_fOnce2Ready = false;
58static RTONCE g_Once2 = RTONCE_INITIALIZER;
59static RTSEMEVENTMULTI g_hEventMulti = NIL_RTSEMEVENTMULTI;
60
61
62static DECLCALLBACK(int) Once1CB(void *pvUser)
63{
64 if (g_fOnceCB1)
65 return VERR_WRONG_ORDER;
66 if (pvUser != (void *)1)
67 {
68 RTPrintf("tstOnce: ERROR - Once1CB: pvUser=%p!\n", pvUser);
69 g_cErrors++;
70 return VERR_INVALID_PARAMETER;
71 }
72 return VINF_SUCCESS;
73}
74
75
76static DECLCALLBACK(int) Once2CB(void *pvUser)
77{
78 if (ASMAtomicIncU32(&g_cOnce2CB) != 1)
79 {
80 RTPrintf("tstOnce: ERROR - Once2CB: g_cOnce2CB not zero!\n");
81 g_cErrors++;
82 return VERR_WRONG_ORDER;
83 }
84 if (pvUser != (void *)42)
85 {
86 RTPrintf("tstOnce: ERROR - Once2CB: pvUser=%p!\n", pvUser);
87 g_cErrors++;
88 return VERR_INVALID_PARAMETER;
89 }
90 RTThreadSleep(2);
91 Assert(!g_fOnce2Ready);
92 ASMAtomicWriteBool(&g_fOnce2Ready, true);
93 return VINF_SUCCESS;
94}
95
96static DECLCALLBACK(int) Once2Thread(RTTHREAD hThread, void *pvUser)
97{
98 NOREF(hThread); NOREF(pvUser);
99
100 int rc = RTSemEventMultiWait(g_hEventMulti, RT_INDEFINITE_WAIT);
101 if (RT_FAILURE(rc))
102 return rc;
103 rc = RTOnce(&g_Once2, Once2CB, (void *)42);
104 if (RT_SUCCESS(rc))
105 {
106 if (!ASMAtomicUoReadBool(&g_fOnce2Ready))
107 {
108 RTPrintf("tstOnce: ERROR - Once2CB: Not initialized!\n");
109 g_cErrors++;
110 }
111 }
112 return rc;
113}
114
115
116int main()
117{
118 RTR3InitExeNoArguments(0);
119
120 /*
121 * Just a simple testcase.
122 */
123 RTPrintf("tstOnce: TESTING - smoke...\n");
124 RTONCE Once1 = RTONCE_INITIALIZER;
125 g_fOnceCB1 = false;
126 int rc = RTOnce(&Once1, Once1CB, (void *)1);
127 if (rc != VINF_SUCCESS)
128 RTPrintf("tstOnce: ERROR - Once1, 1 failed, rc=%Rrc\n", rc);
129 g_fOnceCB1 = false;
130 rc = RTOnce(&Once1, Once1CB, (void *)1);
131 if (rc != VINF_SUCCESS)
132 RTPrintf("tstOnce: ERROR - Once1, 2 failed, rc=%Rrc\n", rc);
133
134 /*
135 * Throw a bunch of threads up against a init once thing.
136 */
137 RTPrintf("tstOnce: TESTING - bunch of threads...\n");
138 /* create the semaphore they'll be waiting on. */
139 rc = RTSemEventMultiCreate(&g_hEventMulti);
140 if (RT_FAILURE(rc))
141 {
142 RTPrintf("tstOnce: FATAL ERROR - RTSemEventMultiCreate returned %Rrc\n", rc);
143 return 1;
144 }
145
146 /* create the threads */
147 RTTHREAD aThreads[32];
148 for (unsigned i = 0; i < RT_ELEMENTS(aThreads); i++)
149 {
150 char szName[16];
151 RTStrPrintf(szName, sizeof(szName), "ONCE2-%d\n", i);
152 rc = RTThreadCreate(&aThreads[i], Once2Thread, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, szName);
153 if (RT_FAILURE(rc))
154 {
155 RTPrintf("tstOnce: ERROR - failed to create thread #%d\n", i);
156 g_cErrors++;
157 }
158 }
159
160 /* kick them off and yield */
161 rc = RTSemEventMultiSignal(g_hEventMulti);
162 if (RT_FAILURE(rc))
163 {
164 RTPrintf("tstOnce: FATAL ERROR - RTSemEventMultiSignal returned %Rrc\n", rc);
165 return 1;
166 }
167 RTThreadYield();
168
169 /* wait for all of them to finish up, 30 seconds each. */
170 for (unsigned i = 0; i < RT_ELEMENTS(aThreads); i++)
171 if (aThreads[i] != NIL_RTTHREAD)
172 {
173 int rc2;
174 rc = RTThreadWait(aThreads[i], 30*1000, &rc2);
175 if (RT_FAILURE(rc))
176 {
177 RTPrintf("tstOnce: ERROR - RTThreadWait on thread #%u returned %Rrc\n", i, rc);
178 g_cErrors++;
179 }
180 else if (RT_FAILURE(rc2))
181 {
182 RTPrintf("tstOnce: ERROR - Thread #%u returned %Rrc\n", i, rc2);
183 g_cErrors++;
184 }
185 }
186
187 /*
188 * Summary.
189 */
190 if (!g_cErrors)
191 RTPrintf("tstOnce: SUCCESS\n");
192 else
193 RTPrintf("tstOnce: FAILURE - %d errors\n", g_cErrors);
194
195 return !!g_cErrors;
196}
197
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