diff options
Diffstat (limited to 'src/VBox/ValidationKit/utils/misc')
-rw-r--r-- | src/VBox/ValidationKit/utils/misc/Makefile.kmk | 52 | ||||
-rw-r--r-- | src/VBox/ValidationKit/utils/misc/loadgenerator.cpp | 381 | ||||
-rw-r--r-- | src/VBox/ValidationKit/utils/misc/loadgeneratorR0.cpp | 91 | ||||
-rw-r--r-- | src/VBox/ValidationKit/utils/misc/vts_rm.cpp | 44 | ||||
-rw-r--r-- | src/VBox/ValidationKit/utils/misc/vts_tar.cpp | 44 |
5 files changed, 612 insertions, 0 deletions
diff --git a/src/VBox/ValidationKit/utils/misc/Makefile.kmk b/src/VBox/ValidationKit/utils/misc/Makefile.kmk new file mode 100644 index 00000000..5d90b09c --- /dev/null +++ b/src/VBox/ValidationKit/utils/misc/Makefile.kmk @@ -0,0 +1,52 @@ +# $Id: Makefile.kmk $ +## @file +# VirtualBox Validation Kit - Miscellaneous Utilites. +# + +# +# Copyright (C) 2010-2019 Oracle Corporation +# +# This file is part of VirtualBox Open Source Edition (OSE), as +# available from http://www.virtualbox.org. This file is free software; +# you can redistribute it and/or modify it under the terms of the GNU +# 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. +# + +SUB_DEPTH = ../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +PROGRAMS += LoadGenerator +LoadGenerator_TEMPLATE = VBoxValidationKitR3Host +LoadGenerator_SOURCES = loadgenerator.cpp + +SYSMODS += loadgeneratorR0 +loadgeneratorR0_TEMPLATE = VBoxValidationKitR0 +loadgeneratorR0_SOURCES = loadgeneratorR0.cpp + +PROGRAMS += vts_rm +vts_rm_TEMPLATE = VBoxValidationKitR3 +vts_rm_SOURCES = vts_rm.cpp + +PROGRAMS += vts_tar +vts_tar_TEMPLATE = VBoxValidationKitR3 +vts_tar_SDKS = VBOX_ZLIB_STATIC +vts_tar_SOURCES = vts_tar.cpp + +PROGRAMS += vts_shutdown +vts_shutdown_TEMPLATE = VBoxValidationKitR3 +vts_shutdown_SOURCES = ../../../Runtime/tools/RTShutdown.cpp + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/ValidationKit/utils/misc/loadgenerator.cpp b/src/VBox/ValidationKit/utils/misc/loadgenerator.cpp new file mode 100644 index 00000000..d6ce5cb1 --- /dev/null +++ b/src/VBox/ValidationKit/utils/misc/loadgenerator.cpp @@ -0,0 +1,381 @@ +/* $Id: loadgenerator.cpp $ */ +/** @file + * Load Generator. + */ + +/* + * Copyright (C) 2007-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * 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. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <iprt/errcore.h> +#include <iprt/thread.h> +#include <iprt/time.h> +#include <iprt/initterm.h> +#include <iprt/string.h> +#include <iprt/stream.h> +#include <iprt/param.h> +#include <iprt/path.h> +#include <iprt/process.h> +#include <iprt/mp.h> +#include <iprt/asm.h> +#include <iprt/getopt.h> +#include <VBox/sup.h> + + +/********************************************************************************************************************************* +* Global Variables * +*********************************************************************************************************************************/ +/** Whether the threads should quit or not. */ +static bool volatile g_fQuit = false; +static const char *g_pszProgramName = NULL; + + +/********************************************************************************************************************************* +* Internal Functions * +*********************************************************************************************************************************/ +static int Error(const char *pszFormat, ...); + + +static void LoadGenSpin(uint64_t cNanoSeconds) +{ + const uint64_t u64StartTS = RTTimeNanoTS(); + do + { + for (uint32_t volatile i = 0; i < 10240 && !g_fQuit; i++) + i++; + } while (RTTimeNanoTS() - u64StartTS < cNanoSeconds && !g_fQuit); +} + + +static DECLCALLBACK(int) LoadGenSpinThreadFunction(RTTHREAD hThreadSelf, void *pvUser) +{ + NOREF(hThreadSelf); + LoadGenSpin(*(uint64_t *)pvUser); + return VINF_SUCCESS; +} + + +static int LoadGenIpiInit(void) +{ + /* + * Try make sure the support library is initialized... + */ + SUPR3Init(NULL); + + /* + * Load the module. + */ + char szPath[RTPATH_MAX]; + int rc = RTPathAppPrivateArchTop(szPath, sizeof(szPath) - sizeof("/loadgenerator.r0")); + if (RT_SUCCESS(rc)) + { + strcat(szPath, "/loadgeneratorR0.r0"); + void *pvImageBase; + rc = SUPR3LoadServiceModule(szPath, "loadgeneratorR0", "LoadGenR0ServiceReqHandler", &pvImageBase); + if (RT_SUCCESS(rc)) + { + /* done */ + } + else + Error("SUPR3LoadServiceModule(%s): %Rrc\n", szPath, rc); + } + else + Error("RTPathAppPrivateArch: %Rrc\n", rc); + return rc; +} + + +static void LoadGenIpi(uint64_t cNanoSeconds) +{ + const uint64_t u64StartTS = RTTimeNanoTS(); + do + { + int rc = SUPR3CallR0Service("loadgeneratorR0", sizeof("loadgeneratorR0") - 1, + 0 /* uOperation */, 1 /* cIpis */, NULL /* pReqHdr */); + if (RT_FAILURE(rc)) + { + Error("SUPR3CallR0Service: %Rrc\n", rc); + break; + } + } while (RTTimeNanoTS() - u64StartTS < cNanoSeconds && !g_fQuit); +} + + +static DECLCALLBACK(int) LoadGenIpiThreadFunction(RTTHREAD hThreadSelf, void *pvUser) +{ + LoadGenIpi(*(uint64_t *)pvUser); + NOREF(hThreadSelf); + return VINF_SUCCESS; +} + + +static int Error(const char *pszFormat, ...) +{ + va_list va; + RTStrmPrintf(g_pStdErr, "%s: error: ", g_pszProgramName); + va_start(va, pszFormat); + RTStrmPrintfV(g_pStdErr, pszFormat, va); + va_end(va); + return 1; +} + + +static int SyntaxError(const char *pszFormat, ...) +{ + va_list va; + RTStrmPrintf(g_pStdErr, "%s: syntax error: ", g_pszProgramName); + va_start(va, pszFormat); + RTStrmPrintfV(g_pStdErr, pszFormat, va); + va_end(va); + return 1; +} + + +int main(int argc, char **argv) +{ + static const struct LOADGENTYPE + { + const char *pszName; + int (*pfnInit)(void); + PFNRTTHREAD pfnThread; + } s_aLoadTypes[] = + { + { "spin", NULL, LoadGenSpinThreadFunction }, + { "ipi", LoadGenIpiInit, LoadGenIpiThreadFunction }, + }; + unsigned iLoadType = 0; + static RTTHREAD s_aThreads[256]; + int rc; + uint32_t cThreads = 1; + bool fScaleByCpus = false; + RTTHREADTYPE enmThreadType = RTTHREADTYPE_DEFAULT; + RTPROCPRIORITY enmProcPriority = RTPROCPRIORITY_DEFAULT; + uint64_t cNanoSeconds = UINT64_MAX; + + RTR3InitExe(argc, &argv, 0); + + /* + * Set program name. + */ + g_pszProgramName = RTPathFilename(argv[0]); + + /* + * Parse arguments. + */ + static const RTGETOPTDEF s_aOptions[] = + { + { "--number-of-threads", 'n', RTGETOPT_REQ_UINT32 }, + { "--timeout", 't', RTGETOPT_REQ_STRING }, + { "--thread-type", 'p', RTGETOPT_REQ_STRING }, + { "--scale-by-cpus", 'c', RTGETOPT_REQ_NOTHING }, + { "--load", 'l', RTGETOPT_REQ_STRING }, + }; + int ch; + RTGETOPTUNION ValueUnion; + RTGETOPTSTATE GetState; + RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0 /* fFlags */); + while ((ch = RTGetOpt(&GetState, &ValueUnion))) + { + switch (ch) + { + case 'n': + cThreads = ValueUnion.u64; + if (cThreads == 0 || cThreads > RT_ELEMENTS(s_aThreads)) + return SyntaxError("Requested number of threads, %RU32, is out of range (1..%d).\n", + cThreads, RT_ELEMENTS(s_aThreads) - 1); + break; + + case 't': + { + char *psz; + rc = RTStrToUInt64Ex(ValueUnion.psz, &psz, 0, &cNanoSeconds); + if (RT_FAILURE(rc)) + return SyntaxError("Failed reading the alleged number '%s' (option '%s', rc=%Rrc).\n", + ValueUnion.psz, rc); + while (*psz == ' ' || *psz == '\t') + psz++; + if (*psz) + { + uint64_t u64Factor = 1; + if (!strcmp(psz, "ns")) + u64Factor = 1; + else if (!strcmp(psz, "ms")) + u64Factor = 1000; + else if (!strcmp(psz, "s")) + u64Factor = 1000000000; + else if (!strcmp(psz, "m")) + u64Factor = UINT64_C(60000000000); + else if (!strcmp(psz, "h")) + u64Factor = UINT64_C(3600000000000); + else + return SyntaxError("Unknown time suffix '%s'\n", psz); + uint64_t u64 = cNanoSeconds * u64Factor; + if (u64 < cNanoSeconds || (u64 < u64Factor && u64)) + return SyntaxError("Time representation overflowed! (%RU64 * %RU64)\n", + psz, cNanoSeconds, u64Factor); + cNanoSeconds = u64; + } + break; + } + + case 'p': + { + enmProcPriority = RTPROCPRIORITY_NORMAL; + + uint32_t u32 = RTTHREADTYPE_INVALID; + char *psz; + rc = RTStrToUInt32Ex(ValueUnion.psz, &psz, 0, &u32); + if (RT_FAILURE(rc) || *psz) + { + if (!strcmp(ValueUnion.psz, "default")) + { + enmProcPriority = RTPROCPRIORITY_DEFAULT; + enmThreadType = RTTHREADTYPE_DEFAULT; + } + else if (!strcmp(ValueUnion.psz, "idle")) + { + enmProcPriority = RTPROCPRIORITY_LOW; + enmThreadType = RTTHREADTYPE_INFREQUENT_POLLER; + } + else if (!strcmp(ValueUnion.psz, "high")) + { + enmProcPriority = RTPROCPRIORITY_HIGH; + enmThreadType = RTTHREADTYPE_IO; + } + else + return SyntaxError("can't grok thread type '%s'\n", + ValueUnion.psz); + } + else + { + enmThreadType = (RTTHREADTYPE)u32; + if (enmThreadType <= RTTHREADTYPE_INVALID || enmThreadType >= RTTHREADTYPE_END) + return SyntaxError("thread type '%d' is out of range (%d..%d)\n", + ValueUnion.psz, RTTHREADTYPE_INVALID + 1, RTTHREADTYPE_END - 1); + } + break; + } + + case 'c': + fScaleByCpus = true; + break; + + case 'l': + { + for (unsigned i = 0; i < RT_ELEMENTS(s_aLoadTypes); i++) + if (!strcmp(s_aLoadTypes[i].pszName, ValueUnion.psz)) + { + ValueUnion.psz = NULL; + iLoadType = i; + break; + } + if (ValueUnion.psz) + return SyntaxError("Unknown load type '%s'.\n", ValueUnion.psz); + break; + } + + case 'h': + RTStrmPrintf(g_pStdOut, + "Usage: %s [-p|--thread-type <type>] [-t|--timeout <sec|xxx[h|m|s|ms|ns]>] \\\n" + " %*s [-n|--number-of-threads <threads>] [-l|--load <loadtype>]\n" + "\n" + "Load types: spin, ipi.\n" + , + g_pszProgramName, strlen(g_pszProgramName), ""); + return 1; + + case 'V': + RTPrintf("$Revision: 127855 $\n"); + return 0; + + case VINF_GETOPT_NOT_OPTION: + return SyntaxError("Unknown argument #%d: '%s'\n", GetState.iNext-1, ValueUnion.psz); + + default: + return RTGetOptPrintError(ch, &ValueUnion); + } + } + + /* + * Scale thread count by host cpu count. + */ + if (fScaleByCpus) + { + const unsigned cCpus = RTMpGetOnlineCount(); + if (cCpus * cThreads > RT_ELEMENTS(s_aThreads)) + return SyntaxError("Requested number of threads, %RU32, is out of range (1..%d) when scaled by %d.\n", + cThreads, RT_ELEMENTS(s_aThreads) - 1, cCpus); + cThreads *= cCpus; + } + + /* + * Modify process and thread priority? (ignore failure) + */ + if (enmProcPriority != RTPROCPRIORITY_DEFAULT) + RTProcSetPriority(enmProcPriority); + if (enmThreadType != RTTHREADTYPE_DEFAULT) + RTThreadSetType(RTThreadSelf(), enmThreadType); + + /* + * Load type specific init. + */ + if (s_aLoadTypes[iLoadType].pfnInit) + { + rc = s_aLoadTypes[iLoadType].pfnInit(); + if (RT_FAILURE(rc)) + return 1; + } + + + /* + * Start threads. + */ + for (unsigned i = 1; i < cThreads; i++) + { + s_aThreads[i] = NIL_RTTHREAD; + rc = RTThreadCreate(&s_aThreads[i], s_aLoadTypes[iLoadType].pfnThread, + &cNanoSeconds, 128*1024, enmThreadType, RTTHREADFLAGS_WAITABLE, "spinner"); + if (RT_FAILURE(rc)) + { + ASMAtomicXchgBool(&g_fQuit, true); + RTStrmPrintf(g_pStdErr, "%s: failed to create thread #%d, rc=%Rrc\n", g_pszProgramName, i, rc); + while (i-- > 1) + RTThreadWait(s_aThreads[i], 1500, NULL); + return 1; + } + } + + /* our selves */ + s_aLoadTypes[iLoadType].pfnThread(RTThreadSelf(), &cNanoSeconds); + + /* + * Wait for threads. + */ + ASMAtomicXchgBool(&g_fQuit, true); + for (unsigned i = 1; i < cThreads; i++) + RTThreadWait(s_aThreads[i], 1500, NULL); + + return 0; +} + diff --git a/src/VBox/ValidationKit/utils/misc/loadgeneratorR0.cpp b/src/VBox/ValidationKit/utils/misc/loadgeneratorR0.cpp new file mode 100644 index 00000000..b45638af --- /dev/null +++ b/src/VBox/ValidationKit/utils/misc/loadgeneratorR0.cpp @@ -0,0 +1,91 @@ +/* $Id: loadgeneratorR0.cpp $ */ +/** @file + * Load Generator, Ring-0 Service. + */ + +/* + * Copyright (C) 2008-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * 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. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <iprt/mp.h> +#include <VBox/sup.h> +#include <iprt/errcore.h> + + + + +/** + * Worker for loadgenR0Ipi. + */ +static DECLCALLBACK(void) loadgenR0IpiWorker(RTCPUID idCpu, void *pvUser1, void *pvUser2) +{ + NOREF(idCpu); + NOREF(pvUser1); + NOREF(pvUser2); +} + + +/** + * Generate broadcast inter processor interrupts (IPI), aka cross calls. + * + * @returns VBox status code. + * @param cIpis The number of IPIs to do. + */ +static int loadgenR0Ipi(uint64_t cIpis) +{ + if (cIpis > _1G || !cIpis) + return VERR_INVALID_PARAMETER; + + while (cIpis-- > 0) + { + int rc = RTMpOnAll(loadgenR0IpiWorker, NULL, NULL); + if (RT_FAILURE(rc)) + return rc; + } + return VINF_SUCCESS; +} + + +/** + * Service request handler entry point. + * + * @copydoc FNSUPR0SERVICEREQHANDLER + */ +extern "C" DECLEXPORT(int) LoadGenR0ServiceReqHandler(PSUPDRVSESSION pSession, uint32_t uOperation, + uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr) + +{ + switch (uOperation) + { + case 0: + if (pReqHdr) + return VERR_INVALID_PARAMETER; + return loadgenR0Ipi(u64Arg); + + default: + NOREF(pSession); + return VERR_NOT_SUPPORTED; + } +} + diff --git a/src/VBox/ValidationKit/utils/misc/vts_rm.cpp b/src/VBox/ValidationKit/utils/misc/vts_rm.cpp new file mode 100644 index 00000000..646905fa --- /dev/null +++ b/src/VBox/ValidationKit/utils/misc/vts_rm.cpp @@ -0,0 +1,44 @@ +/* $Id: vts_rm.cpp $ */ +/** @file + * VirtualBox Validation Kit - rm like utility. + */ + +/* + * Copyright (C) 2013-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * 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. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <iprt/path.h> +#include <iprt/errcore.h> +#include <iprt/initterm.h> +#include <iprt/message.h> + + +int main(int argc, char **argv) +{ + int rc = RTR3InitExe(argc, &argv, 0); + if (RT_FAILURE(rc)) + return RTMsgInitFailure(rc); + return RTPathRmCmd(argc, argv); +} + diff --git a/src/VBox/ValidationKit/utils/misc/vts_tar.cpp b/src/VBox/ValidationKit/utils/misc/vts_tar.cpp new file mode 100644 index 00000000..bcc8c3c7 --- /dev/null +++ b/src/VBox/ValidationKit/utils/misc/vts_tar.cpp @@ -0,0 +1,44 @@ +/* $Id: vts_tar.cpp $ */ +/** @file + * VirtualBox Validation Kit - tar like utility. + */ + +/* + * Copyright (C) 2013-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * 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. + */ + + +/********************************************************************************************************************************* +* Header Files * +*********************************************************************************************************************************/ +#include <iprt/zip.h> +#include <iprt/errcore.h> +#include <iprt/initterm.h> +#include <iprt/message.h> + + +int main(int argc, char **argv) +{ + int rc = RTR3InitExe(argc, &argv, 0); + if (RT_FAILURE(rc)) + return RTMsgInitFailure(rc); + return RTZipTarCmd(argc, argv); +} + |