tstTSC.cpp revision 43a30045886b1e6bec2b2726db20c0bd7edcce0d
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * innotek Portable Runtime Testcase - SMP TSC testcase.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Copyright (C) 2006-2007 innotek GmbH
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * available from http://www.virtualbox.org. This file is free software;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * you can redistribute it and/or modify it under the terms of the GNU
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * General Public License as published by the Free Software Foundation,
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Header Files *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Structures and Typedefs *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsynctypedef struct TSCDATA
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /** The TSC. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /** The APIC ID. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /** Did it succeed? */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync bool volatile fRead;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /** Did it fail? */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync bool volatile fFailed;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /** The thread handle. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Global Variables *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** The number of CPUs waiting on their user event semaphore. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** The number of CPUs ready (in spin) to do the TSC read. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** The variable the CPUs are spinning on.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * 1: Go ahead.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * 2: You're too late, back to square one. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** The number of CPUs that managed to read the TSC. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** The number of CPUs that failed to read the TSC. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/** Indicator forcing the threads to quit. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic volatile bool g_fDone;
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync/*******************************************************************************
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync* Internal Functions *
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync*******************************************************************************/
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic DECLCALLBACK(int) ThreadFunction(RTTHREAD Thread, void *pvUser);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Thread function for catching the other cpus.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @returns VINF_SUCCESS (we don't care).
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param Thread The thread handle.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * @param pvUser PTSCDATA.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsyncstatic DECLCALLBACK(int) ThreadFunction(RTTHREAD Thread, void *pvUser)
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync /* do the reading. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync && TSC3 - TSC1 < 2250 /* WARNING: This is just a guess, increase if it doesn't work for you. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* succeeded. */
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync /* failed */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * This is only relevant to on SMP systems.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync const unsigned cCpus = RTSystemProcessorGetCount();
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTPrintf("tstTSC: SKIPPED - Only relevant on SMP systems\n");
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Create the threads.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTPrintf("tstTSC: FAILED - too many CPUs (%u)\n", cCpus);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* ourselves. */
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync /* the others */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = RTThreadCreate(&s_aData[i].Thread, ThreadFunction, &s_aData[i], 0, RTTHREADTYPE_TIMER, RTTHREADFLAGS_WAITABLE, "OTHERCPU");
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTPrintf("tstTSC: FAILURE - RTThreatCreate failed when creating thread #%u, rc=%Rrc!\n", i, rc);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync while (i-- > 1)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Retry untill we get lucky (or give up).
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTPrintf("tstTSC: FAILURE - %d attempts, giving.\n", cTries);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Wait for the other threads to get ready (brute force active wait, I'm lazy).
b84a3f2aac9529d5c5840512b12d81bc62d0e665vboxsync RTPrintf("tstTSC: FAILURE - threads failed to get waiting (%d != %d (i=%d))\n", g_cWaiting + 1, cCpus, i);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Send them spinning.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTPrintf("tstTSC: WARNING - RTThreadUserSignal(%#u) -> rc=%Rrc!\n", i, rc);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* wait for them to get ready. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTPrintf("tstTSC: FAILURE - threads failed to get ready (%d != %d, i=%d)\n", g_cWaiting + 1, cCpus, i);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Flip the "go" switch and do our readings.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * We give the other threads the slack it takes to two extra TSC and APIC ID reads.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* Compose our own result. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync && TSC5 - TSC1 < 2750 /* WARNING: This is just a guess, increase if it doesn't work for you. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* succeeded. */
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync /* failed */
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync * Wait a little while to let the other ones to finish.
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync RTPrintf("tstTSC: FAILURE - threads failed to complete reading (%d + %d != %d)\n", g_cRead, g_cFailed, cCpus);
968c867cc19737e4e1fd97c396fcf75a3d52dd27vboxsync * If everone succeeded, print the results.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync "-----------------------\n");
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync for (i = 0; i < cCpus; i++)
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTPrintf("%2d %02x %RX64\n", i, s_aData[i].u8ApicId, s_aData[i].TSC);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTPrintf("(Needed %u attempt%s.)\n", cTries + 1, cTries ? "s" : "");
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync * Destroy the threads.
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTPrintf("tstTSC: WARNING - RTThreadUserSignal(%#u) -> rc=%Rrc! (2)\n", i, rc);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync int rc = RTThreadWait(s_aData[i].Thread, 5000, NULL);
0b74a2f80aba476dc8be8bc1c63891fc53945986vboxsync RTPrintf("tstTSC: WARNING - RTThreadWait(%#u) -> rc=%Rrc!\n", i, rc);