397491e685e25e963cc77dfd0b0b169e962de846vboxsync/* $Id$ */
397491e685e25e963cc77dfd0b0b169e962de846vboxsync/** @file
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * IPRT Testcase - RTSemXRoads.
397491e685e25e963cc77dfd0b0b169e962de846vboxsync */
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync/*
c7814cf6e1240a519cbec0441e033d0e2470ed00vboxsync * Copyright (C) 2009-2012 Oracle Corporation
397491e685e25e963cc77dfd0b0b169e962de846vboxsync *
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * available from http://www.virtualbox.org. This file is free software;
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * you can redistribute it and/or modify it under the terms of the GNU
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * General Public License (GPL) as published by the Free Software
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
397491e685e25e963cc77dfd0b0b169e962de846vboxsync *
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * The contents of this file may alternatively be used under the terms
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * of the Common Development and Distribution License Version 1.0
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * VirtualBox OSE distribution, in which case the provisions of the
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * CDDL are applicable instead of those of the GPL.
397491e685e25e963cc77dfd0b0b169e962de846vboxsync *
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * You may elect to license modified versions of this file under the
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * terms and conditions of either the GPL or the CDDL or both.
397491e685e25e963cc77dfd0b0b169e962de846vboxsync */
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync/*******************************************************************************
397491e685e25e963cc77dfd0b0b169e962de846vboxsync* Header Files *
397491e685e25e963cc77dfd0b0b169e962de846vboxsync*******************************************************************************/
397491e685e25e963cc77dfd0b0b169e962de846vboxsync#include <iprt/semaphore.h>
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync#include <iprt/asm.h>
397491e685e25e963cc77dfd0b0b169e962de846vboxsync#include <iprt/err.h>
397491e685e25e963cc77dfd0b0b169e962de846vboxsync#include <iprt/initterm.h>
397491e685e25e963cc77dfd0b0b169e962de846vboxsync#include <iprt/test.h>
397491e685e25e963cc77dfd0b0b169e962de846vboxsync#include <iprt/thread.h>
397491e685e25e963cc77dfd0b0b169e962de846vboxsync#include <iprt/time.h>
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync/*******************************************************************************
397491e685e25e963cc77dfd0b0b169e962de846vboxsync* Global Variables *
397491e685e25e963cc77dfd0b0b169e962de846vboxsync*******************************************************************************/
397491e685e25e963cc77dfd0b0b169e962de846vboxsyncstatic RTTEST g_hTest;
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsyncstatic uint32_t volatile g_cNSCrossings;
397491e685e25e963cc77dfd0b0b169e962de846vboxsyncstatic uint32_t volatile g_cEWCrossings;
397491e685e25e963cc77dfd0b0b169e962de846vboxsyncstatic uint64_t g_u64StartMilliTS;
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsyncstatic uint32_t g_cSecs;
397491e685e25e963cc77dfd0b0b169e962de846vboxsyncstatic RTSEMXROADS g_hXRoads;
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsyncstatic int tstTrafficThreadCommon(uintptr_t iThread, bool fNS)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync{
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync for (uint32_t iLoop = 0; RTTimeMilliTS() - g_u64StartMilliTS < g_cSecs*1000; iLoop++)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync {
397491e685e25e963cc77dfd0b0b169e962de846vboxsync /* fudge */
7e33622becf3d7cf9a2401ac0c53d315877f6e34vboxsync if ((iLoop % 223) == 223)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTThreadYield();
7e33622becf3d7cf9a2401ac0c53d315877f6e34vboxsync else if ((iLoop % 16127) == 16127)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTThreadSleep(1);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync if (fNS)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync {
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC(g_hTest,RTSemXRoadsNSEnter(g_hXRoads), VINF_SUCCESS);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync ASMAtomicIncU32(&g_cNSCrossings);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC(g_hTest,RTSemXRoadsNSLeave(g_hXRoads), VINF_SUCCESS);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync }
397491e685e25e963cc77dfd0b0b169e962de846vboxsync else
397491e685e25e963cc77dfd0b0b169e962de846vboxsync {
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC(g_hTest,RTSemXRoadsEWEnter(g_hXRoads), VINF_SUCCESS);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync ASMAtomicIncU32(&g_cEWCrossings);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC(g_hTest,RTSemXRoadsEWLeave(g_hXRoads), VINF_SUCCESS);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync }
397491e685e25e963cc77dfd0b0b169e962de846vboxsync }
397491e685e25e963cc77dfd0b0b169e962de846vboxsync return VINF_SUCCESS;
397491e685e25e963cc77dfd0b0b169e962de846vboxsync}
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
b7a1977fd3a47a04749e45a18593ecb67ca0972bvboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsyncstatic DECLCALLBACK(int) tstTrafficNSThread(RTTHREAD hSelf, void *pvUser)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync{
397491e685e25e963cc77dfd0b0b169e962de846vboxsync uintptr_t iThread = (uintptr_t)pvUser;
397491e685e25e963cc77dfd0b0b169e962de846vboxsync return tstTrafficThreadCommon(iThread, true);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync}
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsyncstatic DECLCALLBACK(int) tstTrafficEWThread(RTTHREAD hSelf, void *pvUser)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync{
397491e685e25e963cc77dfd0b0b169e962de846vboxsync uintptr_t iThread = (uintptr_t)pvUser;
397491e685e25e963cc77dfd0b0b169e962de846vboxsync return tstTrafficThreadCommon(iThread, false);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync}
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsyncstatic void tstTraffic(unsigned cThreads, unsigned cSecs)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync{
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync RTTestSubF(g_hTest, "Traffic - %u threads per direction, %u sec", cThreads, cSecs);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync /*
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * Create X worker threads which drives in the south/north direction and Y
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * worker threads which drives in the west/east direction. Let them drive
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * in a loop for 15 seconds with slight delays between some of the runs and
397491e685e25e963cc77dfd0b0b169e962de846vboxsync * then check the numbers.
397491e685e25e963cc77dfd0b0b169e962de846vboxsync */
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync /* init */
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync RTTHREAD ahThreadsX[8];
397491e685e25e963cc77dfd0b0b169e962de846vboxsync for (unsigned i = 0; i < RT_ELEMENTS(ahThreadsX); i++)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync ahThreadsX[i] = NIL_RTTHREAD;
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync AssertRelease(RT_ELEMENTS(ahThreadsX) >= cThreads);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync RTTHREAD ahThreadsY[8];
397491e685e25e963cc77dfd0b0b169e962de846vboxsync for (unsigned i = 0; i < RT_ELEMENTS(ahThreadsY); i++)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync ahThreadsY[i] = NIL_RTTHREAD;
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync AssertRelease(RT_ELEMENTS(ahThreadsY) >= cThreads);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync g_cNSCrossings = 0;
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync g_cEWCrossings = 0;
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync g_cSecs = cSecs;
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync g_u64StartMilliTS = RTTimeMilliTS();
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync /* create */
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_RETV(g_hTest, RTSemXRoadsCreate(&g_hXRoads), VINF_SUCCESS);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync int rc = VINF_SUCCESS;
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync for (unsigned i = 0; i < cThreads && RT_SUCCESS(rc); i++)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync {
5708ec0dbaec388c36b5c6c2cf590f12e48748e6vboxsync rc = RTThreadCreateF(&ahThreadsX[i], tstTrafficNSThread, (void *)(uintptr_t)i, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "NS-%u", i);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_OK(g_hTest, rc);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync }
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync for (unsigned i = 0; i < cThreads && RT_SUCCESS(rc); i++)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync {
5708ec0dbaec388c36b5c6c2cf590f12e48748e6vboxsync rc = RTThreadCreateF(&ahThreadsX[i], tstTrafficEWThread, (void *)(uintptr_t)i, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "NS-%u", i);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_OK(g_hTest, rc);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync }
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync /* wait */
397491e685e25e963cc77dfd0b0b169e962de846vboxsync for (unsigned i = 0; i < RT_ELEMENTS(ahThreadsX); i++)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync if (ahThreadsX[i] != NIL_RTTHREAD)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync {
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync int rc2 = RTThreadWaitNoResume(ahThreadsX[i], (60 + cSecs) * 1000, NULL);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_OK(g_hTest, rc2);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync }
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync for (unsigned i = 0; i < RT_ELEMENTS(ahThreadsY); i++)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync if (ahThreadsY[i] != NIL_RTTHREAD)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync {
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync int rc2 = RTThreadWaitNoResume(ahThreadsY[i], (60 + cSecs) * 1000, NULL);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_OK(g_hTest, rc2);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync }
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
7e33622becf3d7cf9a2401ac0c53d315877f6e34vboxsync RTTEST_CHECK_MSG_RETV(g_hTest, g_cEWCrossings > 10 && g_cNSCrossings,
7e33622becf3d7cf9a2401ac0c53d315877f6e34vboxsync (g_hTest, "cEWCrossings=%u g_cNSCrossings=%u\n", g_cEWCrossings, g_cNSCrossings));
7e33622becf3d7cf9a2401ac0c53d315877f6e34vboxsync RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "cNSCrossings=%u\n", g_cNSCrossings);
7e33622becf3d7cf9a2401ac0c53d315877f6e34vboxsync RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "cEWCrossings=%u\n", g_cEWCrossings);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync}
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsyncstatic bool tstBasics(void)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync{
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTestSub(g_hTest, "Basics");
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTSEMXROADS hXRoads;
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_RET(g_hTest, RTSemXRoadsCreate(&hXRoads), VINF_SUCCESS, false);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_RET(g_hTest, RTSemXRoadsNSEnter(hXRoads), VINF_SUCCESS, false);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_RET(g_hTest, RTSemXRoadsNSLeave(hXRoads), VINF_SUCCESS, false);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_RET(g_hTest, RTSemXRoadsEWEnter(hXRoads), VINF_SUCCESS, false);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_RET(g_hTest, RTSemXRoadsEWLeave(hXRoads), VINF_SUCCESS, false);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_RET(g_hTest, RTSemXRoadsEWEnter(hXRoads), VINF_SUCCESS, false);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_RET(g_hTest, RTSemXRoadsEWLeave(hXRoads), VINF_SUCCESS, false);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_RET(g_hTest, RTSemXRoadsNSEnter(hXRoads), VINF_SUCCESS, false);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_RET(g_hTest, RTSemXRoadsNSLeave(hXRoads), VINF_SUCCESS, false);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_RET(g_hTest, RTSemXRoadsNSEnter(hXRoads), VINF_SUCCESS, false);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_RET(g_hTest, RTSemXRoadsNSLeave(hXRoads), VINF_SUCCESS, false);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_RET(g_hTest, RTSemXRoadsDestroy(hXRoads), VINF_SUCCESS, false);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTEST_CHECK_RC_RET(g_hTest, RTSemXRoadsDestroy(NIL_RTSEMXROADS), VINF_SUCCESS, false);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync return true;
397491e685e25e963cc77dfd0b0b169e962de846vboxsync}
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsyncint main()
397491e685e25e963cc77dfd0b0b169e962de846vboxsync{
347837ed95d5742b39a60987e0dcfe038729dce7vboxsync int rc = RTTestInitAndCreate("tstRTSemXRoads", &g_hTest);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync if (rc)
397491e685e25e963cc77dfd0b0b169e962de846vboxsync return rc;
397491e685e25e963cc77dfd0b0b169e962de846vboxsync RTTestBanner(g_hTest);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync if (tstBasics())
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync {
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync tstTraffic(1, 5);
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync tstTraffic(2, 5);
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync tstTraffic(4, 15);
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync tstTraffic(8, 10);
e39cb73e9d0ef96b6ec4b35061de1b9ef733dd06vboxsync }
397491e685e25e963cc77dfd0b0b169e962de846vboxsync
397491e685e25e963cc77dfd0b0b169e962de846vboxsync return RTTestSummaryAndDestroy(g_hTest);
397491e685e25e963cc77dfd0b0b169e962de846vboxsync}
397491e685e25e963cc77dfd0b0b169e962de846vboxsync