cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/* $Id$ */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** @file
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Load Generator.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Copyright (C) 2007-2014 Oracle Corporation
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * available from http://www.virtualbox.org. This file is free software;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * General Public License (GPL) as published by the Free Software
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * The contents of this file may alternatively be used under the terms
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * of the Common Development and Distribution License Version 1.0
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * VirtualBox OSE distribution, in which case the provisions of the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * CDDL are applicable instead of those of the GPL.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * You may elect to license modified versions of this file under the
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * terms and conditions of either the GPL or the CDDL or both.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*******************************************************************************
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync* Header Files *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync*******************************************************************************/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/thread.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/time.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/initterm.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/string.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/stream.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/param.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/path.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/process.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/mp.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/asm.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/getopt.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <VBox/sup.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*******************************************************************************
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync* Global Variables *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync*******************************************************************************/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** Whether the threads should quit or not. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic bool volatile g_fQuit = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic const char *g_pszProgramName = NULL;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*******************************************************************************
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync* Internal Functions *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync*******************************************************************************/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int Error(const char *pszFormat, ...);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic void LoadGenSpin(uint64_t cNanoSeconds)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync const uint64_t u64StartTS = RTTimeNanoTS();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync do
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (uint32_t volatile i = 0; i < 10240 && !g_fQuit; i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync i++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync } while (RTTimeNanoTS() - u64StartTS < cNanoSeconds && !g_fQuit);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic DECLCALLBACK(int) LoadGenSpinThreadFunction(RTTHREAD hThreadSelf, void *pvUser)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NOREF(hThreadSelf);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync LoadGenSpin(*(uint64_t *)pvUser);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return VINF_SUCCESS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int LoadGenIpiInit(void)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Try make sure the support library is initialized...
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync SUPR3Init(NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Load the module.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char szPath[RTPATH_MAX];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = RTPathAppPrivateArchTop(szPath, sizeof(szPath) - sizeof("/loadgenerator.r0"));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync strcat(szPath, "/loadgeneratorR0.r0");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync void *pvImageBase;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = SUPR3LoadServiceModule(szPath, "loadgeneratorR0", "LoadGenR0ServiceReqHandler", &pvImageBase);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_SUCCESS(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* done */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Error("SUPR3LoadServiceModule(%s): %Rrc\n", szPath, rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Error("RTPathAppPrivateArch: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic void LoadGenIpi(uint64_t cNanoSeconds)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync const uint64_t u64StartTS = RTTimeNanoTS();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync do
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc = SUPR3CallR0Service("loadgeneratorR0", sizeof("loadgeneratorR0") - 1,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync 0 /* uOperation */, 1 /* cIpis */, NULL /* pReqHdr */);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync Error("SUPR3CallR0Service: %Rrc\n", rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync } while (RTTimeNanoTS() - u64StartTS < cNanoSeconds && !g_fQuit);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic DECLCALLBACK(int) LoadGenIpiThreadFunction(RTTHREAD hThreadSelf, void *pvUser)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync LoadGenIpi(*(uint64_t *)pvUser);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NOREF(hThreadSelf);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return VINF_SUCCESS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int Error(const char *pszFormat, ...)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync va_list va;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrmPrintf(g_pStdErr, "%s: error: ", g_pszProgramName);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync va_start(va, pszFormat);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrmPrintfV(g_pStdErr, pszFormat, va);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync va_end(va);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic int SyntaxError(const char *pszFormat, ...)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync va_list va;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrmPrintf(g_pStdErr, "%s: syntax error: ", g_pszProgramName);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync va_start(va, pszFormat);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrmPrintfV(g_pStdErr, pszFormat, va);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync va_end(va);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncint main(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync static const struct LOADGENTYPE
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync const char *pszName;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int (*pfnInit)(void);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync PFNRTTHREAD pfnThread;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync } s_aLoadTypes[] =
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "spin", NULL, LoadGenSpinThreadFunction },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "ipi", LoadGenIpiInit, LoadGenIpiThreadFunction },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync };
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync unsigned iLoadType = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync static RTTHREAD s_aThreads[256];
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int rc;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t cThreads = 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync bool fScaleByCpus = false;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTHREADTYPE enmThreadType = RTTHREADTYPE_DEFAULT;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPROCPRIORITY enmProcPriority = RTPROCPRIORITY_DEFAULT;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t cNanoSeconds = UINT64_MAX;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTR3InitExe(argc, &argv, 0);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Set program name.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync g_pszProgramName = RTPathFilename(argv[0]);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Parse arguments.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync static const RTGETOPTDEF s_aOptions[] =
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--number-of-threads", 'n', RTGETOPT_REQ_UINT32 },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--timeout", 't', RTGETOPT_REQ_STRING },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--thread-type", 'p', RTGETOPT_REQ_STRING },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--scale-by-cpus", 'c', RTGETOPT_REQ_NOTHING },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync { "--load", 'l', RTGETOPT_REQ_STRING },
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync };
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync int ch;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTGETOPTUNION ValueUnion;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTGETOPTSTATE GetState;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0 /* fFlags */);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while ((ch = RTGetOpt(&GetState, &ValueUnion)))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync switch (ch)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'n':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cThreads = ValueUnion.u64;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (cThreads == 0 || cThreads > RT_ELEMENTS(s_aThreads))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return SyntaxError("Requested number of threads, %RU32, is out of range (1..%d).\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cThreads, RT_ELEMENTS(s_aThreads) - 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 't':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char *psz;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTStrToUInt64Ex(ValueUnion.psz, &psz, 0, &cNanoSeconds);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return SyntaxError("Failed reading the alleged number '%s' (option '%s', rc=%Rrc).\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ValueUnion.psz, rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (*psz == ' ' || *psz == '\t')
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync psz++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (*psz)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t u64Factor = 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!strcmp(psz, "ns"))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u64Factor = 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if (!strcmp(psz, "ms"))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u64Factor = 1000;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if (!strcmp(psz, "s"))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u64Factor = 1000000000;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if (!strcmp(psz, "m"))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u64Factor = UINT64_C(60000000000);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if (!strcmp(psz, "h"))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync u64Factor = UINT64_C(3600000000000);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return SyntaxError("Unknown time suffix '%s'\n", psz);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t u64 = cNanoSeconds * u64Factor;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (u64 < cNanoSeconds || (u64 < u64Factor && u64))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return SyntaxError("Time representation overflowed! (%RU64 * %RU64)\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync psz, cNanoSeconds, u64Factor);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cNanoSeconds = u64;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'p':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync enmProcPriority = RTPROCPRIORITY_NORMAL;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t u32 = RTTHREADTYPE_INVALID;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync char *psz;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTStrToUInt32Ex(ValueUnion.psz, &psz, 0, &u32);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc) || *psz)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!strcmp(ValueUnion.psz, "default"))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync enmProcPriority = RTPROCPRIORITY_DEFAULT;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync enmThreadType = RTTHREADTYPE_DEFAULT;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if (!strcmp(ValueUnion.psz, "idle"))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync enmProcPriority = RTPROCPRIORITY_LOW;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync enmThreadType = RTTHREADTYPE_INFREQUENT_POLLER;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else if (!strcmp(ValueUnion.psz, "high"))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync enmProcPriority = RTPROCPRIORITY_HIGH;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync enmThreadType = RTTHREADTYPE_IO;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return SyntaxError("can't grok thread type '%s'\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ValueUnion.psz);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync enmThreadType = (RTTHREADTYPE)u32;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (enmThreadType <= RTTHREADTYPE_INVALID || enmThreadType >= RTTHREADTYPE_END)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return SyntaxError("thread type '%d' is out of range (%d..%d)\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ValueUnion.psz, RTTHREADTYPE_INVALID + 1, RTTHREADTYPE_END - 1);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'c':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync fScaleByCpus = true;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'l':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (unsigned i = 0; i < RT_ELEMENTS(s_aLoadTypes); i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (!strcmp(s_aLoadTypes[i].pszName, ValueUnion.psz))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ValueUnion.psz = NULL;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync iLoadType = i;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (ValueUnion.psz)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return SyntaxError("Unknown load type '%s'.\n", ValueUnion.psz);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'h':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrmPrintf(g_pStdOut,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "Usage: %s [-p|--thread-type <type>] [-t|--timeout <sec|xxx[h|m|s|ms|ns]>] \\\n"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync " %*s [-n|--number-of-threads <threads>] [-l|--load <loadtype>]\n"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "\n"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync "Load types: spin, ipi.\n"
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync g_pszProgramName, strlen(g_pszProgramName), "");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case 'V':
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTPrintf("$Revision$\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync case VINF_GETOPT_NOT_OPTION:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return SyntaxError("Unknown argument #%d: '%s'\n", GetState.iNext-1, ValueUnion.psz);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync default:
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTGetOptPrintError(ch, &ValueUnion);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Scale thread count by host cpu count.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (fScaleByCpus)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync const unsigned cCpus = RTMpGetOnlineCount();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (cCpus * cThreads > RT_ELEMENTS(s_aThreads))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return SyntaxError("Requested number of threads, %RU32, is out of range (1..%d) when scaled by %d.\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cThreads, RT_ELEMENTS(s_aThreads) - 1, cCpus);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cThreads *= cCpus;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Modify process and thread priority? (ignore failure)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (enmProcPriority != RTPROCPRIORITY_DEFAULT)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTProcSetPriority(enmProcPriority);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (enmThreadType != RTTHREADTYPE_DEFAULT)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTThreadSetType(RTThreadSelf(), enmThreadType);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Load type specific init.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (s_aLoadTypes[iLoadType].pfnInit)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = s_aLoadTypes[iLoadType].pfnInit();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Start threads.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (unsigned i = 1; i < cThreads; i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync s_aThreads[i] = NIL_RTTHREAD;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync rc = RTThreadCreate(&s_aThreads[i], s_aLoadTypes[iLoadType].pfnThread,
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync &cNanoSeconds, 128*1024, enmThreadType, RTTHREADFLAGS_WAITABLE, "spinner");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (RT_FAILURE(rc))
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMAtomicXchgBool(&g_fQuit, true);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTStrmPrintf(g_pStdErr, "%s: failed to create thread #%d, rc=%Rrc\n", g_pszProgramName, i, rc);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (i-- > 1)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTThreadWait(s_aThreads[i], 1500, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /* our selves */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync s_aLoadTypes[iLoadType].pfnThread(RTThreadSelf(), &cNanoSeconds);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Wait for threads.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync ASMAtomicXchgBool(&g_fQuit, true);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (unsigned i = 1; i < cThreads; i++)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTThreadWait(s_aThreads[i], 1500, NULL);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync