tstRTCritSect.cpp revision bd28966c9d976ffe4518dd2fdf3894dc16b814a1
/* $Id$ */
/** @file
* IPRT Testcase - Critical Sections.
*/
/*
* Copyright (C) 2006-2009 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#ifdef TRY_WIN32_CRIT
# include <Windows.h>
#endif
#include <iprt/critsect.h>
#include <iprt/initterm.h>
#include <iprt/semaphore.h>
#ifndef TRY_WIN32_CRIT
#else /* TRY_WIN32_CRIT */
/* This is for comparing with the "real thing". */
#define RTCRITSECT CRITICAL_SECTION
#define PRTCRITSECT LPCRITICAL_SECTION
{
return VINF_SUCCESS;
}
{
return VINF_SUCCESS;
}
{
return VINF_SUCCESS;
}
{
return VINF_SUCCESS;
}
#endif /* TRY_WIN32_CRIT */
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* Arguments to ThreadTest1().
*/
typedef struct THREADTEST1ARGS
{
/** The critical section. */
/** The thread ordinal. */
/** Pointer to the release counter. */
uint32_t volatile *pu32Release;
/**
* Arguments to ThreadTest2().
*/
typedef struct THREADTEST2ARGS
{
/** The critical section. */
/** The thread ordinal. */
/** Pointer to the release counter. */
uint32_t volatile *pu32Release;
/** Pointer to the alone indicator. */
/** Pointer to the previous thread variable. */
/** Pointer to the sequential enters counter. */
/** Pointer to the reordered enters counter. */
uint32_t volatile *pcReordered;
/** Pointer to the variable counting running threads. */
uint32_t volatile *pcThreadRunning;
/** Number of times this thread was inside the section. */
/** The number of threads. */
/** Number of iterations (sum of all threads). */
/** Yield while inside the section. */
unsigned cCheckLoops;
/** Signal this when done. */
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/** The test handle. */
/**
* Thread which goes to sleep on the critsect and checks that it's released in the right order.
*/
{
/*
* Enter it.
*/
if (RT_FAILURE(rc))
{
return 1;
}
/*
* Check release order.
*/
/*
* Leave it.
*/
if (RT_FAILURE(rc))
{
return 1;
}
return 0;
}
{
/*
* Create a critical section.
*/
/*
* Enter, leave and enter again.
*/
/*
* Now spawn threads which will go to sleep entering the critsect.
*/
uint32_t u32Release = 0;
{
RTTEST_CHECK_RC_RET(g_hTest, RTThreadCreateF(&Thread, ThreadTest1, pArgs, 0, RTTHREADTYPE_DEFAULT, 0, "T%d", iThread), VINF_SUCCESS, 1);
/* wait for it to get into waiting. */
RTThreadSleep(10);
RTThreadSleep(20);
}
/*
* Now we'll release the threads and wait for all of them to quit.
*/
u32Release = 0;
while (u32Release < cThreads)
RTThreadSleep(10);
return 0;
}
/**
* Thread which goes to sleep on the critsect and checks
* that it's released along and in the right order. This is done a number of times.
*
*/
{
uint64_t u64TSStart = 0;
{
/*
* Enter it.
*/
if (RT_FAILURE(rc))
{
return 1;
}
if (!u64TSStart)
u64TSStart = RTTimeNanoTS();
#if 0 /* We just check for sequences. */
/*
* Check release order.
*/
else
#endif
/*
* Check distribution every now and again.
*/
#if 0
{
{
{
printf("tstCritSect: FAILURE - bad distribution thread %d u32Perfect=%d cTimes=%d cDiff=%d (runtime)\n",
}
}
}
#endif
/*
* Check alone and make sure we stay inside here a while
* so the other guys can get ready.
*/
{
{
//AssertReleaseMsgFailed(("Not alone!\n"));
return 1;
}
}
{
{
//AssertReleaseMsgFailed(("Not alone!\n"));
return 1;
}
}
/*
* Check for sequences.
*/
/*
* Leave it.
*/
if (RT_FAILURE(rc))
{
return 1;
}
}
Log2(("ThreadTest2: End - iThread=%d ThreadSelf=%p time=%lld\n", pArgs->iThread, ThreadSelf, u64TSEnd - u64TSStart));
return 0;
}
{
RTTestSubF(g_hTest, "Test #2 - cThreads=%u cIterations=%u cCheckLoops=%u", cThreads, cIterations, cCheckLoops);
/*
* Create a critical section.
*/
int rc;
/*
* Enter, leave and enter again.
*/
/*
* Now spawn threads which will go to sleep entering the critsect.
*/
uint32_t volatile u32Release = 0;
uint32_t volatile cReordered = 0;
uint32_t volatile cThreadRunning = 0;
unsigned iThread;
{
char szThread[17];
if (RT_FAILURE(rc))
{
return 1;
}
/* wait for it to get into waiting. */
RTThreadSleep(10);
RTThreadSleep(20);
}
/*
* Now we'll release the threads and wait for all of them to quit.
*/
u32Release = 0;
while (cThreadRunning > 0)
/*
* Clean up and report results.
*/
/* sequences */
/* distribution caused by sequences / reordering. */
unsigned cDiffTotal = 0;
{
}
"%d enter+leave in %dms cSeq=%d cReordered=%d cDiffTotal=%d\n",
return 0;
}
{
#ifndef TRY_WIN32_CRT
#else
#endif
if (rc)
return rc;
/* parse args. */
static const RTGETOPTDEF s_aOptions[] =
{
};
bool fTestDistribution = false;
int ch;
{
switch (ch)
{
case 'd':
fTestDistribution = true;
break;
case 'h':
return 1;
case VINF_GETOPT_NOT_OPTION:
return RTTestSummaryAndDestroy(hTest);
default:
if (ch > 0)
{
if (RT_C_IS_GRAPH(ch))
else
}
else if (ch == VERR_GETOPT_UNKNOWN_OPTION)
else if (ValueUnion.pDef)
else
return RTTestSummaryAndDestroy(hTest);
}
}
/*
* Perform the testing.
*/
if ( !Test1(1)
&& !Test1(3)
&& !Test1(10)
&& !Test1(63))
{
if ( fTestDistribution
{
/*nothing*/;
}
}
/*
* Summary.
*/
return RTTestSummaryAndDestroy(hTest);
}