cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/* $Id$ */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/** @file
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Allocate all memory we can get and then quit.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Copyright (C) 2011-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/test.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/asm.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/list.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/mem.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/param.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/string.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#include <iprt/time.h>
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync/*******************************************************************************
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync* Structures and Typedefs *
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync*******************************************************************************/
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynctypedef struct TSTALLOC
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** The page sequence number. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t iPageSeq;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** The allocation sequence number. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t iAllocSeq;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** The allocation size. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t cb;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Pointer to the ourselves (paranoid). */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync void *pv;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /** Linked list node. */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTLISTNODE Node;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync} TSTALLOC;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsynctypedef TSTALLOC *PTSTALLOC;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic bool checkList(PRTLISTNODE pHead)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t iPageSeq = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t iAllocSeq = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync PTSTALLOC pCur;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTListForEach(pHead, pCur, TSTALLOC, Node)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTESTI_CHECK_RET(pCur->iAllocSeq == iAllocSeq, false);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTESTI_CHECK_RET(pCur->pv == pCur, false);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t const *pu = (size_t const *)pCur;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t const *puEnd = pu + pCur->cb / sizeof(size_t);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (pu != puEnd)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTESTI_CHECK_RET(*pu == iPageSeq, false);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync iPageSeq++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pu += PAGE_SIZE / sizeof(size_t);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync iAllocSeq++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return true;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncstatic void doTest(RTTEST hTest)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestSub(hTest, "Allocate all memory");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTLISTANCHOR AllocHead;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync PTSTALLOC pCur;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t cNsElapsed = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t cbPrint = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t uPrintTS = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t cbTotal = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if ARCH_BITS == 64
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t const cbOneStart = 64 * _1M;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t const cbOneMin = 4 * _1M;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t const cbOneStart = 16 * _1M;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t const cbOneMin = 4 * _1M;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t cbOne = cbOneStart;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t cAllocs = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t iPageSeq = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTListInit(&AllocHead);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync for (;;)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Allocate a chunk and make sure all the pages are there.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t const uStartTS = RTTimeNanoTS();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pCur = (PTSTALLOC)RTMemPageAlloc(cbOne);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (pCur)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t *pu = (size_t *)pCur;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t *puEnd = pu + cbOne / sizeof(size_t);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync while (pu != puEnd)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync *pu = iPageSeq++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pu += PAGE_SIZE / sizeof(size_t);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t const uEndTS = RTTimeNanoTS();
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint64_t const cNsThis = uEndTS - uStartTS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Update the statistics.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cNsElapsed += cNsThis;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cbTotal += cbOne;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cAllocs++;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Link the allocation.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pCur->iAllocSeq = cAllocs - 1;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pCur->pv = pCur;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync pCur->cb = cbOne;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTListAppend(&AllocHead, &pCur->Node);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Print progress info?
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if ( uEndTS - uPrintTS >= RT_NS_1SEC_64*10
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#if ARCH_BITS == 64
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || cbTotal - cbPrint >= _4G
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync || cbTotal - cbPrint >= _2G
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync#endif
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync )
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cbPrint = cbTotal;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uPrintTS = uEndTS;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t cMBPerSec = (uint32_t)(cbTotal / ((double)cNsElapsed / RT_NS_1SEC) / _1M);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "%'zu bytes in %'llu ns - %'u MB/s\n",
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cbTotal, cNsElapsed, cMBPerSec);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTESTI_CHECK_RETV(checkList(&AllocHead));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Try again with a smaller request.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Failed to allocate %'zu bytes (after %'zu bytes)\n", cbOne, cbTotal);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (cbOne <= cbOneMin)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync cbOne = cbOneMin;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Verifying...\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTESTI_CHECK_RETV(checkList(&AllocHead));
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "... detected no corruption.\n");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync /*
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync * Free up some memory before displaying the results.
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync */
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync size_t i = 0;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync PTSTALLOC pPrev;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTListForEachReverseSafe(&AllocHead, pCur, pPrev, TSTALLOC, Node)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync {
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTMemPageFree(pCur->pv, pCur->cb);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (++i > 32)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync break;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync }
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestValue(hTest, "amount", cbTotal, RTTESTUNIT_BYTES);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestValue(hTest, "time", cNsElapsed, RTTESTUNIT_NS);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync uint32_t cMBPerSec = (uint32_t)(cbTotal / ((double)cNsElapsed / RT_NS_1SEC) / _1M);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestValue(hTest, "speed", cMBPerSec, RTTESTUNIT_MEGABYTES_PER_SEC);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestSubDone(hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsyncint main(int argc, char **argv)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync{
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTEST hTest;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTEXITCODE rcExit = RTTestInitAndCreate("memallocall", &hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (rcExit != RTEXITCODE_SUCCESS)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return rcExit;
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestBanner(hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync NOREF(argv);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync if (argc == 1)
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync doTest(hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync else
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync RTTestFailed(hTest, "This test takes no arguments!");
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync return RTTestSummaryAndDestroy(hTest);
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync}
cf22150eaeeb72431bf1cf65c309a431454fb22bvboxsync