<commit_before>/*
 * Copyright 2010-2011 PathScale, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * memory.cc - Contains stub definition of C++ new/delete operators.
 *
 * These definitions are intended to be used for testing and are weak symbols
 * to allow them to be replaced by definitions from a STL implementation.
 * These versions simply wrap malloc() and free(), they do not provide a
 * C++-specific allocator.
 */

#include <stddef.h>
#include <stdlib.h>
#include "stdexcept.h"
#include "atomic.h"

namespace std
{
	struct nothrow_t {};
}

/// The type of the function called when allocation fails.
typedef void (*new_handler)();
/**
 * The function to call when allocation fails.  By default, there is no
 * handler and a bad allocation exception is thrown if an allocation fails.
 */
static new_handler new_handl;

namespace std
{
	/**
	 * Sets a function to be called when there is a failure in new.
	 */
	__attribute__((weak))
	new_handler set_new_handler(new_handler handler)
	{
		return ATOMIC_SWAP(&new_handl, handler);
	}
	__attribute__((weak))
	new_handler get_new_handler(void)
	{
		return ATOMIC_LOAD(&new_handl);
	}
}

__attribute__((weak))
void* operator new(size_t size)
{
	if (0 == size)
	{
		size = 1;
	}
	void * mem = malloc(size);
	while (0 == mem)
	{
		new_handler h = std::get_new_handler();
		if (0 != h)
		{
			h();
		}
		else
		{
			throw std::bad_alloc();
		}
		mem = malloc(size);
	}

	return mem;
}

__attribute__((weak))
void* operator new(size_t size, const std::nothrow_t &) throw()
{
	try {
		return :: operator new(size);
	} catch (...) {
		// nothrow operator new should return NULL in case of
		// std::bad_alloc exception in new handler
		return NULL;
	}
}

__attribute__((weak))
void operator delete(void * ptr)
{
	free(ptr);
}

__attribute__((weak))
void * operator new[](size_t size)
{
	return ::operator new(size);
}

__attribute__((weak))
void * operator new[](size_t size, const std::nothrow_t &) throw()
{
	try {
		return ::operator new[](size);
	} catch (...) {
		// nothrow operator new should return NULL in case of
		// std::bad_alloc exception in new handler
		return NULL;
	}
}

__attribute__((weak))
void operator delete[](void * ptr) throw()
{
	::operator delete(ptr);
}

<commit_msg>am 67917c05: Make exception specifications conditional on language dialect for new / delete operators (fixes warnings when compiling as C++11)<commit_after>/*
 * Copyright 2010-2011 PathScale, Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * memory.cc - Contains stub definition of C++ new/delete operators.
 *
 * These definitions are intended to be used for testing and are weak symbols
 * to allow them to be replaced by definitions from a STL implementation.
 * These versions simply wrap malloc() and free(), they do not provide a
 * C++-specific allocator.
 */

#include <stddef.h>
#include <stdlib.h>
#include "stdexcept.h"
#include "atomic.h"

namespace std
{
	struct nothrow_t {};
}

/// The type of the function called when allocation fails.
typedef void (*new_handler)();
/**
 * The function to call when allocation fails.  By default, there is no
 * handler and a bad allocation exception is thrown if an allocation fails.
 */
static new_handler new_handl;

namespace std
{
	/**
	 * Sets a function to be called when there is a failure in new.
	 */
	__attribute__((weak))
	new_handler set_new_handler(new_handler handler)
	{
		return ATOMIC_SWAP(&new_handl, handler);
	}
	__attribute__((weak))
	new_handler get_new_handler(void)
	{
		return ATOMIC_LOAD(&new_handl);
	}
}

__attribute__((weak))
void* operator new(size_t size)
{
	if (0 == size)
	{
		size = 1;
	}
	void * mem = malloc(size);
	while (0 == mem)
	{
		new_handler h = std::get_new_handler();
		if (0 != h)
		{
			h();
		}
		else
		{
			throw std::bad_alloc();
		}
		mem = malloc(size);
	}

	return mem;
}

__attribute__((weak))
void* operator new(size_t size, const std::nothrow_t &) throw()
{
	try {
		return :: operator new(size);
	} catch (...) {
		// nothrow operator new should return NULL in case of
		// std::bad_alloc exception in new handler
		return NULL;
	}
}

__attribute__((weak))
void operator delete(void * ptr)
#if __cplusplus < 201000L
throw()
#endif
{
	free(ptr);
}

__attribute__((weak))
void * operator new[](size_t size)
#if __cplusplus < 201000L
throw(std::bad_alloc)
#endif
{
	return ::operator new(size);
}

__attribute__((weak))
void * operator new[](size_t size, const std::nothrow_t &) throw()
{
	try {
		return ::operator new[](size);
	} catch (...) {
		// nothrow operator new should return NULL in case of
		// std::bad_alloc exception in new handler
		return NULL;
	}
}

__attribute__((weak))
void operator delete[](void * ptr)
#if __cplusplus < 201000L
throw()
#endif
{
	::operator delete(ptr);
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2004-2005 The Regents of The University of Michigan
 * Copyright (c) 2016 The University of Virginia
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 *          Ali Saidi
 *          Korey Sewell
 *          Alec Roelke
 */
#include "arch/riscv/process.hh"

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <map>
#include <string>
#include <vector>

#include "arch/riscv/isa_traits.hh"
#include "base/loader/elf_object.hh"
#include "base/loader/object_file.hh"
#include "base/logging.hh"
#include "cpu/thread_context.hh"
#include "debug/Stack.hh"
#include "mem/page_table.hh"
#include "params/Process.hh"
#include "sim/aux_vector.hh"
#include "sim/process.hh"
#include "sim/process_impl.hh"
#include "sim/syscall_return.hh"
#include "sim/system.hh"

using namespace std;
using namespace RiscvISA;

RiscvProcess::RiscvProcess(ProcessParams * params,
    ObjectFile *objFile) : Process(params, objFile)
{
    const Addr stack_base = 0x7FFFFFFFFFFFFFFFL;
    const Addr max_stack_size = 8 * 1024 * 1024;
    const Addr next_thread_stack_base = stack_base - max_stack_size;
    const Addr brk_point = roundUp(objFile->bssBase() + objFile->bssSize(),
            PageBytes);
    const Addr mmap_end = 0x4000000000000000L;
    memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
            next_thread_stack_base, mmap_end);
}

void
RiscvProcess::initState()
{
    Process::initState();

    argsInit<uint64_t>(PageBytes);
}

template<class IntType> void
RiscvProcess::argsInit(int pageSize)
{
    updateBias();
    objFile->loadSections(initVirtMem);
    ElfObject* elfObject = dynamic_cast<ElfObject*>(objFile);
    memState->setStackMin(memState->getStackBase());

    // Determine stack size and populate auxv
    Addr stack_top = memState->getStackMin();
    stack_top -= elfObject->programHeaderSize();
    for (const string& arg: argv)
        stack_top -= arg.size() + 1;
    for (const string& env: envp)
        stack_top -= env.size() + 1;
    stack_top &= -sizeof(Addr);

    vector<AuxVector<IntType>> auxv;
    if (elfObject != nullptr) {
        auxv.push_back({M5_AT_ENTRY, objFile->entryPoint()});
        auxv.push_back({M5_AT_PHNUM, elfObject->programHeaderCount()});
        auxv.push_back({M5_AT_PHENT, elfObject->programHeaderSize()});
        auxv.push_back({M5_AT_PHDR, elfObject->programHeaderTable()});
        auxv.push_back({M5_AT_PAGESZ, PageBytes});
        auxv.push_back({M5_AT_SECURE, 0});
        auxv.push_back({M5_AT_RANDOM, stack_top});
        auxv.push_back({M5_AT_NULL, 0});
    }
    stack_top -= (1 + argv.size()) * sizeof(Addr) +
                   (1 + envp.size()) * sizeof(Addr) +
                   sizeof(Addr) + 2 * sizeof(IntType) * auxv.size();
    stack_top &= -2*sizeof(Addr);
    memState->setStackSize(memState->getStackBase() - stack_top);
    allocateMem(roundDown(stack_top, pageSize),
            roundUp(memState->getStackSize(), pageSize));

    // Copy program headers to stack
    memState->setStackMin(memState->getStackMin() -
            elfObject->programHeaderSize());
    uint8_t* phdr = new uint8_t[elfObject->programHeaderSize()];
    initVirtMem.readBlob(elfObject->programHeaderTable(), phdr,
            elfObject->programHeaderSize());
    initVirtMem.writeBlob(memState->getStackMin(), phdr,
            elfObject->programHeaderSize());
    delete phdr;

    // Copy argv to stack
    vector<Addr> argPointers;
    for (const string& arg: argv) {
        memState->setStackMin(memState->getStackMin() - (arg.size() + 1));
        initVirtMem.writeString(memState->getStackMin(), arg.c_str());
        argPointers.push_back(memState->getStackMin());
        if (DTRACE(Stack)) {
            string wrote;
            initVirtMem.readString(wrote, argPointers.back());
            DPRINTFN("Wrote arg \"%s\" to address %p\n",
                    wrote, (void*)memState->getStackMin());
        }
    }
    argPointers.push_back(0);

    // Copy envp to stack
    vector<Addr> envPointers;
    for (const string& env: envp) {
        memState->setStackMin(memState->getStackMin() - (env.size() + 1));
        initVirtMem.writeString(memState->getStackMin(), env.c_str());
        envPointers.push_back(memState->getStackMin());
        DPRINTF(Stack, "Wrote env \"%s\" to address %p\n",
                env, (void*)memState->getStackMin());
    }
    envPointers.push_back(0);

    // Align stack
    memState->setStackMin(memState->getStackMin() & -sizeof(Addr));

    // Calculate bottom of stack
    memState->setStackMin(memState->getStackMin() -
            ((1 + argv.size()) * sizeof(Addr) +
             (1 + envp.size()) * sizeof(Addr) +
             sizeof(Addr) + 2 * sizeof(IntType) * auxv.size()));
    memState->setStackMin(memState->getStackMin() & -2*sizeof(Addr));
    Addr sp = memState->getStackMin();
    const auto pushOntoStack =
        [this, &sp](const uint8_t* data, const size_t size) {
            initVirtMem.writeBlob(sp, data, size);
            sp += size;
        };

    // Push argc and argv pointers onto stack
    IntType argc = htog((IntType)argv.size());
    DPRINTF(Stack, "Wrote argc %d to address %p\n",
            argv.size(), (void*)sp);
    pushOntoStack((uint8_t*)&argc, sizeof(IntType));
    for (const Addr& argPointer: argPointers) {
        DPRINTF(Stack, "Wrote argv pointer %p to address %p\n",
                (void*)argPointer, (void*)sp);
        pushOntoStack((uint8_t*)&argPointer, sizeof(Addr));
    }

    // Push env pointers onto stack
    for (const Addr& envPointer: envPointers) {
        DPRINTF(Stack, "Wrote envp pointer %p to address %p\n",
                (void*)envPointer, (void*)sp);
        pushOntoStack((uint8_t*)&envPointer, sizeof(Addr));
    }

    // Push aux vector onto stack
    std::map<IntType, string> aux_keys = {
        {M5_AT_ENTRY, "M5_AT_ENTRY"},
        {M5_AT_PHNUM, "M5_AT_PHNUM"},
        {M5_AT_PHENT, "M5_AT_PHENT"},
        {M5_AT_PHDR, "M5_AT_PHDR"},
        {M5_AT_PAGESZ, "M5_AT_PAGESZ"},
        {M5_AT_SECURE, "M5_AT_SECURE"},
        {M5_AT_RANDOM, "M5_AT_RANDOM"},
        {M5_AT_NULL, "M5_AT_NULL"}
    };
    for (const AuxVector<IntType>& aux: auxv) {
        DPRINTF(Stack, "Wrote aux key %s to address %p\n",
                aux_keys[aux.a_type], (void*)sp);
        pushOntoStack((uint8_t*)&aux.a_type, sizeof(IntType));
        DPRINTF(Stack, "Wrote aux value %x to address %p\n",
                aux.a_val, (void*)sp);
        pushOntoStack((uint8_t*)&aux.a_val, sizeof(IntType));
    }

    ThreadContext *tc = system->getThreadContext(contextIds[0]);
    tc->setIntReg(StackPointerReg, memState->getStackMin());
    tc->pcState(getStartPC());

    memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
}

RiscvISA::IntReg
RiscvProcess::getSyscallArg(ThreadContext *tc, int &i)
{
    // RISC-V only has four system call argument registers by convention, so
    // if a larger index is requested return 0
    RiscvISA::IntReg retval = 0;
    if (i < 4)
        retval = tc->readIntReg(SyscallArgumentRegs[i]);
    i++;
    return retval;
}

void
RiscvProcess::setSyscallArg(ThreadContext *tc, int i, RiscvISA::IntReg val)
{
    tc->setIntReg(SyscallArgumentRegs[i], val);
}

void
RiscvProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
{
    if (sysret.successful()) {
        // no error
        tc->setIntReg(SyscallPseudoReturnReg, sysret.returnValue());
    } else {
        // got an error, return details
        tc->setIntReg(SyscallPseudoReturnReg, sysret.errnoValue());
    }
}
<commit_msg>arch-riscv: Define AT_RANDOM properly<commit_after>/*
 * Copyright (c) 2004-2005 The Regents of The University of Michigan
 * Copyright (c) 2016 The University of Virginia
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 *          Ali Saidi
 *          Korey Sewell
 *          Alec Roelke
 */
#include "arch/riscv/process.hh"

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <iterator>
#include <map>
#include <string>
#include <vector>

#include "arch/riscv/isa_traits.hh"
#include "base/loader/elf_object.hh"
#include "base/loader/object_file.hh"
#include "base/logging.hh"
#include "base/random.hh"
#include "cpu/thread_context.hh"
#include "debug/Stack.hh"
#include "mem/page_table.hh"
#include "params/Process.hh"
#include "sim/aux_vector.hh"
#include "sim/process.hh"
#include "sim/process_impl.hh"
#include "sim/syscall_return.hh"
#include "sim/system.hh"

using namespace std;
using namespace RiscvISA;

RiscvProcess::RiscvProcess(ProcessParams * params,
    ObjectFile *objFile) : Process(params, objFile)
{
    const Addr stack_base = 0x7FFFFFFFFFFFFFFFL;
    const Addr max_stack_size = 8 * 1024 * 1024;
    const Addr next_thread_stack_base = stack_base - max_stack_size;
    const Addr brk_point = roundUp(objFile->bssBase() + objFile->bssSize(),
            PageBytes);
    const Addr mmap_end = 0x4000000000000000L;
    memState = make_shared<MemState>(brk_point, stack_base, max_stack_size,
            next_thread_stack_base, mmap_end);
}

void
RiscvProcess::initState()
{
    Process::initState();

    argsInit<uint64_t>(PageBytes);
}

template<class IntType> void
RiscvProcess::argsInit(int pageSize)
{
    const int RandomBytes = 16;

    updateBias();
    objFile->loadSections(initVirtMem);
    ElfObject* elfObject = dynamic_cast<ElfObject*>(objFile);
    memState->setStackMin(memState->getStackBase());

    // Determine stack size and populate auxv
    Addr stack_top = memState->getStackMin();
    stack_top -= RandomBytes;
    for (const string& arg: argv)
        stack_top -= arg.size() + 1;
    for (const string& env: envp)
        stack_top -= env.size() + 1;
    stack_top &= -sizeof(Addr);

    vector<AuxVector<IntType>> auxv;
    if (elfObject != nullptr) {
        auxv.push_back({M5_AT_ENTRY, objFile->entryPoint()});
        auxv.push_back({M5_AT_PHNUM, elfObject->programHeaderCount()});
        auxv.push_back({M5_AT_PHENT, elfObject->programHeaderSize()});
        auxv.push_back({M5_AT_PHDR, elfObject->programHeaderTable()});
        auxv.push_back({M5_AT_PAGESZ, PageBytes});
        auxv.push_back({M5_AT_SECURE, 0});
        auxv.push_back({M5_AT_RANDOM, stack_top});
        auxv.push_back({M5_AT_NULL, 0});
    }
    stack_top -= (1 + argv.size()) * sizeof(Addr) +
                   (1 + envp.size()) * sizeof(Addr) +
                   sizeof(Addr) + 2 * sizeof(IntType) * auxv.size();
    stack_top &= -2*sizeof(Addr);
    memState->setStackSize(memState->getStackBase() - stack_top);
    allocateMem(roundDown(stack_top, pageSize),
            roundUp(memState->getStackSize(), pageSize));

    // Copy random bytes (for AT_RANDOM) to stack
    memState->setStackMin(memState->getStackMin() - RandomBytes);
    uint8_t at_random[RandomBytes];
    generate(begin(at_random), end(at_random),
             [&]{ return random_mt.random(0, 0xFF); });
    initVirtMem.writeBlob(memState->getStackMin(), at_random, RandomBytes);

    // Copy argv to stack
    vector<Addr> argPointers;
    for (const string& arg: argv) {
        memState->setStackMin(memState->getStackMin() - (arg.size() + 1));
        initVirtMem.writeString(memState->getStackMin(), arg.c_str());
        argPointers.push_back(memState->getStackMin());
        if (DTRACE(Stack)) {
            string wrote;
            initVirtMem.readString(wrote, argPointers.back());
            DPRINTFN("Wrote arg \"%s\" to address %p\n",
                    wrote, (void*)memState->getStackMin());
        }
    }
    argPointers.push_back(0);

    // Copy envp to stack
    vector<Addr> envPointers;
    for (const string& env: envp) {
        memState->setStackMin(memState->getStackMin() - (env.size() + 1));
        initVirtMem.writeString(memState->getStackMin(), env.c_str());
        envPointers.push_back(memState->getStackMin());
        DPRINTF(Stack, "Wrote env \"%s\" to address %p\n",
                env, (void*)memState->getStackMin());
    }
    envPointers.push_back(0);

    // Align stack
    memState->setStackMin(memState->getStackMin() & -sizeof(Addr));

    // Calculate bottom of stack
    memState->setStackMin(memState->getStackMin() -
            ((1 + argv.size()) * sizeof(Addr) +
             (1 + envp.size()) * sizeof(Addr) +
             sizeof(Addr) + 2 * sizeof(IntType) * auxv.size()));
    memState->setStackMin(memState->getStackMin() & -2*sizeof(Addr));
    Addr sp = memState->getStackMin();
    const auto pushOntoStack =
        [this, &sp](const uint8_t* data, const size_t size) {
            initVirtMem.writeBlob(sp, data, size);
            sp += size;
        };

    // Push argc and argv pointers onto stack
    IntType argc = htog((IntType)argv.size());
    DPRINTF(Stack, "Wrote argc %d to address %p\n",
            argv.size(), (void*)sp);
    pushOntoStack((uint8_t*)&argc, sizeof(IntType));
    for (const Addr& argPointer: argPointers) {
        DPRINTF(Stack, "Wrote argv pointer %p to address %p\n",
                (void*)argPointer, (void*)sp);
        pushOntoStack((uint8_t*)&argPointer, sizeof(Addr));
    }

    // Push env pointers onto stack
    for (const Addr& envPointer: envPointers) {
        DPRINTF(Stack, "Wrote envp pointer %p to address %p\n",
                (void*)envPointer, (void*)sp);
        pushOntoStack((uint8_t*)&envPointer, sizeof(Addr));
    }

    // Push aux vector onto stack
    std::map<IntType, string> aux_keys = {
        {M5_AT_ENTRY, "M5_AT_ENTRY"},
        {M5_AT_PHNUM, "M5_AT_PHNUM"},
        {M5_AT_PHENT, "M5_AT_PHENT"},
        {M5_AT_PHDR, "M5_AT_PHDR"},
        {M5_AT_PAGESZ, "M5_AT_PAGESZ"},
        {M5_AT_SECURE, "M5_AT_SECURE"},
        {M5_AT_RANDOM, "M5_AT_RANDOM"},
        {M5_AT_NULL, "M5_AT_NULL"}
    };
    for (const AuxVector<IntType>& aux: auxv) {
        DPRINTF(Stack, "Wrote aux key %s to address %p\n",
                aux_keys[aux.a_type], (void*)sp);
        pushOntoStack((uint8_t*)&aux.a_type, sizeof(IntType));
        DPRINTF(Stack, "Wrote aux value %x to address %p\n",
                aux.a_val, (void*)sp);
        pushOntoStack((uint8_t*)&aux.a_val, sizeof(IntType));
    }

    ThreadContext *tc = system->getThreadContext(contextIds[0]);
    tc->setIntReg(StackPointerReg, memState->getStackMin());
    tc->pcState(getStartPC());

    memState->setStackMin(roundDown(memState->getStackMin(), pageSize));
}

RiscvISA::IntReg
RiscvProcess::getSyscallArg(ThreadContext *tc, int &i)
{
    // RISC-V only has four system call argument registers by convention, so
    // if a larger index is requested return 0
    RiscvISA::IntReg retval = 0;
    if (i < 4)
        retval = tc->readIntReg(SyscallArgumentRegs[i]);
    i++;
    return retval;
}

void
RiscvProcess::setSyscallArg(ThreadContext *tc, int i, RiscvISA::IntReg val)
{
    tc->setIntReg(SyscallArgumentRegs[i], val);
}

void
RiscvProcess::setSyscallReturn(ThreadContext *tc, SyscallReturn sysret)
{
    if (sysret.successful()) {
        // no error
        tc->setIntReg(SyscallPseudoReturnReg, sysret.returnValue());
    } else {
        // got an error, return details
        tc->setIntReg(SyscallPseudoReturnReg, sysret.errnoValue());
    }
}
<|endoftext|>


<commit_before>/*
  * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License").
  * You may not use this file except in compliance with the License.
  * A copy of the License is located at
  *
  *  http://aws.amazon.com/apache2.0
  *
  * or in the "license" file accompanying this file. This file is distributed
  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  * express or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */

#include <aws/core/utils/StringUtils.h>

#include <aws/core/utils/memory/stl/AWSStringStream.h>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <functional>

using namespace Aws::Utils;

void StringUtils::Replace(Aws::String &s, const char* search, const char* replace)
{
    if(!search || !replace)
    {
        return;
    }

    size_t replaceLength = strlen(replace);
    size_t searchLength = strlen(search);

    for (std::size_t pos = 0;; pos += replaceLength)
    {
        pos = s.find(search, pos);
        if (pos == Aws::String::npos)
            break;

        s.erase(pos, searchLength);
        s.insert(pos, replace);
    }
}

Aws::String StringUtils::ToLower(const char* source)
{
    Aws::String copy;
    size_t sourceLength = strlen(source);
    copy.resize(sourceLength);
    std::transform(source, source + sourceLength, copy.begin(), ::tolower);

    return std::move(copy);
}

Aws::String StringUtils::ToUpper(const char* source)
{
    Aws::String copy;
    size_t sourceLength = strlen(source);
    copy.resize(sourceLength);
    std::transform(source, source + sourceLength, copy.begin(), ::toupper);

    return std::move(copy);
}

bool StringUtils::CaselessCompare(const char* value1, const char* value2)
{
    Aws::String value1Lower = ToLower(value1);
    Aws::String value2Lower = ToLower(value2);

    return value1Lower == value2Lower;
}

Aws::Vector<Aws::String> StringUtils::Split(const Aws::String& toSplit, char splitOn)
{
    Aws::StringStream input(toSplit);
    Aws::Vector<Aws::String> returnValues;
    Aws::String item;

    while(std::getline(input, item, splitOn))
    {
        if(item.size() > 0)
        {
            returnValues.push_back(item);
        }
    }

    return std::move(returnValues);
}

Aws::Vector<Aws::String> StringUtils::SplitOnLine(const Aws::String& toSplit)
{
    Aws::StringStream input(toSplit);
    Aws::Vector<Aws::String> returnValues;
    Aws::String item;

    while (std::getline(input, item))
    {
        if (item.size() > 0)
        {
            returnValues.push_back(item);
        }
    }

    return std::move(returnValues);
}

Aws::String StringUtils::URLEncode(const char* unsafe)
{
    Aws::StringStream escaped;
    escaped.fill('0');
    escaped << std::hex << std::uppercase;

    size_t unsafeLength = strlen(unsafe);
    for (auto i = unsafe, n = unsafe + unsafeLength; i != n; ++i)
    {
        char c = *i;
        if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~')
        {
            escaped << c;
        }
        else
        {
            escaped << '%' << std::setw(2) << ((int) c) << std::setw(0);
        }
    }

    return escaped.str();
}

Aws::String StringUtils::URLEncode(double unsafe)
{
    char buffer[32];
    snprintf(buffer, sizeof(buffer), "%g", unsafe);
    return URLEncode(buffer);

}

Aws::String StringUtils::URLDecode(const char* safe)
{
    Aws::StringStream unescaped;
    unescaped.fill('0');
    unescaped << std::hex;

    size_t safeLength = strlen(safe);
    for (auto i = safe, n = safe + safeLength; i != n; ++i)
    {
        char c = *i;
        if(c == '%')
        {
            char hex[3];
            hex[0] = *(i + 1);
            hex[1] = *(i + 2);
            hex[2] = 0;
            i += 2;
            int hexAsInteger = strtol(hex, nullptr, 16);
            unescaped << (char)hexAsInteger;
        }
        else
        {
            unescaped << *i;
        }
    }

    return unescaped.str();
}

Aws::String StringUtils::LTrim(const char* source)
{
    Aws::String copy(source);
    copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), std::not1(std::ptr_fun<int, int>(::isspace))));
    return std::move(copy);
}

// trim from end
Aws::String StringUtils::RTrim(const char* source)
{
    Aws::String copy(source);
    copy.erase(std::find_if(copy.rbegin(), copy.rend(), std::not1(std::ptr_fun<int, int>(::isspace))).base(), copy.end());
    return std::move(copy);
}

// trim from both ends
Aws::String StringUtils::Trim(const char* source)
{
    return LTrim(RTrim(source).c_str());
}

long long StringUtils::ConvertToInt64(const char* source)
{
    if(!source)
    {
        return 0;
    }

#ifdef __ANDROID__
    return atoll(source);
#else
    return std::atoll(source);
#endif // __ANDROID__
}

long StringUtils::ConvertToInt32(const char* source)
{
    if (!source)
    {
        return 0;
    }

    return std::atol(source);
}

bool StringUtils::ConvertToBool(const char* source)
{
    if(!source)
    {
        return false;
    }

    Aws::String strValue = ToLower(source);
    if(strValue == "true" || strValue == "1")
    {
        return true;
    }

    return false;
}

double StringUtils::ConvertToDouble(const char* source)
{
    if(!source)
    {
        return 0.0;
    }

    return std::strtod(source, NULL);
}

#ifdef _WIN32

Aws::WString StringUtils::ToWString(const char* source)
{
    Aws::WString outString;

    outString.resize(std::strlen(source));
    std::copy(source, source + std::strlen(source), outString.begin());
    return outString;
}

Aws::String StringUtils::FromWString(const wchar_t* source)
{
    Aws::WString inWString(source);

    Aws::String outString(inWString.begin(), inWString.end());
    return outString;
}

#endif

<commit_msg>Forgot about windows not having a fully functioning c99 implementation.<commit_after>/*
  * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License").
  * You may not use this file except in compliance with the License.
  * A copy of the License is located at
  *
  *  http://aws.amazon.com/apache2.0
  *
  * or in the "license" file accompanying this file. This file is distributed
  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  * express or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */

#include <aws/core/utils/StringUtils.h>

#include <aws/core/utils/memory/stl/AWSStringStream.h>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <cstring>
#include <functional>

using namespace Aws::Utils;

void StringUtils::Replace(Aws::String &s, const char* search, const char* replace)
{
    if(!search || !replace)
    {
        return;
    }

    size_t replaceLength = strlen(replace);
    size_t searchLength = strlen(search);

    for (std::size_t pos = 0;; pos += replaceLength)
    {
        pos = s.find(search, pos);
        if (pos == Aws::String::npos)
            break;

        s.erase(pos, searchLength);
        s.insert(pos, replace);
    }
}

Aws::String StringUtils::ToLower(const char* source)
{
    Aws::String copy;
    size_t sourceLength = strlen(source);
    copy.resize(sourceLength);
    std::transform(source, source + sourceLength, copy.begin(), ::tolower);

    return std::move(copy);
}

Aws::String StringUtils::ToUpper(const char* source)
{
    Aws::String copy;
    size_t sourceLength = strlen(source);
    copy.resize(sourceLength);
    std::transform(source, source + sourceLength, copy.begin(), ::toupper);

    return std::move(copy);
}

bool StringUtils::CaselessCompare(const char* value1, const char* value2)
{
    Aws::String value1Lower = ToLower(value1);
    Aws::String value2Lower = ToLower(value2);

    return value1Lower == value2Lower;
}

Aws::Vector<Aws::String> StringUtils::Split(const Aws::String& toSplit, char splitOn)
{
    Aws::StringStream input(toSplit);
    Aws::Vector<Aws::String> returnValues;
    Aws::String item;

    while(std::getline(input, item, splitOn))
    {
        if(item.size() > 0)
        {
            returnValues.push_back(item);
        }
    }

    return std::move(returnValues);
}

Aws::Vector<Aws::String> StringUtils::SplitOnLine(const Aws::String& toSplit)
{
    Aws::StringStream input(toSplit);
    Aws::Vector<Aws::String> returnValues;
    Aws::String item;

    while (std::getline(input, item))
    {
        if (item.size() > 0)
        {
            returnValues.push_back(item);
        }
    }

    return std::move(returnValues);
}

Aws::String StringUtils::URLEncode(const char* unsafe)
{
    Aws::StringStream escaped;
    escaped.fill('0');
    escaped << std::hex << std::uppercase;

    size_t unsafeLength = strlen(unsafe);
    for (auto i = unsafe, n = unsafe + unsafeLength; i != n; ++i)
    {
        char c = *i;
        if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~')
        {
            escaped << c;
        }
        else
        {
            escaped << '%' << std::setw(2) << ((int) c) << std::setw(0);
        }
    }

    return escaped.str();
}

Aws::String StringUtils::URLEncode(double unsafe)
{
    char buffer[32];
#if defined(_MSC_VER) && _MSC_VER < 1900
    _vsnprintf_s(buffer, sizeof(buffer), _TRUNCATE, "%g", unsafe);
#else
    snprintf(buffer, sizeof(buffer), "%g", unsafe);
    return URLEncode(buffer);
#endif

}

Aws::String StringUtils::URLDecode(const char* safe)
{
    Aws::StringStream unescaped;
    unescaped.fill('0');
    unescaped << std::hex;

    size_t safeLength = strlen(safe);
    for (auto i = safe, n = safe + safeLength; i != n; ++i)
    {
        char c = *i;
        if(c == '%')
        {
            char hex[3];
            hex[0] = *(i + 1);
            hex[1] = *(i + 2);
            hex[2] = 0;
            i += 2;
            int hexAsInteger = strtol(hex, nullptr, 16);
            unescaped << (char)hexAsInteger;
        }
        else
        {
            unescaped << *i;
        }
    }

    return unescaped.str();
}

Aws::String StringUtils::LTrim(const char* source)
{
    Aws::String copy(source);
    copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), std::not1(std::ptr_fun<int, int>(::isspace))));
    return std::move(copy);
}

// trim from end
Aws::String StringUtils::RTrim(const char* source)
{
    Aws::String copy(source);
    copy.erase(std::find_if(copy.rbegin(), copy.rend(), std::not1(std::ptr_fun<int, int>(::isspace))).base(), copy.end());
    return std::move(copy);
}

// trim from both ends
Aws::String StringUtils::Trim(const char* source)
{
    return LTrim(RTrim(source).c_str());
}

long long StringUtils::ConvertToInt64(const char* source)
{
    if(!source)
    {
        return 0;
    }

#ifdef __ANDROID__
    return atoll(source);
#else
    return std::atoll(source);
#endif // __ANDROID__
}

long StringUtils::ConvertToInt32(const char* source)
{
    if (!source)
    {
        return 0;
    }

    return std::atol(source);
}

bool StringUtils::ConvertToBool(const char* source)
{
    if(!source)
    {
        return false;
    }

    Aws::String strValue = ToLower(source);
    if(strValue == "true" || strValue == "1")
    {
        return true;
    }

    return false;
}

double StringUtils::ConvertToDouble(const char* source)
{
    if(!source)
    {
        return 0.0;
    }

    return std::strtod(source, NULL);
}

#ifdef _WIN32

Aws::WString StringUtils::ToWString(const char* source)
{
    Aws::WString outString;

    outString.resize(std::strlen(source));
    std::copy(source, source + std::strlen(source), outString.begin());
    return outString;
}

Aws::String StringUtils::FromWString(const wchar_t* source)
{
    Aws::WString inWString(source);

    Aws::String outString(inWString.begin(), inWString.end());
    return outString;
}

#endif

<|endoftext|>


<commit_before>/*
 * SchemeSmobAV.c
 *
 * Scheme small objects (SMOBS) for attention values.
 *
 * Copyright (c) 2008,2009 Linas Vepstas <linas@linas.org>
 */

#ifdef HAVE_GUILE

#include <libguile.h>

#include <opencog/atomspace/AttentionValue.h>
#include <opencog/guile/SchemeSmob.h>

using namespace opencog;

/* ============================================================== */
/**
 * Search for an attention value in a list of values.
 * Return the attention value if found, else return null.
 * Throw errors if the list is not stictly just key-value pairs
 */
AttentionValue * SchemeSmob::get_av_from_list(SCM slist)
{
	while (scm_is_pair(slist))
	{
		SCM sval = SCM_CAR(slist);
		if (SCM_SMOB_PREDICATE(SchemeSmob::cog_misc_tag, sval))
		{
			scm_t_bits misctype = SCM_SMOB_FLAGS(sval);
			switch (misctype)
			{
				case COG_AV:
					return (AttentionValue *) SCM_SMOB_DATA(sval);
				default:
					break;
			}
		}

		slist = SCM_CDR(slist);
	}

	return NULL;
}

/* ============================================================== */

std::string SchemeSmob::av_to_string(const AttentionValue *av)
{
#define BUFLEN 120
	char buff[BUFLEN];

	snprintf(buff, BUFLEN, "(av %d %d %u)",
	         av->getSTI(), av->getLTI(), av->getVLTI());

	std::string ret = buff;
	return ret;
}

/* ============================================================== */
/**
 * Take over memory management of an attention value
 */
SCM SchemeSmob::take_av (AttentionValue *av)
{
	scm_gc_register_collectable_memory (av,
	                 sizeof(*av), "opencog av");

	SCM smob;
	SCM_NEWSMOB (smob, cog_misc_tag, av);
	SCM_SET_SMOB_FLAGS(smob, COG_AV);
	return smob;
}

/* ============================================================== */
/**
 * Create a new attention value, with indicated sti/lti/vlti
 */
SCM SchemeSmob::ss_new_av (SCM ssti, SCM slti, SCM svlti)
{
	if (!scm_is_integer(ssti)) {
		scm_wrong_type_arg_msg("cog-new-av", 1, svlti, "unsigned short");
	}
	if (!scm_is_integer(slti)) {
		scm_wrong_type_arg_msg("cog-new-av", 2, svlti, "unsigned short");
	}
	if (!scm_is_integer(svlti)) {
		scm_wrong_type_arg_msg("cog-new-av", 3, svlti, "unsigned short");
	}
	AttentionValue::sti_t sti = scm_to_short(ssti);
	AttentionValue::lti_t lti = scm_to_short(slti);
    AttentionValue::vlti_t vlti = scm_to_ushort(svlti);
	AttentionValue *av = new AttentionValue(sti, lti, vlti);
	return take_av(av);
}

/* ============================================================== */
/**
 * Return true if the scm is an attention value
 */
SCM SchemeSmob::ss_av_p (SCM s)
{
	if (SCM_SMOB_PREDICATE(SchemeSmob::cog_misc_tag, s))
	{
		scm_t_bits misctype = SCM_SMOB_FLAGS(s);
		switch (misctype)
		{
			case COG_AV:
				return SCM_BOOL_T;

			default:
				return SCM_BOOL_F;
		}
	}
	return SCM_BOOL_F;
}

/* ============================================================== */

AttentionValue * SchemeSmob::verify_av(SCM sav, const char *subrname, int pos)
{
	if (!SCM_SMOB_PREDICATE(SchemeSmob::cog_misc_tag, sav))
		scm_wrong_type_arg_msg(subrname, pos, sav, "opencog attention value");

	scm_t_bits misctype = SCM_SMOB_FLAGS(sav);
	if (COG_AV != misctype)
		scm_wrong_type_arg_msg(subrname, pos, sav, "opencog attention value");

	AttentionValue *av = (AttentionValue *) SCM_SMOB_DATA(sav);
	return av;
}

/**
 * Return association list holding contents of an attention value
 */
SCM SchemeSmob::ss_av_get_value (SCM s)
{
	AttentionValue *av = verify_av(s, "cog-av->alist");

	SCM sti = scm_from_short(av->getSTI());
	SCM lti = scm_from_short(av->getLTI());
	SCM vlti = scm_from_ushort(av->getVLTI());

	SCM ssti = scm_from_locale_symbol("sti");
	SCM slti = scm_from_locale_symbol("lti");
	SCM svlti = scm_from_locale_symbol("vlti");

	SCM rc = SCM_EOL;
	rc = scm_acons(svlti, vlti, rc);
	rc = scm_acons(slti, lti, rc);
	rc = scm_acons(ssti, sti, rc);
	return rc;
}

#endif /* HAVE_GUILE */
/* ===================== END OF FILE ============================ */
<commit_msg>Minor trite bugfix in error reporting<commit_after>/*
 * SchemeSmobAV.c
 *
 * Scheme small objects (SMOBS) for attention values.
 *
 * Copyright (c) 2008,2009 Linas Vepstas <linas@linas.org>
 */

#ifdef HAVE_GUILE

#include <libguile.h>

#include <opencog/atomspace/AttentionValue.h>
#include <opencog/guile/SchemeSmob.h>

using namespace opencog;

/* ============================================================== */
/**
 * Search for an attention value in a list of values.
 * Return the attention value if found, else return null.
 * Throw errors if the list is not stictly just key-value pairs
 */
AttentionValue * SchemeSmob::get_av_from_list(SCM slist)
{
	while (scm_is_pair(slist))
	{
		SCM sval = SCM_CAR(slist);
		if (SCM_SMOB_PREDICATE(SchemeSmob::cog_misc_tag, sval))
		{
			scm_t_bits misctype = SCM_SMOB_FLAGS(sval);
			switch (misctype)
			{
				case COG_AV:
					return (AttentionValue *) SCM_SMOB_DATA(sval);
				default:
					break;
			}
		}

		slist = SCM_CDR(slist);
	}

	return NULL;
}

/* ============================================================== */

std::string SchemeSmob::av_to_string(const AttentionValue *av)
{
#define BUFLEN 120
	char buff[BUFLEN];

	snprintf(buff, BUFLEN, "(av %d %d %u)",
	         av->getSTI(), av->getLTI(), av->getVLTI());

	return buff;
}

/* ============================================================== */
/**
 * Take over memory management of an attention value
 */
SCM SchemeSmob::take_av (AttentionValue *av)
{
	scm_gc_register_collectable_memory (av,
	                 sizeof(*av), "opencog av");

	SCM smob;
	SCM_NEWSMOB (smob, cog_misc_tag, av);
	SCM_SET_SMOB_FLAGS(smob, COG_AV);
	return smob;
}

/* ============================================================== */
/**
 * Create a new attention value, with indicated sti/lti/vlti
 */
SCM SchemeSmob::ss_new_av (SCM ssti, SCM slti, SCM svlti)
{
	if (!scm_is_integer(ssti)) {
		scm_wrong_type_arg_msg("cog-new-av", 1, ssti, "signed short");
	}
	if (!scm_is_integer(slti)) {
		scm_wrong_type_arg_msg("cog-new-av", 2, slti, "signed short");
	}
	if (!scm_is_integer(svlti)) {
		scm_wrong_type_arg_msg("cog-new-av", 3, svlti, "unsigned short");
	}
	AttentionValue::sti_t sti = scm_to_short(ssti);
	AttentionValue::lti_t lti = scm_to_short(slti);
	AttentionValue::vlti_t vlti = scm_to_ushort(svlti);
	AttentionValue *av = new AttentionValue(sti, lti, vlti);
	return take_av(av);
}

/* ============================================================== */
/**
 * Return true if the scm is an attention value
 */
SCM SchemeSmob::ss_av_p (SCM s)
{
	if (SCM_SMOB_PREDICATE(SchemeSmob::cog_misc_tag, s))
	{
		scm_t_bits misctype = SCM_SMOB_FLAGS(s);
		switch (misctype)
		{
			case COG_AV:
				return SCM_BOOL_T;

			default:
				return SCM_BOOL_F;
		}
	}
	return SCM_BOOL_F;
}

/* ============================================================== */

AttentionValue * SchemeSmob::verify_av(SCM sav, const char *subrname, int pos)
{
	if (!SCM_SMOB_PREDICATE(SchemeSmob::cog_misc_tag, sav))
		scm_wrong_type_arg_msg(subrname, pos, sav, "opencog attention value");

	scm_t_bits misctype = SCM_SMOB_FLAGS(sav);
	if (COG_AV != misctype)
		scm_wrong_type_arg_msg(subrname, pos, sav, "opencog attention value");

	AttentionValue *av = (AttentionValue *) SCM_SMOB_DATA(sav);
	return av;
}

/**
 * Return association list holding contents of an attention value
 */
SCM SchemeSmob::ss_av_get_value (SCM s)
{
	AttentionValue *av = verify_av(s, "cog-av->alist");

	SCM sti = scm_from_short(av->getSTI());
	SCM lti = scm_from_short(av->getLTI());
	SCM vlti = scm_from_ushort(av->getVLTI());

	SCM ssti = scm_from_locale_symbol("sti");
	SCM slti = scm_from_locale_symbol("lti");
	SCM svlti = scm_from_locale_symbol("vlti");

	SCM rc = SCM_EOL;
	rc = scm_acons(svlti, vlti, rc);
	rc = scm_acons(slti, lti, rc);
	rc = scm_acons(ssti, sti, rc);
	return rc;
}

#endif /* HAVE_GUILE */
/* ===================== END OF FILE ============================ */
<|endoftext|>


<commit_before>/*
    This file is a part of libcds - Concurrent Data Structures library

    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016

    Source code repo: http://github.com/khizmax/libcds/
    Download: http://sourceforge.net/projects/libcds/files/

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this
      list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "pqueue_type.h"
#include "item.h"

namespace {
    static size_t s_nThreadCount = 8;
    static size_t s_nQueueSize = 2000000;

    class pqueue_pop: public cds_test::stress_fixture
    {
        typedef cds_test::stress_fixture base_class;

    protected:
        template <class PQueue>
        class Producer: public cds_test::thread
        {
            typedef cds_test::thread base_class;

        public:
            Producer( cds_test::thread_pool& pool, PQueue& queue )
                : base_class( pool )
                , m_Queue( queue )
            {}

            Producer( Producer& src )
                : base_class( src )
                , m_Queue( src.m_Queue )
            {}

            virtual thread * clone()
            {
                return new Producer( *this );
            }

            virtual void test()
            {
                typedef typename PQueue::value_type value_type;
                for ( array_type::const_iterator it = m_arr.begin(); it != m_arr.end(); ++it ) {
                    if ( !m_Queue.push( value_type( *it ) ))
                        ++m_nPushError;
                }
            }

            void prepare( size_t nStart, size_t nEnd )
            {
                m_arr.reserve( nEnd - nStart );
                for ( size_t i = nStart; i < nEnd; ++i )
                    m_arr.push_back( i );
                shuffle( m_arr.begin(), m_arr.end() );
            }

        public:
            PQueue&             m_Queue;
            size_t              m_nPushError = 0;

            typedef std::vector<size_t> array_type;
            array_type          m_arr;
        };

        template <class PQueue>
        class Consumer: public cds_test::thread
        {
            typedef cds_test::thread base_class;

        public:
            Consumer( cds_test::thread_pool& pool, PQueue& queue )
                : base_class( pool )
                , m_Queue( queue )
            {}

            Consumer( Consumer& src )
                : base_class( src )
                , m_Queue( src.m_Queue )
            {}

            virtual thread * clone()
            {
                return new Consumer( *this );
            }

            virtual void test()
            {
                typedef typename PQueue::value_type value_type;
                size_t nPrevKey;
                value_type val;
                if ( m_Queue.pop( val )) {
                    ++m_nPopSuccess;
                    nPrevKey = val.key;

                    while ( !m_Queue.empty() ) {
                        if ( m_Queue.pop( val )) {
                            ++m_nPopSuccess;
                            if ( val.key > nPrevKey )
                                ++m_nPopError;
                            else if ( val.key == nPrevKey )
                                ++m_nPopErrorEq;
                            nPrevKey = val.key;
                        }
                        else
                            ++m_nPopFailed;
                    }
                }
                else
                    ++m_nPopFailed;
            }

        public:
            PQueue&             m_Queue;
            size_t              m_nPopError = 0;
            size_t              m_nPopErrorEq = 0;
            size_t              m_nPopSuccess = 0;
            size_t              m_nPopFailed = 0;
        };

    protected:

        template <class PQueue>
        void test( PQueue& q )
        {
            size_t const nThreadItemCount = s_nQueueSize / s_nThreadCount;
            s_nQueueSize = nThreadItemCount * s_nThreadCount;

            cds_test::thread_pool& pool = get_pool();

            propout() << std::make_pair( "thread_count", s_nThreadCount )
                << std::make_pair( "push_count", s_nQueueSize );

            // push
            {
                pool.add( new Producer<PQueue>( pool, q ), s_nThreadCount );

                size_t nStart = 0;
                for ( size_t i = 0; i < pool.size(); ++i ) {
                    static_cast<Producer<PQueue>&>( pool.get(i) ).prepare( nStart, nStart + nThreadItemCount );
                    nStart += nThreadItemCount;
                }

                std::chrono::milliseconds duration = pool.run();
                propout() << std::make_pair( "producer_duration", duration );
            }

            // pop
            {
                pool.clear();
                pool.add( new Consumer<PQueue>( pool, q ), s_nThreadCount );

                std::chrono::milliseconds duration = pool.run();
                propout() << std::make_pair( "consumer_duration", duration );

                // Analyze result
                size_t nTotalPopped = 0;
                size_t nTotalError = 0;
                size_t nTotalErrorEq = 0;
                size_t nTotalFailed = 0;
                for ( size_t i = 0; i < pool.size(); ++i ) {
                    Consumer<PQueue>& cons = static_cast<Consumer<PQueue>&>( pool.get(i));

                    nTotalPopped  += cons.m_nPopSuccess;
                    nTotalError   += cons.m_nPopError;
                    nTotalErrorEq += cons.m_nPopErrorEq;
                    nTotalFailed  += cons.m_nPopFailed;
                }

                propout()
                    << std::make_pair( "total_popped", nTotalPopped )
                    << std::make_pair( "error_pop_double", nTotalErrorEq )
                    << std::make_pair( "error_priority_violation", nTotalError );

                EXPECT_EQ( nTotalPopped, s_nQueueSize );
                EXPECT_EQ( nTotalError, 0 );
                EXPECT_EQ( nTotalErrorEq, 0 );
            }

            propout() << q.statistics();
        }

    public:
        static void SetUpTestCase()
        {
            cds_test::config const& cfg = get_config( "pqueue_pop" );

            s_nThreadCount = cfg.get_size_t( "ThreadCount", s_nThreadCount );
            s_nQueueSize = cfg.get_size_t( "QueueSize", s_nQueueSize );

            if ( s_nThreadCount == 0 )
                s_nThreadCount = 1;
            if ( s_nQueueSize == 0 )
                s_nQueueSize = 1000;
        }

        //static void TearDownTestCase();
    };

#define CDSSTRESS_MSPriorityQueue( fixture_t, pqueue_t ) \
    TEST_F( fixture_t, pqueue_t ) \
    { \
        typedef pqueue::Types<pqueue::simple_value>::pqueue_t pqueue_type; \
        pqueue_type pq( s_nQueueSize ); \
        test( pq ); \
    }
    CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_dyn_less )
    CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_dyn_less_stat )
    CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_dyn_cmp )
    //CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_dyn_mutex ) // too slow

#define CDSSTRESS_MSPriorityQueue_static( fixture_t, pqueue_t ) \
    TEST_F( fixture_t, pqueue_t ) \
    { \
        typedef pqueue::Types<pqueue::simple_value>::pqueue_t pqueue_type; \
        std::unique_ptr< pqueue_type > pq( new pqueue_type ); \
        test( *pq.get() ); \
    }
    //CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_static_less )
    //CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_static_less_stat )
    //CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_static_cmp )
    //CDSSTRESS_MSPriorityQueue( pqueue_pop, 1MSPriorityQueue_static_mutex )

#define CDSSTRESS_PriorityQueue( fixture_t, pqueue_t ) \
    TEST_F( fixture_t, pqueue_t ) \
    { \
        typedef pqueue::Types<pqueue::simple_value>::pqueue_t pqueue_type; \
        pqueue_type pq; \
        test( pq ); \
    }
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_vector )
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_vector_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_deque )
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_deque_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_boost_deque )
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_boost_deque_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_boost_stable_vector )
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_boost_stable_vector_stat )

    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_HP_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_HP_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_HP_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_HP_min_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_DHP_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_DHP_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_DHP_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_DHP_min_stat )
    // CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpi_max )
    // CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpi_max_stat )
    // CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpi_min )
    // CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpi_min_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpb_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpb_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpb_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpb_min_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpt_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpt_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpt_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpt_min_stat )
#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_shb_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_shb_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_shb_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_shb_min_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_sht_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_sht_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_sht_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_sht_min_stat )
#endif

    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_HP_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_HP_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_HP_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_HP_min_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_DHP_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_DHP_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_DHP_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_DHP_min_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpi_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpi_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpb_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpb_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpt_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpt_min )
#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_shb_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_shb_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_sht_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_sht_min )
#endif

    CDSSTRESS_PriorityQueue( pqueue_pop, StdPQueue_vector_spin )
    CDSSTRESS_PriorityQueue( pqueue_pop, StdPQueue_vector_mutex )
    CDSSTRESS_PriorityQueue( pqueue_pop, StdPQueue_deque_spin )
    CDSSTRESS_PriorityQueue( pqueue_pop, StdPQueue_deque_mutex )

} // namespace
<commit_msg>Added more error messages<commit_after>/*
    This file is a part of libcds - Concurrent Data Structures library

    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016

    Source code repo: http://github.com/khizmax/libcds/
    Download: http://sourceforge.net/projects/libcds/files/

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this
      list of conditions and the following disclaimer.

    * Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "pqueue_type.h"
#include "item.h"

namespace {
    static size_t s_nThreadCount = 8;
    static size_t s_nQueueSize = 2000000;

    class pqueue_pop: public cds_test::stress_fixture
    {
        typedef cds_test::stress_fixture base_class;

    protected:
        template <class PQueue>
        class Producer: public cds_test::thread
        {
            typedef cds_test::thread base_class;

        public:
            Producer( cds_test::thread_pool& pool, PQueue& queue )
                : base_class( pool )
                , m_Queue( queue )
            {}

            Producer( Producer& src )
                : base_class( src )
                , m_Queue( src.m_Queue )
            {}

            virtual thread * clone()
            {
                return new Producer( *this );
            }

            virtual void test()
            {
                typedef typename PQueue::value_type value_type;
                for ( array_type::const_iterator it = m_arr.begin(); it != m_arr.end(); ++it ) {
                    if ( !m_Queue.push( value_type( *it ) ))
                        ++m_nPushError;
                }
            }

            void prepare( size_t nStart, size_t nEnd )
            {
                m_arr.reserve( nEnd - nStart );
                for ( size_t i = nStart; i < nEnd; ++i )
                    m_arr.push_back( i );
                shuffle( m_arr.begin(), m_arr.end() );
            }

        public:
            PQueue&             m_Queue;
            size_t              m_nPushError = 0;

            typedef std::vector<size_t> array_type;
            array_type          m_arr;
        };

        template <class PQueue>
        class Consumer: public cds_test::thread
        {
            typedef cds_test::thread base_class;

        public:
            Consumer( cds_test::thread_pool& pool, PQueue& queue )
                : base_class( pool )
                , m_Queue( queue )
            {}

            Consumer( Consumer& src )
                : base_class( src )
                , m_Queue( src.m_Queue )
            {}

            virtual thread * clone()
            {
                return new Consumer( *this );
            }

            virtual void test()
            {
                typedef typename PQueue::value_type value_type;
                size_t nPrevKey;
                value_type val;
                if ( m_Queue.pop( val )) {
                    ++m_nPopSuccess;
                    nPrevKey = val.key;

                    while ( !m_Queue.empty() ) {
                        if ( m_Queue.pop( val )) {
                            ++m_nPopSuccess;
                            if ( val.key > nPrevKey ) {
                                ++m_nPopError;
                                m_arrFailedPops.emplace_back( failed_pops{ nPrevKey, val.key } );
                            }
                            else if ( val.key == nPrevKey ) {
                                ++m_nPopErrorEq;
                                m_arrFailedPops.emplace_back( failed_pops{ nPrevKey, val.key } );
                            }
                            nPrevKey = val.key;
                        }
                        else
                            ++m_nPopFailed;
                    }
                }
                else
                    ++m_nPopFailed;
            }

        public:
            PQueue&             m_Queue;
            size_t              m_nPopError = 0;
            size_t              m_nPopErrorEq = 0;
            size_t              m_nPopSuccess = 0;
            size_t              m_nPopFailed = 0;

            struct failed_pops {
                size_t prev_key;
                size_t popped_key;
            };
            std::vector< failed_pops > m_arrFailedPops;
        };

    protected:

        template <class PQueue>
        void test( PQueue& q )
        {
            size_t const nThreadItemCount = s_nQueueSize / s_nThreadCount;
            s_nQueueSize = nThreadItemCount * s_nThreadCount;

            cds_test::thread_pool& pool = get_pool();

            propout() << std::make_pair( "thread_count", s_nThreadCount )
                << std::make_pair( "push_count", s_nQueueSize );

            // push
            {
                pool.add( new Producer<PQueue>( pool, q ), s_nThreadCount );

                size_t nStart = 0;
                for ( size_t i = 0; i < pool.size(); ++i ) {
                    static_cast<Producer<PQueue>&>( pool.get(i) ).prepare( nStart, nStart + nThreadItemCount );
                    nStart += nThreadItemCount;
                }

                std::chrono::milliseconds duration = pool.run();
                propout() << std::make_pair( "producer_duration", duration );
            }

            // pop
            {
                pool.clear();
                pool.add( new Consumer<PQueue>( pool, q ), s_nThreadCount );

                std::chrono::milliseconds duration = pool.run();
                propout() << std::make_pair( "consumer_duration", duration );

                // Analyze result
                size_t nTotalPopped = 0;
                size_t nTotalError = 0;
                size_t nTotalErrorEq = 0;
                size_t nTotalFailed = 0;
                for ( size_t i = 0; i < pool.size(); ++i ) {
                    Consumer<PQueue>& cons = static_cast<Consumer<PQueue>&>( pool.get(i));

                    nTotalPopped  += cons.m_nPopSuccess;
                    nTotalError   += cons.m_nPopError;
                    nTotalErrorEq += cons.m_nPopErrorEq;
                    nTotalFailed  += cons.m_nPopFailed;

                    if ( !cons.m_arrFailedPops.empty() ) {
                        std::cerr << "Failed pop:";
                        for ( size_t k = 0; k < cons.m_arrFailedPops.size(); ++k ) {
                            std::cerr << "\nThread " << i << ": prev_key=" << cons.m_arrFailedPops[k].prev_key << " popped_key=" << cons.m_arrFailedPops[k].popped_key;
                        }
                        std::cerr << std::endl;
                    }
                }

                propout()
                    << std::make_pair( "total_popped", nTotalPopped )
                    << std::make_pair( "error_pop_double", nTotalErrorEq )
                    << std::make_pair( "error_priority_violation", nTotalError );

                EXPECT_EQ( nTotalPopped, s_nQueueSize );
                EXPECT_EQ( nTotalError, 0 );
                EXPECT_EQ( nTotalErrorEq, 0 );
            }

            propout() << q.statistics();
        }

    public:
        static void SetUpTestCase()
        {
            cds_test::config const& cfg = get_config( "pqueue_pop" );

            s_nThreadCount = cfg.get_size_t( "ThreadCount", s_nThreadCount );
            s_nQueueSize = cfg.get_size_t( "QueueSize", s_nQueueSize );

            if ( s_nThreadCount == 0 )
                s_nThreadCount = 1;
            if ( s_nQueueSize == 0 )
                s_nQueueSize = 1000;
        }

        //static void TearDownTestCase();
    };

#define CDSSTRESS_MSPriorityQueue( fixture_t, pqueue_t ) \
    TEST_F( fixture_t, pqueue_t ) \
    { \
        typedef pqueue::Types<pqueue::simple_value>::pqueue_t pqueue_type; \
        pqueue_type pq( s_nQueueSize ); \
        test( pq ); \
    }
    CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_dyn_less )
    CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_dyn_less_stat )
    CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_dyn_cmp )
    //CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_dyn_mutex ) // too slow

#define CDSSTRESS_MSPriorityQueue_static( fixture_t, pqueue_t ) \
    TEST_F( fixture_t, pqueue_t ) \
    { \
        typedef pqueue::Types<pqueue::simple_value>::pqueue_t pqueue_type; \
        std::unique_ptr< pqueue_type > pq( new pqueue_type ); \
        test( *pq.get() ); \
    }
    //CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_static_less )
    //CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_static_less_stat )
    //CDSSTRESS_MSPriorityQueue( pqueue_pop, MSPriorityQueue_static_cmp )
    //CDSSTRESS_MSPriorityQueue( pqueue_pop, 1MSPriorityQueue_static_mutex )

#define CDSSTRESS_PriorityQueue( fixture_t, pqueue_t ) \
    TEST_F( fixture_t, pqueue_t ) \
    { \
        typedef pqueue::Types<pqueue::simple_value>::pqueue_t pqueue_type; \
        pqueue_type pq; \
        test( pq ); \
    }
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_vector )
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_vector_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_deque )
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_deque_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_boost_deque )
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_boost_deque_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_boost_stable_vector )
    CDSSTRESS_PriorityQueue( pqueue_pop, FCPQueue_boost_stable_vector_stat )

    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_HP_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_HP_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_HP_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_HP_min_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_DHP_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_DHP_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_DHP_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_DHP_min_stat )
    // CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpi_max )
    // CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpi_max_stat )
    // CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpi_min )
    // CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpi_min_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpb_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpb_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpb_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpb_min_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpt_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpt_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpt_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_gpt_min_stat )
#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_shb_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_shb_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_shb_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_shb_min_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_sht_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_sht_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_sht_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, EllenBinTree_RCU_sht_min_stat )
#endif

    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_HP_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_HP_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_HP_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_HP_min_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_DHP_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_DHP_max_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_DHP_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_DHP_min_stat )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpi_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpi_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpb_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpb_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpt_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_gpt_min )
#ifdef CDS_URCU_SIGNAL_HANDLING_ENABLED
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_shb_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_shb_min )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_sht_max )
    CDSSTRESS_PriorityQueue( pqueue_pop, SkipList_RCU_sht_min )
#endif

    CDSSTRESS_PriorityQueue( pqueue_pop, StdPQueue_vector_spin )
    CDSSTRESS_PriorityQueue( pqueue_pop, StdPQueue_vector_mutex )
    CDSSTRESS_PriorityQueue( pqueue_pop, StdPQueue_deque_spin )
    CDSSTRESS_PriorityQueue( pqueue_pop, StdPQueue_deque_mutex )

} // namespace
<|endoftext|>