tstCritSect.cpp revision cf2f82bcba4fa493f0d58f762dde2a04817d869b
/* $Id$ */
/** @file
* innotek Portable Runtime Testcase - Critical Sections.
*/
/*
* Copyright (C) 2006-2007 innotek GmbH
*
* 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 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.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#ifdef TRY_WIN32_CRIT
# include <Windows.h>
#endif
#include <iprt/critsect.h>
#include <iprt/semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef TRY_WIN32_CRIT
#else
/* 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
/*******************************************************************************
* 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 *
*******************************************************************************/
/** Error counter. */
/**
* 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.
*/
{
printf("tstCritSect: FAILURE - thread %d: released as number %d\n", pArgs->iThread, *pArgs->pu32Release);
}
/*
* Leave it.
*/
if (RT_FAILURE(rc))
{
return 1;
}
return 0;
}
{
/*
* Create a critical section.
*/
if (RT_FAILURE(rc))
{
return 1;
}
/*
* Enter, leave and enter again.
*/
if (RT_FAILURE(rc))
{
return 1;
}
if (RT_FAILURE(rc))
{
return 1;
}
if (RT_FAILURE(rc))
{
return 1;
}
/*
* Now spawn threads which will go to sleep entering the critsect.
*/
uint32_t u32Release = 0;
{
char szThread[17];
if (RT_FAILURE(rc))
{
exit(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;
if (RT_FAILURE(rc))
{
return 1;
}
while (u32Release < cThreads)
RTThreadSleep(10);
if (RT_FAILURE(rc))
{
}
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))
{
printf("tstCritSect: FATAL FAILURE - Test 2 - thread %d, iteration %d: RTCritSectEnter -> %d\n", pArgs->iThread, i, rc);
return 1;
}
if (!u64TSStart)
u64TSStart = RTTimeNanoTS();
#if 0 /* We just check for sequences. */
/*
* Check release order.
*/
{
printf("tstCritSect: FAILURE - Test 2 - thread %d, iteration %d: released as number %d (%d)\n",
}
else
printf("tstCritSect: SUCCESS - Test 2 - thread %d, iteration %d: released as number %d (%d)\n",
#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.
*/
{
{
printf("tstCritSect: FATAL FAILURE - Test 2 - thread %d, iteration %d: not alone!!!\n", pArgs->iThread, i);
AssertReleaseMsgFailed(("Not alone!\n"));
return 1;
}
}
{
{
printf("tstCritSect: FATAL FAILURE - Test 2 - thread %d, iteration %d: not alone!!!\n", pArgs->iThread, i);
AssertReleaseMsgFailed(("Not alone!\n"));
return 1;
}
}
/*
* Check for sequences.
*/
/*
* Leave it.
*/
if (RT_FAILURE(rc))
{
printf("tstCritSect: FATAL FAILURE - Test 2 - thread %d, iteration %d: RTCritSectEnter -> %d\n", pArgs->iThread, i, rc);
return 1;
}
}
Log2(("ThreadTest2: End - iThread=%d ThreadSelf=%p time=%lld\n", pArgs->iThread, ThreadSelf, u64TSEnd - u64TSStart));
return 0;
}
{
printf("tstCritSect: Test2 - cThread=%d cIterations=%d cCheckLoops=%d...\n", cThreads, cIterations, cCheckLoops);
/*
* Create a critical section.
*/
if (RT_FAILURE(rc))
{
return 1;
}
/*
* Enter, leave and enter again.
*/
if (RT_FAILURE(rc))
{
return 1;
}
if (RT_FAILURE(rc))
{
return 1;
}
if (RT_FAILURE(rc))
{
return 1;
}
/*
* 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))
{
exit(1);
}
/* wait for it to get into waiting. */
RTThreadSleep(10);
RTThreadSleep(20);
}
printf("tstCritSect: Test2 - threads created...\n");
/*
* Now we'll release the threads and wait for all of them to quit.
*/
u32Release = 0;
if (RT_FAILURE(rc))
{
return 1;
}
while (cThreadRunning > 0)
/*
* Clean up and report results.
*/
if (RT_FAILURE(rc))
{
}
/* sequences */
{
}
/* distribution caused by sequences / reordering. */
unsigned cDiffTotal = 0;
{
{
printf("tstCritSect: FAILURE - bad distribution thread %d u32Perfect=%d cTimes=%d cDiff=%d\n",
}
}
printf("tstCritSect: Test2 - DONE. %d enter+leave in %dms cSeq=%d cReordered=%d cDiffTotal=%d\n",
return 0;
}
{
printf("tstCritSect: TESTING\n");
if (RT_FAILURE(rc))
{
return 1;
}
printf("tstCritSect: Test1...\n");
if (Test1(1))
return 1;
if (Test1(3))
return 1;
if (Test1(10))
return 1;
if (Test1(63))
return 1;
return 1;
return 1;
return 1;
return 1;
return 1;
return 1;
return 1;
/*
* Summary.
*/
if (!g_cErrors)
printf("tstCritSect: SUCCESS\n");
else
return !!g_cErrors;
}