<commit_before>/*
 * avs2wav main.cpp
 *  extract audio data as RIFF WAV format, from avs file
 *
 *  Copyright (C) 2010 janus_wel<janus.wel.3@gmail.com>
 *  see LICENSE for redistributing, modifying, and so on.
 * */

#include "avs2wav.hpp"
#include "main.hpp"

#include "../../include/avsutil.hpp"

#include "../../helper/elapsed.hpp"
#include "../../helper/io.hpp"
#include "../../helper/wav.hpp"

#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <locale>
#include <memory>   // fot std::auto_ptr
#include <stdexcept>
#include <string>
#include <vector>

// using namespaces
using namespace std;
using namespace avsutil;

// forward declarations
// output audio informations
ostream& operator <<(ostream&, const audio_type::info_type&);

int Main::main(void) {
    // constants
    const unsigned int header_width = 24;

    if (inputfile.empty()) {
        throw avs2wav_error(BAD_ARGUMENT, "Specify <inputfile>\n");
    }

    // read in avs file
    avs_type& avs = manager().load(inputfile.c_str());
    if (!avs.is_fine()) {
        throw avs2wav_error(BAD_AVS, avs.errmsg());
    }

    // get audio stream
    audio_type& audio = avs.audio();
    const audio_type::info_type& info = audio.info();

    if (!info.exists) {
        throw avs2wav_error(BAD_AVS,
                "Specified file has no audio stream: " + inputfile);
    }

    // preparations
    // output and information stream (to stdout for now)
    ostream targetout(cout.rdbuf());
    ostream infoout(cout.rdbuf());

    // settings for infoout and targetout
    // this is true if redirected to file or connected to pipe
    if (!util::io::is_redirected()) {
        // if output to file

        // set output filename if it isn't decided still
        if (outputfile.empty()) outputfile.assign(inputfile).append(".wav");

        // create filebuf and set it output stream
        filebuf* fbuf = new filebuf;
        fbuf->open(outputfile.c_str(), ios::out | ios::binary | ios::trunc);
        if (!fbuf->is_open()) {
            cerr << "Can't open file to write: " << outputfile << endl;
            return UNKNOWN;
        }

        // set filebuf to output stream
        targetout.rdbuf(fbuf);
    }
    else {
        // if output to stdout

        // only to show
        outputfile.assign("stdout");
        // use stderr to show a progress of the process and informations of avs
        infoout.rdbuf(cerr.rdbuf());
        // set stdout to binary mode (Windows only)
        util::io::set_stdout_binary();
    }

    // showing informations
    infoout << left
        << setw(header_width) << "source:"              << inputfile << "\n"
        << setw(header_width) << "destination:"         << outputfile << "\n"
        << setw(header_width) << "buffers for output:"  << buf_size << " bytes\n"
        << info;

    // Applying manipulators to the stream to show informations.
    infoout << fixed << setprecision(2);

    // writing wav header
    format::riff_wav::elements_type elements = {
        info.channels,
        info.bit_depth,
        static_cast<uint32_t>(info.numof_samples),
        info.sampling_rate
    };
    format::riff_wav::header_type header(elements);
    targetout << header;

    // allocate buffer
    std::vector<char> buffer(buf_size);
    buffer.reserve(buf_size);
    char* buf = &buffer[0];
    std::istream& ain = audio.stream();

    // preparations for copying audio samples
    const unsigned int block_size = info.block_size;
    uint64_t numerator = 0;
    const uint64_t denominator = info.numof_samples;
    double percentage = 0;
    util::time::elapsed elapsed;
    // go!!
    while (ain.good()) {
        // read and write
        ain.read(buf, buf_size);
        targetout.write(buf, ain.gcount());

        // calculations to show progresses
        numerator += ain.gcount() / block_size;
        percentage = static_cast<double>(numerator) * 100 / denominator;

        // showing progresses
        infoout
            << "\r"
            << numerator << "/" << denominator << " samples"
            << " (" << percentage << "%)"
            << " elapsed " << elapsed() << " sec";
    }

    infoout
        << "\n\ndone.\n"
        << endl;

    return OK;
}

ostream& operator <<(ostream& out, const audio_type::info_type& info) {
    // constants
    static const unsigned int header_width = 18;

    // preparations
    string channels;
    switch (info.channels) {
        case 1: channels = "mono";   break;
        case 2: channels = "stereo"; break;
        case 6: channels = "5.1ch";  break;
        default:
            channels.assign(tconv.strfrom(info.channels)).append("ch");
            break;
    }
    float sampling_rate = static_cast<float>(info.sampling_rate) / 1000;

    // instantiate new ostream object and set streambuf of "out" to it
    // in order to save the formattings of "out"
    ostream o(out.rdbuf());
    o << left << setfill('.')
        << "\n"
        << setw(header_width) << "bit depth "     << ' ' << info.bit_depth << "bit\n"
        << setw(header_width) << "channels "      << ' ' << channels << "\n"
        << setw(header_width) << "sampling rate " << ' ' << sampling_rate << "kHz\n"
        << endl;

    return out;
}

int main(const int argc, const char* argv[]) {
    try {
        std::locale::global(std::locale(""));
        Main main;
        main.analyze_option(argc, argv);
        main.preparation();
        return main.start();
    }
    catch (const avs2wav_error& ex) {
        std::cerr << ex.what() << std::endl;
        if (ex.return_value() == BAD_ARGUMENT) usage(std::cerr);
        return ex.return_value();
    }
    catch (const std::exception& ex) {
        std::cerr << "error: " << ex.what() << std::endl;
        return UNKNOWN;
    }
}

<commit_msg>Imbue the classic locale to ostreams<commit_after>/*
 * avs2wav main.cpp
 *  extract audio data as RIFF WAV format, from avs file
 *
 *  Copyright (C) 2010 janus_wel<janus.wel.3@gmail.com>
 *  see LICENSE for redistributing, modifying, and so on.
 * */

#include "avs2wav.hpp"
#include "main.hpp"

#include "../../include/avsutil.hpp"

#include "../../helper/elapsed.hpp"
#include "../../helper/io.hpp"
#include "../../helper/wav.hpp"

#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <locale>
#include <memory>   // fot std::auto_ptr
#include <stdexcept>
#include <string>
#include <vector>

// using namespaces
using namespace std;
using namespace avsutil;

// forward declarations
// output audio informations
ostream& operator <<(ostream&, const audio_type::info_type&);

int Main::main(void) {
    // constants
    const unsigned int header_width = 24;

    if (inputfile.empty()) {
        throw avs2wav_error(BAD_ARGUMENT, "Specify <inputfile>\n");
    }

    // read in avs file
    avs_type& avs = manager().load(inputfile.c_str());
    if (!avs.is_fine()) {
        throw avs2wav_error(BAD_AVS, avs.errmsg());
    }

    // get audio stream
    audio_type& audio = avs.audio();
    const audio_type::info_type& info = audio.info();

    if (!info.exists) {
        throw avs2wav_error(BAD_AVS,
                "Specified file has no audio stream: " + inputfile);
    }

    // preparations
    // output and information stream (to stdout for now)
    ostream targetout(cout.rdbuf());
    ostream infoout(cout.rdbuf());
    targetout.imbue(std::locale::classic());
    infoout.imbue(std::locale::classic());

    // settings for infoout and targetout
    // this is true if redirected to file or connected to pipe
    if (!util::io::is_redirected()) {
        // if output to file

        // set output filename if it isn't decided still
        if (outputfile.empty()) outputfile.assign(inputfile).append(".wav");

        // create filebuf and set it output stream
        filebuf* fbuf = new filebuf;
        fbuf->open(outputfile.c_str(), ios::out | ios::binary | ios::trunc);
        if (!fbuf->is_open()) {
            cerr << "Can't open file to write: " << outputfile << endl;
            return UNKNOWN;
        }

        // set filebuf to output stream
        targetout.rdbuf(fbuf);
    }
    else {
        // if output to stdout

        // only to show
        outputfile.assign("stdout");
        // use stderr to show a progress of the process and informations of avs
        infoout.rdbuf(cerr.rdbuf());
        // set stdout to binary mode (Windows only)
        util::io::set_stdout_binary();
    }

    // showing informations
    infoout << left
        << setw(header_width) << "source:"              << inputfile << "\n"
        << setw(header_width) << "destination:"         << outputfile << "\n"
        << setw(header_width) << "buffers for output:"  << buf_size << " bytes\n"
        << info;

    // Applying manipulators to the stream to show informations.
    infoout << fixed << setprecision(2);

    // writing wav header
    format::riff_wav::elements_type elements = {
        info.channels,
        info.bit_depth,
        static_cast<uint32_t>(info.numof_samples),
        info.sampling_rate
    };
    format::riff_wav::header_type header(elements);
    targetout << header;

    // allocate buffer
    std::vector<char> buffer(buf_size);
    buffer.reserve(buf_size);
    char* buf = &buffer[0];
    std::istream& ain = audio.stream();

    // preparations for copying audio samples
    const unsigned int block_size = info.block_size;
    uint64_t numerator = 0;
    const uint64_t denominator = info.numof_samples;
    double percentage = 0;
    util::time::elapsed elapsed;
    // go!!
    while (ain.good()) {
        // read and write
        ain.read(buf, buf_size);
        targetout.write(buf, ain.gcount());

        // calculations to show progresses
        numerator += ain.gcount() / block_size;
        percentage = static_cast<double>(numerator) * 100 / denominator;

        // showing progresses
        infoout
            << "\r"
            << numerator << "/" << denominator << " samples"
            << " (" << percentage << "%)"
            << " elapsed " << elapsed() << " sec";
    }

    infoout
        << "\n\ndone.\n"
        << endl;

    return OK;
}

ostream& operator <<(ostream& out, const audio_type::info_type& info) {
    // constants
    static const unsigned int header_width = 18;

    // preparations
    string channels;
    switch (info.channels) {
        case 1: channels = "mono";   break;
        case 2: channels = "stereo"; break;
        case 6: channels = "5.1ch";  break;
        default:
            channels.assign(tconv.strfrom(info.channels)).append("ch");
            break;
    }
    float sampling_rate = static_cast<float>(info.sampling_rate) / 1000;

    // instantiate new ostream object and set streambuf of "out" to it
    // in order to save the formattings of "out"
    ostream o(out.rdbuf());
    o << left << setfill('.')
        << "\n"
        << setw(header_width) << "bit depth "     << ' ' << info.bit_depth << "bit\n"
        << setw(header_width) << "channels "      << ' ' << channels << "\n"
        << setw(header_width) << "sampling rate " << ' ' << sampling_rate << "kHz\n"
        << endl;

    return out;
}

int main(const int argc, const char* argv[]) {
    try {
        std::locale::global(std::locale(""));
        Main main;
        main.analyze_option(argc, argv);
        main.preparation();
        return main.start();
    }
    catch (const avs2wav_error& ex) {
        std::cerr << ex.what() << std::endl;
        if (ex.return_value() == BAD_ARGUMENT) usage(std::cerr);
        return ex.return_value();
    }
    catch (const std::exception& ex) {
        std::cerr << "error: " << ex.what() << std::endl;
        return UNKNOWN;
    }
}

<|endoftext|>


<commit_before>#include <supplesearch/engine.hpp>
#include <supplesearch/databases/text.hpp>
#include <supplesearch/measures/cosine.hpp>

#include <supplesearch/algorithms/inverse_document_frequency.hpp>
#include <supplesearch/algorithms/covariance_matrix.hpp>
#include <supplesearch/algorithms/lsi.hpp>

#include <iomanip>
#include <iostream>

using namespace SuppleSearch;

int main(int argc, char** argv)
{
  if (argc < 4) {
    std::cout << "Usage: ss database keywords query" << std::endl;
    return 1;
  }

  Databases::Text::shared db(Databases::Text::build(argv[1]));
  Databases::Text::shared keywords(Databases::Text::build(argv[2]));
  Measure::shared measure(new Measures::Cosine());
  Algorithms::TFIDF::shared tfidf(new Algorithms::LSI(0.75));
  Engine engine(db, keywords, tfidf, measure);
  Algorithms::CovarianceMatrix covariance_matrix(db, keywords);

  // Algorithms::InverseDocumentFrequency idf(db);
  // auto qt = idf.process(engine.keywords());
  // int i = 0;
  // for (auto stem : engine.keywords()) {
  //   std::cout << qt(i++) << "\t" << stem << std::endl;
  // }

  auto query = db->build_document("query", argv[3]);
  auto results = engine.query(query);

  std::cout << "Results for \"" << argv[3] << "\"";

  if (argc == 5) {
    auto proposed_queries = covariance_matrix.process(query, 10, std::stoul(argv[4]));

    std::cout << " (consider ";
    size_t max_queries = proposed_queries.size() > 10 ? 10 : proposed_queries.size();
    for (size_t i = 0; i < max_queries; i++) {
      std::cout << "\"" << argv[3] << ' ' << proposed_queries[i].second->content() << "\" [" << std::setprecision(4) << proposed_queries[i].first << "] ";
    }
    std::cout << ")";
  }

  std::cout << ":" << std::endl << std::endl;

  for (auto result : results) {
    if (!isnan(result.first) && (result.first > 0)) {
      std::cout << std::setw(8) << std::setprecision(6) << result.first << "\t" << result.second->title() << std::endl << "--------" << std::endl;
      std::cout << result.second->content();
      for (auto stem : result.second->stemmed_content()) {
        std::cout << stem << ' ';
      }
      std::cout << std::endl << std::endl << std::endl;
    }
  }

  return 0;
}
<commit_msg>added preciosn from cmdline<commit_after>#include <supplesearch/engine.hpp>
#include <supplesearch/databases/text.hpp>
#include <supplesearch/measures/cosine.hpp>

#include <supplesearch/algorithms/inverse_document_frequency.hpp>
#include <supplesearch/algorithms/covariance_matrix.hpp>
#include <supplesearch/algorithms/lsi.hpp>

#include <iomanip>
#include <iostream>

using namespace SuppleSearch;

int main(int argc, char** argv)
{
  if (argc < 5) {
    std::cout << "Usage: ss database keywords query precision extra" << std::endl;
    return 1;
  }

  double precision = std::stof(argv[4]);

  Databases::Text::shared db(Databases::Text::build(argv[1]));
  Databases::Text::shared keywords(Databases::Text::build(argv[2]));
  Measure::shared measure(new Measures::Cosine());
  Algorithms::TFIDF::shared tfidf(precision < 1.0 ? new Algorithms::LSI(precision) : new Algorithms::TFIDF());
  Engine engine(db, keywords, tfidf, measure);
  Algorithms::CovarianceMatrix covariance_matrix(db, keywords);

  auto query = db->build_document("query", argv[3]);
  auto results = engine.query(query);

  std::cout << "Results for \"" << argv[3] << "\"";

  if (argc == 6) {
    auto proposed_queries = covariance_matrix.process(query, 10, std::stoul(argv[5]));

    std::cout << " (consider ";
    size_t max_queries = proposed_queries.size() > 10 ? 10 : proposed_queries.size();
    for (size_t i = 0; i < max_queries; i++) {
      std::cout << "\"" << argv[3] << ' ' << proposed_queries[i].second->content() << "\" [" << std::setprecision(4) << proposed_queries[i].first << "] ";
    }
    std::cout << ")";
  }

  std::cout << ":" << std::endl << std::endl;

  for (auto result : results) {
    if (!isnan(result.first) && (result.first > 0)) {
      std::cout << std::setw(8) << std::setprecision(6) << result.first << "\t" << result.second->title() << std::endl << "--------" << std::endl;
      std::cout << result.second->content();
      for (auto stem : result.second->stemmed_content()) {
        std::cout << stem << ' ';
      }
      std::cout << std::endl << std::endl << std::endl;
    }
  }

  return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * 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: Ali Saidi
 */

#include <string>

#include "arch/sparc/vtophys.hh"
#include "arch/sparc/tlb.hh"
#include "base/compiler.hh"
#include "base/chunk_generator.hh"
#include "base/trace.hh"
#include "cpu/thread_context.hh"
#include "mem/vport.hh"

using namespace std;

namespace SparcISA
{
    Addr vtophys(Addr vaddr)
    {
        // In SPARC it's almost always impossible to turn a VA->PA w/o a context
        // The only times we can kinda do it are if we have a SegKPM mapping
        // and can find the real address in the tlb or we have a physical
        // adddress already (beacuse we are looking at the hypervisor)
        // Either case is rare, so we'll just panic.

        panic("vtophys() without context on SPARC largly worthless\n");
        M5_DUMMY_RETURN
    }

    Addr vtophys(ThreadContext *tc, Addr addr)
    {
        // Here we have many options and are really implementing something like
        // a fill handler to find the address since there isn't a multilevel
        // table for us to walk around.
        //
        // 1. We are currently hyperpriv, return the address unmodified
        // 2. The mmu is off return(ra->pa)
        // 3. We are currently priv, use ctx0* tsbs to find the page
        // 4. We are not priv, use ctxN0* tsbs to find the page
        // For all accesses we check the tlbs first since it's possible that
        // long standing pages (e.g. locked kernel mappings) won't be in the tsb
        uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA);

        bool hpriv = bits(tlbdata,0,0);
        //bool priv = bits(tlbdata,2,2);
        bool addr_mask = bits(tlbdata,3,3);
        bool data_real = !bits(tlbdata,5,5);
        bool inst_real = !bits(tlbdata,4,4);
        bool ctx_zero  = bits(tlbdata,18,16) > 0;
        int part_id = bits(tlbdata,15,8);
        int pri_context = bits(tlbdata,47,32);
        //int sec_context = bits(tlbdata,63,48);

        FunctionalPort *mem = tc->getPhysPort();
        ITB* itb = tc->getITBPtr();
        DTB* dtb = tc->getDTBPtr();
        TlbEntry* tbe;
        PageTableEntry pte;
        Addr tsbs[4];
        Addr va_tag;
        TteTag ttetag;

        if (hpriv)
            return addr;

        if (addr_mask)
            addr = addr & VAddrAMask;

        tbe = dtb->lookup(addr, part_id, data_real, ctx_zero ? 0 : pri_context , false);
        if (tbe) goto foundtbe;

        tbe = itb->lookup(addr, part_id, inst_real, ctx_zero ? 0 : pri_context, false);
        if (tbe) goto foundtbe;

        // We didn't find it in the tlbs, so lets look at the TSBs
        dtb->GetTsbPtr(tc, addr, ctx_zero ? 0 : pri_context, tsbs);
        va_tag = bits(addr, 63, 22);
        for (int x = 0; x < 4; x++) {
            ttetag = betoh(mem->read<uint64_t>(tsbs[x]));
            if (ttetag.valid() && ttetag.va() == va_tag) {
                pte.populate(betoh(mem->read<uint64_t>(tsbs[x]) + sizeof(uint64_t)),
                        PageTableEntry::sun4v); // I think it's sun4v at least!
                DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TTE\n", addr,
                        pte.paddrMask() | addr & pte.sizeMask());
                goto foundpte;
            }
        }
        panic("couldn't translate %#x\n", addr);

foundtbe:
        pte = tbe->pte;
        DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TLB\n", addr,
                pte.paddrMask() | addr & pte.sizeMask());
foundpte:
        return pte.paddrMask() | addr & pte.sizeMask();
    }
}
<commit_msg>style: bring this file into M5 style, use the new pte translate function.<commit_after>/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * 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: Ali Saidi
 */

#include <string>

#include "arch/sparc/vtophys.hh"
#include "arch/sparc/tlb.hh"
#include "base/compiler.hh"
#include "base/chunk_generator.hh"
#include "base/trace.hh"
#include "cpu/thread_context.hh"
#include "mem/vport.hh"

using namespace std;

namespace SparcISA {

Addr
vtophys(Addr vaddr)
{
    // In SPARC it's almost always impossible to turn a VA->PA w/o a
    // context The only times we can kinda do it are if we have a
    // SegKPM mapping and can find the real address in the tlb or we
    // have a physical adddress already (beacuse we are looking at the
    // hypervisor) Either case is rare, so we'll just panic.

    panic("vtophys() without context on SPARC largly worthless\n");
    M5_DUMMY_RETURN;
}

Addr
vtophys(ThreadContext *tc, Addr addr)
{
    // Here we have many options and are really implementing something like
    // a fill handler to find the address since there isn't a multilevel
    // table for us to walk around.
    //
    // 1. We are currently hyperpriv, return the address unmodified
    // 2. The mmu is off return(ra->pa)
    // 3. We are currently priv, use ctx0* tsbs to find the page
    // 4. We are not priv, use ctxN0* tsbs to find the page
    // For all accesses we check the tlbs first since it's possible that
    // long standing pages (e.g. locked kernel mappings) won't be in the tsb
    uint64_t tlbdata = tc->readMiscRegNoEffect(MISCREG_TLB_DATA);

    bool hpriv = bits(tlbdata,0,0);
    //bool priv = bits(tlbdata,2,2);
    bool addr_mask = bits(tlbdata,3,3);
    bool data_real = !bits(tlbdata,5,5);
    bool inst_real = !bits(tlbdata,4,4);
    bool ctx_zero  = bits(tlbdata,18,16) > 0;
    int part_id = bits(tlbdata,15,8);
    int pri_context = bits(tlbdata,47,32);
    //int sec_context = bits(tlbdata,63,48);

    FunctionalPort *mem = tc->getPhysPort();
    ITB* itb = tc->getITBPtr();
    DTB* dtb = tc->getDTBPtr();
    TlbEntry* tbe;
    PageTableEntry pte;
    Addr tsbs[4];
    Addr va_tag;
    TteTag ttetag;

    if (hpriv)
        return addr;

    if (addr_mask)
        addr = addr & VAddrAMask;

    tbe = dtb->lookup(addr, part_id, data_real, ctx_zero ? 0 : pri_context ,
                      false);
    if (tbe)
        goto foundtbe;

    tbe = itb->lookup(addr, part_id, inst_real, ctx_zero ? 0 : pri_context,
                      false);
    if (tbe)
        goto foundtbe;

    // We didn't find it in the tlbs, so lets look at the TSBs
    dtb->GetTsbPtr(tc, addr, ctx_zero ? 0 : pri_context, tsbs);
    va_tag = bits(addr, 63, 22);
    for (int x = 0; x < 4; x++) {
        ttetag = betoh(mem->read<uint64_t>(tsbs[x]));
        if (ttetag.valid() && ttetag.va() == va_tag) {
            uint64_t entry = mem->read<uint64_t>(tsbs[x]) + sizeof(uint64_t);
            // I think it's sun4v at least!
            pte.populate(betoh(entry), PageTableEntry::sun4v);
            DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TTE\n",
                    addr, pte.translate(addr));
            goto foundpte;
        }
    }
    panic("couldn't translate %#x\n", addr);

  foundtbe:
    pte = tbe->pte;
    DPRINTF(VtoPhys, "Virtual(%#x)->Physical(%#x) found in TLB\n", addr,
            pte.translate(addr));
  foundpte:
    return pte.translate(addr);
}

} /* namespace SparcISA */
<|endoftext|>


<commit_before>// SensorList.cc

#include "lib.h"
#include "log.h"
#include "SensorList.h"
#include "Sensor.h"
#include "Command.h"

#include "StateSensor.h"
#include "PacketSensor.h"
#include "DelaySensor.h"
#include "MinDelaySensor.h"
#include "MaxDelaySensor.h"
#include "ThroughputSensor.h"
#include "EwmaThroughputSensor.h"

using namespace std;

SensorList::SensorList()
{
  reset();
}

SensorList::SensorList(SensorList const & right)
{
  if (right.head.get() != NULL)
  {
    logWrite(ERROR, "SensorList copy constructed after setup. "
             "This shouldn't have been able to happen. "
             "Sensors have been lost.");
  }
  reset();
}

SensorList & SensorList::operator=(SensorList const & right)
{
  if (this != &right)
  {
    if (right.head.get() != NULL)
    {
      logWrite(ERROR, "SensorList assigned after setup. "
               "This shouldn't have been able to happen. "
               "Sensors have been lost.");
    }
    reset();
  }
  return *this;
}

void SensorList::addSensor(SensorCommand const & newSensor)
{
  // Add dependency type demux here.
  switch(newSensor.type)
  {
  case NULL_SENSOR:
    pushNullSensor();
    break;
  case STATE_SENSOR:
    pushStateSensor();
    break;
  case PACKET_SENSOR:
    pushPacketSensor();
    break;
  case DELAY_SENSOR:
    pushDelaySensor();
    break;
  case MIN_DELAY_SENSOR:
    pushMinDelaySensor();
    break;
  case MAX_DELAY_SENSOR:
    pushMaxDelaySensor();
    break;
  case THROUGHPUT_SENSOR:
    pushThroughputSensor();
    break;
  case EWMA_THROUGHPUT_SENSOR:
    pushEwmaThroughputSensor();
    break;
  default:
    logWrite(ERROR,
             "Incorrect sensor type (%d). Ignoring add sensor command.",
             newSensor.type);
    break;
  }
}

Sensor * SensorList::getHead(void)
{
  return head.get();
}

void SensorList::reset(void)
{
  head.reset(NULL);
  tail = NULL;
  // Dependency = NULL here
  depNullSensor = NULL;
  depStateSensor = NULL;
  depPacketSensor = NULL;
  depDelaySensor = NULL;
  depThroughputSensor = NULL;
  depMinDelaySensor = NULL;
}

void SensorList::pushSensor(std::auto_ptr<Sensor> newSensor)
{
  if (tail != NULL)
  {
    tail->addNode(newSensor);
    tail = tail->getTail();
  }
  else
  {
    head = newSensor;
    tail = head.get();
  }
}

// Add individual pushSensor functions here.

void SensorList::pushNullSensor(void)
{
  // Dependency list

  // Example dependency check
  if (depNullSensor == NULL)
  {
    logWrite(SENSOR, "Adding NullSensor");
    NullSensor * newSensor = new NullSensor();
    std::auto_ptr<Sensor> current(newSensor);
    pushSensor(current);

    // Example dependency set
    depNullSensor = newSensor;
  }
}

void SensorList::pushStateSensor(void)
{
  // Dependency list
  pushNullSensor();

  // Dependency check
  if (depStateSensor == NULL)
  {
    logWrite(SENSOR, "Adding StateSensor");
    StateSensor * newSensor = new StateSensor();
    std::auto_ptr<Sensor> current(newSensor);
    pushSensor(current);

    // Dependency set
    depStateSensor = newSensor;
  }
}

void SensorList::pushPacketSensor(void)
{
  // Dependency list
  pushStateSensor();

  // Example dependency check
  if (depPacketSensor == NULL)
  {
    logWrite(SENSOR, "Adding PacketSensor");
    PacketSensor * newSensor = new PacketSensor(depStateSensor);
    std::auto_ptr<Sensor> current(newSensor);
    pushSensor(current);

    // Example dependency set
    depPacketSensor = newSensor;
  }
}

void SensorList::pushDelaySensor(void)
{
  // Dependency list
  pushStateSensor();
  pushPacketSensor();

  // Example dependency check
  if (depDelaySensor == NULL)
  {
    logWrite(SENSOR, "Adding DelaySensor");
    DelaySensor * newSensor = new DelaySensor(depPacketSensor, depStateSensor);
    std::auto_ptr<Sensor> current(newSensor);
    pushSensor(current);

    // Example dependency set
    depDelaySensor = newSensor;
  }
}

void SensorList::pushMinDelaySensor(void)
{
  // Dependency list
  pushDelaySensor();

  if (depMinDelaySensor == NULL) {
      logWrite(SENSOR, "Adding MinDelaySensor");
      MinDelaySensor * newSensor = new MinDelaySensor(depDelaySensor);
      std::auto_ptr<Sensor> current(newSensor);
      pushSensor(current);

      // Dependency set
      depMinDelaySensor = newSensor;
  }

}

void SensorList::pushMaxDelaySensor(void)
{
  // Dependency list
  pushMinDelaySensor();
  pushDelaySensor();
  pushStateSensor();

  logWrite(SENSOR, "Adding MaxDelaySensor");
  std::auto_ptr<Sensor> current(new MaxDelaySensor(depDelaySensor,
                                                   depStateSensor,
                                                   depMinDelaySensor));
  pushSensor(current);
}

void SensorList::pushThroughputSensor(void)
{
  // Dependency list
  pushStateSensor();
  pushPacketSensor();

  // Example dependency check
  if (depThroughputSensor == NULL)
  {
    logWrite(SENSOR, "Adding ThroughputSensor");
    ThroughputSensor * newSensor = new ThroughputSensor(depPacketSensor,
                                                        depStateSensor);
    std::auto_ptr<Sensor> current(newSensor);
    pushSensor(current);

    // Example dependency set
    depThroughputSensor = newSensor;
  }
}

void SensorList::pushEwmaThroughputSensor(void)
{
  // Dependency list
  pushStateSensor();
  pushThroughputSensor();

  logWrite(SENSOR, "Adding EwmaThroughputSensor");
  std::auto_ptr<Sensor> current(new EwmaThroughputSensor(depThroughputSensor,
                                                         depStateSensor));
  pushSensor(current);
}
<commit_msg>Oops, got left out of my last commit - MaxDelay now depends on PacketSensor<commit_after>// SensorList.cc

#include "lib.h"
#include "log.h"
#include "SensorList.h"
#include "Sensor.h"
#include "Command.h"

#include "StateSensor.h"
#include "PacketSensor.h"
#include "DelaySensor.h"
#include "MinDelaySensor.h"
#include "MaxDelaySensor.h"
#include "ThroughputSensor.h"
#include "EwmaThroughputSensor.h"

using namespace std;

SensorList::SensorList()
{
  reset();
}

SensorList::SensorList(SensorList const & right)
{
  if (right.head.get() != NULL)
  {
    logWrite(ERROR, "SensorList copy constructed after setup. "
             "This shouldn't have been able to happen. "
             "Sensors have been lost.");
  }
  reset();
}

SensorList & SensorList::operator=(SensorList const & right)
{
  if (this != &right)
  {
    if (right.head.get() != NULL)
    {
      logWrite(ERROR, "SensorList assigned after setup. "
               "This shouldn't have been able to happen. "
               "Sensors have been lost.");
    }
    reset();
  }
  return *this;
}

void SensorList::addSensor(SensorCommand const & newSensor)
{
  // Add dependency type demux here.
  switch(newSensor.type)
  {
  case NULL_SENSOR:
    pushNullSensor();
    break;
  case STATE_SENSOR:
    pushStateSensor();
    break;
  case PACKET_SENSOR:
    pushPacketSensor();
    break;
  case DELAY_SENSOR:
    pushDelaySensor();
    break;
  case MIN_DELAY_SENSOR:
    pushMinDelaySensor();
    break;
  case MAX_DELAY_SENSOR:
    pushMaxDelaySensor();
    break;
  case THROUGHPUT_SENSOR:
    pushThroughputSensor();
    break;
  case EWMA_THROUGHPUT_SENSOR:
    pushEwmaThroughputSensor();
    break;
  default:
    logWrite(ERROR,
             "Incorrect sensor type (%d). Ignoring add sensor command.",
             newSensor.type);
    break;
  }
}

Sensor * SensorList::getHead(void)
{
  return head.get();
}

void SensorList::reset(void)
{
  head.reset(NULL);
  tail = NULL;
  // Dependency = NULL here
  depNullSensor = NULL;
  depStateSensor = NULL;
  depPacketSensor = NULL;
  depDelaySensor = NULL;
  depThroughputSensor = NULL;
  depMinDelaySensor = NULL;
}

void SensorList::pushSensor(std::auto_ptr<Sensor> newSensor)
{
  if (tail != NULL)
  {
    tail->addNode(newSensor);
    tail = tail->getTail();
  }
  else
  {
    head = newSensor;
    tail = head.get();
  }
}

// Add individual pushSensor functions here.

void SensorList::pushNullSensor(void)
{
  // Dependency list

  // Example dependency check
  if (depNullSensor == NULL)
  {
    logWrite(SENSOR, "Adding NullSensor");
    NullSensor * newSensor = new NullSensor();
    std::auto_ptr<Sensor> current(newSensor);
    pushSensor(current);

    // Example dependency set
    depNullSensor = newSensor;
  }
}

void SensorList::pushStateSensor(void)
{
  // Dependency list
  pushNullSensor();

  // Dependency check
  if (depStateSensor == NULL)
  {
    logWrite(SENSOR, "Adding StateSensor");
    StateSensor * newSensor = new StateSensor();
    std::auto_ptr<Sensor> current(newSensor);
    pushSensor(current);

    // Dependency set
    depStateSensor = newSensor;
  }
}

void SensorList::pushPacketSensor(void)
{
  // Dependency list
  pushStateSensor();

  // Example dependency check
  if (depPacketSensor == NULL)
  {
    logWrite(SENSOR, "Adding PacketSensor");
    PacketSensor * newSensor = new PacketSensor(depStateSensor);
    std::auto_ptr<Sensor> current(newSensor);
    pushSensor(current);

    // Example dependency set
    depPacketSensor = newSensor;
  }
}

void SensorList::pushDelaySensor(void)
{
  // Dependency list
  pushStateSensor();
  pushPacketSensor();

  // Example dependency check
  if (depDelaySensor == NULL)
  {
    logWrite(SENSOR, "Adding DelaySensor");
    DelaySensor * newSensor = new DelaySensor(depPacketSensor, depStateSensor);
    std::auto_ptr<Sensor> current(newSensor);
    pushSensor(current);

    // Example dependency set
    depDelaySensor = newSensor;
  }
}

void SensorList::pushMinDelaySensor(void)
{
  // Dependency list
  pushDelaySensor();

  if (depMinDelaySensor == NULL) {
      logWrite(SENSOR, "Adding MinDelaySensor");
      MinDelaySensor * newSensor = new MinDelaySensor(depDelaySensor);
      std::auto_ptr<Sensor> current(newSensor);
      pushSensor(current);

      // Dependency set
      depMinDelaySensor = newSensor;
  }

}

void SensorList::pushMaxDelaySensor(void)
{
  // Dependency list
  pushMinDelaySensor();
  pushDelaySensor();
  pushStateSensor();
  pushPacketSensor();

  logWrite(SENSOR, "Adding MaxDelaySensor");
  std::auto_ptr<Sensor> current(new MaxDelaySensor(depDelaySensor,
                                                   depStateSensor,
                                                   depMinDelaySensor,
                                                   depPacketSensor));
  pushSensor(current);
}

void SensorList::pushThroughputSensor(void)
{
  // Dependency list
  pushStateSensor();
  pushPacketSensor();

  // Example dependency check
  if (depThroughputSensor == NULL)
  {
    logWrite(SENSOR, "Adding ThroughputSensor");
    ThroughputSensor * newSensor = new ThroughputSensor(depPacketSensor,
                                                        depStateSensor);
    std::auto_ptr<Sensor> current(newSensor);
    pushSensor(current);

    // Example dependency set
    depThroughputSensor = newSensor;
  }
}

void SensorList::pushEwmaThroughputSensor(void)
{
  // Dependency list
  pushStateSensor();
  pushThroughputSensor();

  logWrite(SENSOR, "Adding EwmaThroughputSensor");
  std::auto_ptr<Sensor> current(new EwmaThroughputSensor(depThroughputSensor,
                                                         depStateSensor));
  pushSensor(current);
}
<|endoftext|>


<commit_before>/*
 *   Copyright (C) 2014 Pelagicore AB
 *   All rights reserved.
 */
#include <glibmm.h>
#include <dbus-c++/dbus.h>
#include <dbus-c++/glib-integration.h>

#include "CommandLineParser.h"
#include "log.h"
#include "paminterface.h"
#include "pelagicontain.h"
#include "pelagicontaintodbusadapter.h"
#include "dbusmainloop.h"
#include "generators.h" /* used for gen_ct_name */
#include "pulsegateway.h"
#include "networkgateway.h"
#include "dbusgateway.h"
#include <sys/stat.h>
#include "systemcallinterface.h"
#include "devicenodegateway.h"

LOG_DEFINE_APP_IDS("PCON", "Pelagicontain");
LOG_DECLARE_DEFAULT_CONTEXT(Pelagicontain_DefaultLogContext, "PCON", "Main context");

#ifndef CONFIG
    #error Must define CONFIG; path to configuration file (/etc/pelagicontain?)
#endif

int main(int argc, char **argv)
{
    const char *summary = "Pelagicore container utility. "
                          "Requires an absolute path to the container root, "
                          "the command to run inside the container and "
                          "an alphanumerical cookie string as first, second and"
                          "third argument respectively";
    const char *paramsDescription = "[container root directory (abs path)] "
                                    "[command] [cookie]";

    pelagicore::CommandLineParser commandLineParser(summary,
                                                    paramsDescription,
                                                    PACKAGE_VERSION,
                                                    "");

    std::string containerRoot;
    std::string containedCommand;
    std::string cookie;
    const char* configFilePath = CONFIG;
    commandLineParser.addOption(configFilePath,
                                "with-config-file",
                                'c',
                                "Config file");

    if (commandLineParser.parse(argc, argv)) {
        return -1;
    }

    if (argc < 4) {
        log_error("Invalid arguments");
        commandLineParser.printHelp();
        return -1;
    } else {
        containerRoot = std::string(argv[1]);
        containedCommand = std::string(argv[2]);
        cookie = std::string(argv[3]);
    }

    if (containerRoot.c_str()[0] != '/') {
        log_error("Path to container root must be absolute");
        commandLineParser.printHelp();
        return -1;
    }

    std::string containerName = Generator::gen_ct_name();
    std::string containerConfig(configFilePath);

    // Create gateway directory for container in containerRoot/gateways.
    // This dir will contain various sockets etc acting as gateways
    // in/out of the container.
    std::string containerDir = containerRoot + "/" + containerName;
    std::string gatewayDir = containerDir + "/gateways";
    if (mkdir(containerDir.c_str(), S_IRWXU) == -1) {
        log_error("Could not create container directory %s, %s.",
                  containerDir.c_str(),
                  strerror(errno));
        exit(-1);
    }
    if (mkdir(gatewayDir.c_str(), S_IRWXU) == -1) {
        log_error("Could not create gateway directory %s, %s.",
                  gatewayDir.c_str(),
                  strerror(errno));
        exit(-1);
    }

    Glib::RefPtr<Glib::MainLoop> ml = Glib::MainLoop::create();

    { // Create a new scope so that we can do a clean up after dtors
        DBus::Glib::BusDispatcher dispatcher;
        DBus::default_dispatcher = &dispatcher;
        dispatcher.attach(ml->get_context()->gobj());
        DBus::Connection bus = DBus::Connection::SessionBus();

        /* Pelagicontain needs an interface to the mainloop so it can
         * exit it when we are to clean up and shut down
         */
        DBusMainloop mainloopInterface(ml);

        /* The request_name call does not return anything but raises an
         * exception if the name cannot be requested.
         */
        std::string name = "com.pelagicore.Pelagicontain" + cookie;
        bus.request_name(name.c_str());

        PAMInterface pamInterface(bus);
        ControllerInterface controllerInterface(gatewayDir);
        SystemcallInterface systemcallInterface;
        Pelagicontain pelagicontain(&pamInterface,
                                    &mainloopInterface,
                                    &controllerInterface,
                                    cookie);

        std::string objectPath = "/com/pelagicore/Pelagicontain";

        PelagicontainToDBusAdapter pcAdapter(bus, objectPath, pelagicontain);

        pelagicontain.addGateway(new NetworkGateway(controllerInterface,
                                                    systemcallInterface));

        pelagicontain.addGateway(new PulseGateway(gatewayDir, containerName,
                                                  controllerInterface));

        pelagicontain.addGateway(new DeviceNodeGateway(controllerInterface));

        pelagicontain.addGateway(new DBusGateway(controllerInterface,
                                                 systemcallInterface,
                                                 DBusGateway::SessionProxy,
                                                 gatewayDir,
                                                 containerName));

        pelagicontain.addGateway(new DBusGateway(controllerInterface,
                                                 systemcallInterface,
                                                 DBusGateway::SystemProxy,
                                                 gatewayDir,
                                                 containerName));

        pid_t pcPid = pelagicontain.preload(containerName,
                                            containerConfig,
                                            containerRoot,
                                            containedCommand);

        if (!pcPid) {
            // Fatal failure, only do necessary cleanup
            log_error() << "Could not start container, will shut down";
        } else {
            log_debug() << "Started container with PID " << pcPid;
            // setup IPC between Pelagicontain and Controller
            bool connected = pelagicontain.establishConnection();
            if (connected) {
                ml->run();
                // When we return here Pelagicontain has exited the mainloop
                log_debug("Exited mainloop");
            } else {
                // Fatal failure, only do necessary cleanup
                log_error() << "Could not connect to Controller";
                pelagicontain.shutdownContainer();
            }
        }
    }

    // remove instance specific dirs again
    if (rmdir(gatewayDir.c_str()) == -1) {
        log_error("Cannot delete dir %s, %s",
                  gatewayDir.c_str(),
                  strerror(errno));
    }

    if (rmdir(containerDir.c_str()) == -1) {
        log_error("Cannot delete dir %s, %s",
                  gatewayDir.c_str(),
                  strerror(errno));
    }

    log_debug() << "Goodbye.";
}
<commit_msg>main.cpp: First attempt at signal handler for pelagicontain.<commit_after>/*
 *   Copyright (C) 2014 Pelagicore AB
 *   All rights reserved.
 */
#include <glibmm.h>
#include <dbus-c++/dbus.h>
#include <dbus-c++/glib-integration.h>

#include <signal.h>
#include <unistd.h>
#include "CommandLineParser.h"
#include "log.h"
#include "paminterface.h"
#include "pelagicontain.h"
#include "pelagicontaintodbusadapter.h"
#include "dbusmainloop.h"
#include "generators.h" /* used for gen_ct_name */
#include "pulsegateway.h"
#include "networkgateway.h"
#include "dbusgateway.h"
#include <sys/stat.h>
#include "systemcallinterface.h"
#include "devicenodegateway.h"

LOG_DEFINE_APP_IDS("PCON", "Pelagicontain");
LOG_DECLARE_DEFAULT_CONTEXT(Pelagicontain_DefaultLogContext, "PCON", "Main context");

#ifndef CONFIG
    #error Must define CONFIG; path to configuration file (/etc/pelagicontain?)
#endif

/* Needs to be global in order to be reachable from the signal handler */
static Pelagicontain *pelagicontain;

void signalHandler(int signum)
{
    log_debug() << "caught signal " << signum;
    pelagicontain->shutdown();
}

int main(int argc, char **argv)
{

    signal(SIGINT, signalHandler);
    signal(SIGTERM, signalHandler);

    const char *summary = "Pelagicore container utility. "
                          "Requires an absolute path to the container root, "
                          "the command to run inside the container and "
                          "an alphanumerical cookie string as first, second and"
                          "third argument respectively";
    const char *paramsDescription = "[container root directory (abs path)] "
                                    "[command] [cookie]";

    pelagicore::CommandLineParser commandLineParser(summary,
                                                    paramsDescription,
                                                    PACKAGE_VERSION,
                                                    "");

    std::string containerRoot;
    std::string containedCommand;
    std::string cookie;
    const char* configFilePath = CONFIG;
    commandLineParser.addOption(configFilePath,
                                "with-config-file",
                                'c',
                                "Config file");

    if (commandLineParser.parse(argc, argv)) {
        return -1;
    }

    if (argc < 4) {
        log_error("Invalid arguments");
        commandLineParser.printHelp();
        return -1;
    } else {
        containerRoot = std::string(argv[1]);
        containedCommand = std::string(argv[2]);
        cookie = std::string(argv[3]);
    }

    if (containerRoot.c_str()[0] != '/') {
        log_error("Path to container root must be absolute");
        commandLineParser.printHelp();
        return -1;
    }

    std::string containerName = Generator::gen_ct_name();
    std::string containerConfig(configFilePath);

    // Create gateway directory for container in containerRoot/gateways.
    // This dir will contain various sockets etc acting as gateways
    // in/out of the container.
    std::string containerDir = containerRoot + "/" + containerName;
    std::string gatewayDir = containerDir + "/gateways";
    if (mkdir(containerDir.c_str(), S_IRWXU) == -1) {
        log_error("Could not create container directory %s, %s.",
                  containerDir.c_str(),
                  strerror(errno));
        exit(-1);
    }
    if (mkdir(gatewayDir.c_str(), S_IRWXU) == -1) {
        log_error("Could not create gateway directory %s, %s.",
                  gatewayDir.c_str(),
                  strerror(errno));
        exit(-1);
    }

    Glib::RefPtr<Glib::MainLoop> ml = Glib::MainLoop::create();

    { // Create a new scope so that we can do a clean up after dtors
        DBus::Glib::BusDispatcher dispatcher;
        DBus::default_dispatcher = &dispatcher;
        dispatcher.attach(ml->get_context()->gobj());
        DBus::Connection bus = DBus::Connection::SessionBus();

        /* Pelagicontain needs an interface to the mainloop so it can
         * exit it when we are to clean up and shut down
         */
        DBusMainloop mainloopInterface(ml);

        /* The request_name call does not return anything but raises an
         * exception if the name cannot be requested.
         */
        std::string name = "com.pelagicore.Pelagicontain" + cookie;
        bus.request_name(name.c_str());

        PAMInterface pamInterface(bus);
        ControllerInterface controllerInterface(gatewayDir);
        SystemcallInterface systemcallInterface;
        pelagicontain = new Pelagicontain(&pamInterface,
                                          &mainloopInterface,
                                          &controllerInterface,
                                          cookie);

        std::string objectPath = "/com/pelagicore/Pelagicontain";

        PelagicontainToDBusAdapter pcAdapter(bus, objectPath, *pelagicontain);

        pelagicontain->addGateway(new NetworkGateway(controllerInterface,
                                                    systemcallInterface));

        pelagicontain->addGateway(new PulseGateway(gatewayDir, containerName,
                                                  controllerInterface));

        pelagicontain->addGateway(new DeviceNodeGateway(controllerInterface));

        pelagicontain->addGateway(new DBusGateway(controllerInterface,
                                                 systemcallInterface,
                                                 DBusGateway::SessionProxy,
                                                 gatewayDir,
                                                 containerName));

        pelagicontain->addGateway(new DBusGateway(controllerInterface,
                                                 systemcallInterface,
                                                 DBusGateway::SystemProxy,
                                                 gatewayDir,
                                                 containerName));

        pid_t pcPid = pelagicontain->preload(containerName,
                                            containerConfig,
                                            containerRoot,
                                            containedCommand);

        if (!pcPid) {
            // Fatal failure, only do necessary cleanup
            log_error() << "Could not start container, will shut down";
        } else {
            log_debug() << "Started container with PID " << pcPid;
            // setup IPC between Pelagicontain and Controller
            bool connected = pelagicontain->establishConnection();
            if (connected) {
                ml->run();
                // When we return here Pelagicontain has exited the mainloop
                log_debug("Exited mainloop");
            } else {
                // Fatal failure, only do necessary cleanup
                log_error() << "Could not connect to Controller";
                pelagicontain->shutdownContainer();
            }
        }
    }

    delete pelagicontain;

    // remove instance specific dirs again
    if (rmdir(gatewayDir.c_str()) == -1) {
        log_error("Cannot delete dir %s, %s",
                  gatewayDir.c_str(),
                  strerror(errno));
    }

    if (rmdir(containerDir.c_str()) == -1) {
        log_error("Cannot delete dir %s, %s",
                  gatewayDir.c_str(),
                  strerror(errno));
    }

    log_debug() << "Goodbye.";
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. 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.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License 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 "benchmark/benchmark.h"
#include "benchmark_api_internal.h"
#include "internal_macros.h"

#ifndef BENCHMARK_OS_WINDOWS
#include <sys/resource.h>
#include <sys/time.h>
#include <unistd.h>
#endif

#include <algorithm>
#include <atomic>
#include <condition_variable>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>
#include <thread>

#include "check.h"
#include "commandlineflags.h"
#include "complexity.h"
#include "log.h"
#include "mutex.h"
#include "re.h"
#include "stat.h"
#include "string_util.h"
#include "sysinfo.h"
#include "timers.h"

namespace benchmark {

namespace {
// For non-dense Range, intermediate values are powers of kRangeMultiplier.
static const int kRangeMultiplier = 8;
// The size of a benchmark family determines is the number of inputs to repeat
// the benchmark on. If this is "large" then warn the user during configuration.
static const size_t kMaxFamilySize = 100;
}  // end namespace

namespace internal {

//=============================================================================//
//                         BenchmarkFamilies
//=============================================================================//

// Class for managing registered benchmarks.  Note that each registered
// benchmark identifies a family of related benchmarks to run.
class BenchmarkFamilies {
 public:
  static BenchmarkFamilies* GetInstance();

  // Registers a benchmark family and returns the index assigned to it.
  size_t AddBenchmark(std::unique_ptr<Benchmark> family);

  // Extract the list of benchmark instances that match the specified
  // regular expression.
  bool FindBenchmarks(const std::string& re,
                      std::vector<Benchmark::Instance>* benchmarks,
                      std::ostream* Err);

 private:
  BenchmarkFamilies() {}

  std::vector<std::unique_ptr<Benchmark>> families_;
  Mutex mutex_;
};

BenchmarkFamilies* BenchmarkFamilies::GetInstance() {
  static BenchmarkFamilies instance;
  return &instance;
}

size_t BenchmarkFamilies::AddBenchmark(std::unique_ptr<Benchmark> family) {
  MutexLock l(mutex_);
  size_t index = families_.size();
  families_.push_back(std::move(family));
  return index;
}

bool BenchmarkFamilies::FindBenchmarks(
    const std::string& spec, std::vector<Benchmark::Instance>* benchmarks,
    std::ostream* ErrStream) {
  CHECK(ErrStream);
  auto& Err = *ErrStream;
  // Make regular expression out of command-line flag
  std::string error_msg;
  Regex re;
  if (!re.Init(spec, &error_msg)) {
    Err << "Could not compile benchmark re: " << error_msg << std::endl;
    return false;
  }

  // Special list of thread counts to use when none are specified
  const std::vector<int> one_thread = {1};

  MutexLock l(mutex_);
  for (std::unique_ptr<Benchmark>& family : families_) {
    // Family was deleted or benchmark doesn't match
    if (!family) continue;

    if (family->ArgsCnt() == -1) {
      family->Args({});
    }
    const std::vector<int>* thread_counts =
        (family->thread_counts_.empty()
             ? &one_thread
             : &static_cast<const std::vector<int>&>(family->thread_counts_));
    const size_t family_size = family->args_.size() * thread_counts->size();
    // The benchmark will be run at least 'family_size' different inputs.
    // If 'family_size' is very large warn the user.
    if (family_size > kMaxFamilySize) {
      Err << "The number of inputs is very large. " << family->name_
          << " will be repeated at least " << family_size << " times.\n";
    }
    // reserve in the special case the regex ".", since we know the final
    // family size.
    if (spec == ".") benchmarks->reserve(family_size);

    for (auto const& args : family->args_) {
      for (int num_threads : *thread_counts) {
        Benchmark::Instance instance;
        instance.name = family->name_;
        instance.benchmark = family.get();
        instance.report_mode = family->report_mode_;
        instance.arg = args;
        instance.time_unit = family->time_unit_;
        instance.range_multiplier = family->range_multiplier_;
        instance.min_time = family->min_time_;
        instance.repetitions = family->repetitions_;
        instance.use_real_time = family->use_real_time_;
        instance.use_manual_time = family->use_manual_time_;
        instance.complexity = family->complexity_;
        instance.complexity_lambda = family->complexity_lambda_;
        instance.threads = num_threads;

        // Add arguments to instance name
        size_t arg_i = 0;
        for (auto const& arg : args) {
          instance.name += "/";

          if (arg_i < family->arg_names_.size()) {
            const auto& arg_name = family->arg_names_[arg_i];
            if (!arg_name.empty()) {
              instance.name +=
                  StringPrintF("%s:", family->arg_names_[arg_i].c_str());
            }
          }

          AppendHumanReadable(arg, &instance.name);
          ++arg_i;
        }

        if (!IsZero(family->min_time_)) {
          instance.name += StringPrintF("/min_time:%0.3f", family->min_time_);
        }
        if (family->repetitions_ != 0) {
          instance.name += StringPrintF("/repeats:%d", family->repetitions_);
        }
        if (family->use_manual_time_) {
          instance.name += "/manual_time";
        } else if (family->use_real_time_) {
          instance.name += "/real_time";
        }

        // Add the number of threads used to the name
        if (!family->thread_counts_.empty()) {
          instance.name += StringPrintF("/threads:%d", instance.threads);
        }

        if (re.Match(instance.name)) {
          instance.last_benchmark_instance = (&args == &family->args_.back());
          benchmarks->push_back(std::move(instance));
        }
      }
    }
  }
  return true;
}

Benchmark* RegisterBenchmarkInternal(Benchmark* bench) {
  std::unique_ptr<Benchmark> bench_ptr(bench);
  BenchmarkFamilies* families = BenchmarkFamilies::GetInstance();
  families->AddBenchmark(std::move(bench_ptr));
  return bench;
}

// FIXME: This function is a hack so that benchmark.cc can access
// `BenchmarkFamilies`
bool FindBenchmarksInternal(const std::string& re,
                            std::vector<Benchmark::Instance>* benchmarks,
                            std::ostream* Err) {
  return BenchmarkFamilies::GetInstance()->FindBenchmarks(re, benchmarks, Err);
}

//=============================================================================//
//                               Benchmark
//=============================================================================//

Benchmark::Benchmark(const char* name)
    : name_(name),
      report_mode_(RM_Unspecified),
      time_unit_(kNanosecond),
      range_multiplier_(kRangeMultiplier),
      min_time_(0),
      repetitions_(0),
      use_real_time_(false),
      use_manual_time_(false),
      complexity_(oNone),
      complexity_lambda_(nullptr) {}

Benchmark::~Benchmark() {}

void Benchmark::AddRange(std::vector<int>* dst, int lo, int hi, int mult) {
  CHECK_GE(lo, 0);
  CHECK_GE(hi, lo);
  CHECK_GE(mult, 2);

  // Add "lo"
  dst->push_back(lo);

  static const int kint32max = std::numeric_limits<int32_t>::max();

  // Now space out the benchmarks in multiples of "mult"
  for (int32_t i = 1; i < kint32max / mult; i *= mult) {
    if (i >= hi) break;
    if (i > lo) {
      dst->push_back(i);
    }
  }
  // Add "hi" (if different from "lo")
  if (hi != lo) {
    dst->push_back(hi);
  }
}

Benchmark* Benchmark::Arg(int x) {
  CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
  args_.push_back({x});
  return this;
}

Benchmark* Benchmark::Unit(TimeUnit unit) {
  time_unit_ = unit;
  return this;
}

Benchmark* Benchmark::Range(int start, int limit) {
  CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
  std::vector<int> arglist;
  AddRange(&arglist, start, limit, range_multiplier_);

  for (int i : arglist) {
    args_.push_back({i});
  }
  return this;
}

Benchmark* Benchmark::Ranges(const std::vector<std::pair<int, int>>& ranges) {
  CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(ranges.size()));
  std::vector<std::vector<int>> arglists(ranges.size());
  std::size_t total = 1;
  for (std::size_t i = 0; i < ranges.size(); i++) {
    AddRange(&arglists[i], ranges[i].first, ranges[i].second,
             range_multiplier_);
    total *= arglists[i].size();
  }

  std::vector<std::size_t> ctr(arglists.size(), 0);

  for (std::size_t i = 0; i < total; i++) {
    std::vector<int> tmp;
    tmp.reserve(arglists.size());

    for (std::size_t j = 0; j < arglists.size(); j++) {
      tmp.push_back(arglists[j].at(ctr[j]));
    }

    args_.push_back(std::move(tmp));

    for (std::size_t j = 0; j < arglists.size(); j++) {
      if (ctr[j] + 1 < arglists[j].size()) {
        ++ctr[j];
        break;
      }
      ctr[j] = 0;
    }
  }
  return this;
}

Benchmark* Benchmark::ArgName(const std::string& name) {
  CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
  arg_names_ = {name};
  return this;
}

Benchmark* Benchmark::ArgNames(const std::vector<std::string>& names) {
  CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(names.size()));
  arg_names_ = names;
  return this;
}

Benchmark* Benchmark::DenseRange(int start, int limit, int step) {
  CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
  CHECK_GE(start, 0);
  CHECK_LE(start, limit);
  for (int arg = start; arg <= limit; arg += step) {
    args_.push_back({arg});
  }
  return this;
}

Benchmark* Benchmark::Args(const std::vector<int>& args) {
  CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(args.size()));
  args_.push_back(args);
  return this;
}

Benchmark* Benchmark::Apply(void (*custom_arguments)(Benchmark* benchmark)) {
  custom_arguments(this);
  return this;
}

Benchmark* Benchmark::RangeMultiplier(int multiplier) {
  CHECK(multiplier > 1);
  range_multiplier_ = multiplier;
  return this;
}

Benchmark* Benchmark::Repetitions(int n) {
  CHECK(n > 0);
  repetitions_ = n;
  return this;
}

Benchmark* Benchmark::ReportAggregatesOnly(bool value) {
  report_mode_ = value ? RM_ReportAggregatesOnly : RM_Default;
  return this;
}

Benchmark* Benchmark::MinTime(double t) {
  CHECK(t > 0.0);
  min_time_ = t;
  return this;
}

Benchmark* Benchmark::UseRealTime() {
  CHECK(!use_manual_time_)
      << "Cannot set UseRealTime and UseManualTime simultaneously.";
  use_real_time_ = true;
  return this;
}

Benchmark* Benchmark::UseManualTime() {
  CHECK(!use_real_time_)
      << "Cannot set UseRealTime and UseManualTime simultaneously.";
  use_manual_time_ = true;
  return this;
}

Benchmark* Benchmark::Complexity(BigO complexity) {
  complexity_ = complexity;
  return this;
}

Benchmark* Benchmark::Complexity(BigOFunc* complexity) {
  complexity_lambda_ = complexity;
  complexity_ = oLambda;
  return this;
}

Benchmark* Benchmark::Threads(int t) {
  CHECK_GT(t, 0);
  thread_counts_.push_back(t);
  return this;
}

Benchmark* Benchmark::ThreadRange(int min_threads, int max_threads) {
  CHECK_GT(min_threads, 0);
  CHECK_GE(max_threads, min_threads);

  AddRange(&thread_counts_, min_threads, max_threads, 2);
  return this;
}

Benchmark* Benchmark::DenseThreadRange(int min_threads, int max_threads,
                                       int stride) {
  CHECK_GT(min_threads, 0);
  CHECK_GE(max_threads, min_threads);
  CHECK_GE(stride, 1);

  for (auto i = min_threads; i < max_threads; i += stride) {
    thread_counts_.push_back(i);
  }
  thread_counts_.push_back(max_threads);
  return this;
}

Benchmark* Benchmark::ThreadPerCpu() {
  static int num_cpus = NumCPUs();
  thread_counts_.push_back(num_cpus);
  return this;
}

void Benchmark::SetName(const char* name) { name_ = name; }

int Benchmark::ArgsCnt() const {
  if (args_.empty()) {
    if (arg_names_.empty()) return -1;
    return static_cast<int>(arg_names_.size());
  }
  return static_cast<int>(args_.front().size());
}

//=============================================================================//
//                            FunctionBenchmark
//=============================================================================//

void FunctionBenchmark::Run(State& st) { func_(st); }

}  // end namespace internal
}  // end namespace benchmark
<commit_msg>Issue 327 (#328)<commit_after>// Copyright 2015 Google Inc. 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.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License 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 "benchmark/benchmark.h"
#include "benchmark_api_internal.h"
#include "internal_macros.h"

#ifndef BENCHMARK_OS_WINDOWS
#include <sys/resource.h>
#include <sys/time.h>
#include <unistd.h>
#endif

#include <algorithm>
#include <atomic>
#include <condition_variable>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <memory>
#include <thread>

#include "check.h"
#include "commandlineflags.h"
#include "complexity.h"
#include "log.h"
#include "mutex.h"
#include "re.h"
#include "stat.h"
#include "string_util.h"
#include "sysinfo.h"
#include "timers.h"

namespace benchmark {

namespace {
// For non-dense Range, intermediate values are powers of kRangeMultiplier.
static const int kRangeMultiplier = 8;
// The size of a benchmark family determines is the number of inputs to repeat
// the benchmark on. If this is "large" then warn the user during configuration.
static const size_t kMaxFamilySize = 100;
}  // end namespace

namespace internal {

//=============================================================================//
//                         BenchmarkFamilies
//=============================================================================//

// Class for managing registered benchmarks.  Note that each registered
// benchmark identifies a family of related benchmarks to run.
class BenchmarkFamilies {
 public:
  static BenchmarkFamilies* GetInstance();

  // Registers a benchmark family and returns the index assigned to it.
  size_t AddBenchmark(std::unique_ptr<Benchmark> family);

  // Extract the list of benchmark instances that match the specified
  // regular expression.
  bool FindBenchmarks(const std::string& re,
                      std::vector<Benchmark::Instance>* benchmarks,
                      std::ostream* Err);

 private:
  BenchmarkFamilies() {}

  std::vector<std::unique_ptr<Benchmark>> families_;
  Mutex mutex_;
};

BenchmarkFamilies* BenchmarkFamilies::GetInstance() {
  static BenchmarkFamilies instance;
  return &instance;
}

size_t BenchmarkFamilies::AddBenchmark(std::unique_ptr<Benchmark> family) {
  MutexLock l(mutex_);
  size_t index = families_.size();
  families_.push_back(std::move(family));
  return index;
}

bool BenchmarkFamilies::FindBenchmarks(
    const std::string& spec, std::vector<Benchmark::Instance>* benchmarks,
    std::ostream* ErrStream) {
  CHECK(ErrStream);
  auto& Err = *ErrStream;
  // Make regular expression out of command-line flag
  std::string error_msg;
  Regex re;
  if (!re.Init(spec, &error_msg)) {
    Err << "Could not compile benchmark re: " << error_msg << std::endl;
    return false;
  }

  // Special list of thread counts to use when none are specified
  const std::vector<int> one_thread = {1};

  MutexLock l(mutex_);
  for (std::unique_ptr<Benchmark>& family : families_) {
    // Family was deleted or benchmark doesn't match
    if (!family) continue;

    if (family->ArgsCnt() == -1) {
      family->Args({});
    }
    const std::vector<int>* thread_counts =
        (family->thread_counts_.empty()
             ? &one_thread
             : &static_cast<const std::vector<int>&>(family->thread_counts_));
    const size_t family_size = family->args_.size() * thread_counts->size();
    // The benchmark will be run at least 'family_size' different inputs.
    // If 'family_size' is very large warn the user.
    if (family_size > kMaxFamilySize) {
      Err << "The number of inputs is very large. " << family->name_
          << " will be repeated at least " << family_size << " times.\n";
    }
    // reserve in the special case the regex ".", since we know the final
    // family size.
    if (spec == ".") benchmarks->reserve(family_size);

    for (auto const& args : family->args_) {
      for (int num_threads : *thread_counts) {
        Benchmark::Instance instance;
        instance.name = family->name_;
        instance.benchmark = family.get();
        instance.report_mode = family->report_mode_;
        instance.arg = args;
        instance.time_unit = family->time_unit_;
        instance.range_multiplier = family->range_multiplier_;
        instance.min_time = family->min_time_;
        instance.repetitions = family->repetitions_;
        instance.use_real_time = family->use_real_time_;
        instance.use_manual_time = family->use_manual_time_;
        instance.complexity = family->complexity_;
        instance.complexity_lambda = family->complexity_lambda_;
        instance.threads = num_threads;

        // Add arguments to instance name
        size_t arg_i = 0;
        for (auto const& arg : args) {
          instance.name += "/";

          if (arg_i < family->arg_names_.size()) {
            const auto& arg_name = family->arg_names_[arg_i];
            if (!arg_name.empty()) {
              instance.name +=
                  StringPrintF("%s:", family->arg_names_[arg_i].c_str());
            }
          }

          instance.name += std::to_string(arg);
          ++arg_i;
        }

        if (!IsZero(family->min_time_)) {
          instance.name += StringPrintF("/min_time:%0.3f", family->min_time_);
        }
        if (family->repetitions_ != 0) {
          instance.name += StringPrintF("/repeats:%d", family->repetitions_);
        }
        if (family->use_manual_time_) {
          instance.name += "/manual_time";
        } else if (family->use_real_time_) {
          instance.name += "/real_time";
        }

        // Add the number of threads used to the name
        if (!family->thread_counts_.empty()) {
          instance.name += StringPrintF("/threads:%d", instance.threads);
        }

        if (re.Match(instance.name)) {
          instance.last_benchmark_instance = (&args == &family->args_.back());
          benchmarks->push_back(std::move(instance));
        }
      }
    }
  }
  return true;
}

Benchmark* RegisterBenchmarkInternal(Benchmark* bench) {
  std::unique_ptr<Benchmark> bench_ptr(bench);
  BenchmarkFamilies* families = BenchmarkFamilies::GetInstance();
  families->AddBenchmark(std::move(bench_ptr));
  return bench;
}

// FIXME: This function is a hack so that benchmark.cc can access
// `BenchmarkFamilies`
bool FindBenchmarksInternal(const std::string& re,
                            std::vector<Benchmark::Instance>* benchmarks,
                            std::ostream* Err) {
  return BenchmarkFamilies::GetInstance()->FindBenchmarks(re, benchmarks, Err);
}

//=============================================================================//
//                               Benchmark
//=============================================================================//

Benchmark::Benchmark(const char* name)
    : name_(name),
      report_mode_(RM_Unspecified),
      time_unit_(kNanosecond),
      range_multiplier_(kRangeMultiplier),
      min_time_(0),
      repetitions_(0),
      use_real_time_(false),
      use_manual_time_(false),
      complexity_(oNone),
      complexity_lambda_(nullptr) {}

Benchmark::~Benchmark() {}

void Benchmark::AddRange(std::vector<int>* dst, int lo, int hi, int mult) {
  CHECK_GE(lo, 0);
  CHECK_GE(hi, lo);
  CHECK_GE(mult, 2);

  // Add "lo"
  dst->push_back(lo);

  static const int kint32max = std::numeric_limits<int32_t>::max();

  // Now space out the benchmarks in multiples of "mult"
  for (int32_t i = 1; i < kint32max / mult; i *= mult) {
    if (i >= hi) break;
    if (i > lo) {
      dst->push_back(i);
    }
  }
  // Add "hi" (if different from "lo")
  if (hi != lo) {
    dst->push_back(hi);
  }
}

Benchmark* Benchmark::Arg(int x) {
  CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
  args_.push_back({x});
  return this;
}

Benchmark* Benchmark::Unit(TimeUnit unit) {
  time_unit_ = unit;
  return this;
}

Benchmark* Benchmark::Range(int start, int limit) {
  CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
  std::vector<int> arglist;
  AddRange(&arglist, start, limit, range_multiplier_);

  for (int i : arglist) {
    args_.push_back({i});
  }
  return this;
}

Benchmark* Benchmark::Ranges(const std::vector<std::pair<int, int>>& ranges) {
  CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(ranges.size()));
  std::vector<std::vector<int>> arglists(ranges.size());
  std::size_t total = 1;
  for (std::size_t i = 0; i < ranges.size(); i++) {
    AddRange(&arglists[i], ranges[i].first, ranges[i].second,
             range_multiplier_);
    total *= arglists[i].size();
  }

  std::vector<std::size_t> ctr(arglists.size(), 0);

  for (std::size_t i = 0; i < total; i++) {
    std::vector<int> tmp;
    tmp.reserve(arglists.size());

    for (std::size_t j = 0; j < arglists.size(); j++) {
      tmp.push_back(arglists[j].at(ctr[j]));
    }

    args_.push_back(std::move(tmp));

    for (std::size_t j = 0; j < arglists.size(); j++) {
      if (ctr[j] + 1 < arglists[j].size()) {
        ++ctr[j];
        break;
      }
      ctr[j] = 0;
    }
  }
  return this;
}

Benchmark* Benchmark::ArgName(const std::string& name) {
  CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
  arg_names_ = {name};
  return this;
}

Benchmark* Benchmark::ArgNames(const std::vector<std::string>& names) {
  CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(names.size()));
  arg_names_ = names;
  return this;
}

Benchmark* Benchmark::DenseRange(int start, int limit, int step) {
  CHECK(ArgsCnt() == -1 || ArgsCnt() == 1);
  CHECK_GE(start, 0);
  CHECK_LE(start, limit);
  for (int arg = start; arg <= limit; arg += step) {
    args_.push_back({arg});
  }
  return this;
}

Benchmark* Benchmark::Args(const std::vector<int>& args) {
  CHECK(ArgsCnt() == -1 || ArgsCnt() == static_cast<int>(args.size()));
  args_.push_back(args);
  return this;
}

Benchmark* Benchmark::Apply(void (*custom_arguments)(Benchmark* benchmark)) {
  custom_arguments(this);
  return this;
}

Benchmark* Benchmark::RangeMultiplier(int multiplier) {
  CHECK(multiplier > 1);
  range_multiplier_ = multiplier;
  return this;
}

Benchmark* Benchmark::Repetitions(int n) {
  CHECK(n > 0);
  repetitions_ = n;
  return this;
}

Benchmark* Benchmark::ReportAggregatesOnly(bool value) {
  report_mode_ = value ? RM_ReportAggregatesOnly : RM_Default;
  return this;
}

Benchmark* Benchmark::MinTime(double t) {
  CHECK(t > 0.0);
  min_time_ = t;
  return this;
}

Benchmark* Benchmark::UseRealTime() {
  CHECK(!use_manual_time_)
      << "Cannot set UseRealTime and UseManualTime simultaneously.";
  use_real_time_ = true;
  return this;
}

Benchmark* Benchmark::UseManualTime() {
  CHECK(!use_real_time_)
      << "Cannot set UseRealTime and UseManualTime simultaneously.";
  use_manual_time_ = true;
  return this;
}

Benchmark* Benchmark::Complexity(BigO complexity) {
  complexity_ = complexity;
  return this;
}

Benchmark* Benchmark::Complexity(BigOFunc* complexity) {
  complexity_lambda_ = complexity;
  complexity_ = oLambda;
  return this;
}

Benchmark* Benchmark::Threads(int t) {
  CHECK_GT(t, 0);
  thread_counts_.push_back(t);
  return this;
}

Benchmark* Benchmark::ThreadRange(int min_threads, int max_threads) {
  CHECK_GT(min_threads, 0);
  CHECK_GE(max_threads, min_threads);

  AddRange(&thread_counts_, min_threads, max_threads, 2);
  return this;
}

Benchmark* Benchmark::DenseThreadRange(int min_threads, int max_threads,
                                       int stride) {
  CHECK_GT(min_threads, 0);
  CHECK_GE(max_threads, min_threads);
  CHECK_GE(stride, 1);

  for (auto i = min_threads; i < max_threads; i += stride) {
    thread_counts_.push_back(i);
  }
  thread_counts_.push_back(max_threads);
  return this;
}

Benchmark* Benchmark::ThreadPerCpu() {
  static int num_cpus = NumCPUs();
  thread_counts_.push_back(num_cpus);
  return this;
}

void Benchmark::SetName(const char* name) { name_ = name; }

int Benchmark::ArgsCnt() const {
  if (args_.empty()) {
    if (arg_names_.empty()) return -1;
    return static_cast<int>(arg_names_.size());
  }
  return static_cast<int>(args_.front().size());
}

//=============================================================================//
//                            FunctionBenchmark
//=============================================================================//

void FunctionBenchmark::Run(State& st) { func_(st); }

}  // end namespace internal
}  // end namespace benchmark
<|endoftext|>


<commit_before>//===--- SILPrinter.cpp - Pretty-printing of SIL Code ---------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the logic to pretty-print SIL, Instructions, etc.
//
//===----------------------------------------------------------------------===//

#include "swift/SIL/SILVisitor.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/raw_ostream.h"
using namespace swift;

struct ID {
  enum {
    BasicBlock, SSAValue
  } Kind;
  unsigned Number;
  int ResultNumber;
};

raw_ostream &operator<<(raw_ostream &OS, ID i) {
  switch (i.Kind) {
  case ID::BasicBlock: OS << "bb"; break;
  case ID::SSAValue: OS << '%'; break;
  }
  OS << i.Number;

  if (i.ResultNumber != -1)
    OS << '#' << i.ResultNumber;
  return OS;
}

namespace {
/// SILPrinter class - This is the internal implementation details of printing
/// for SIL structures.
class SILPrinter : public SILVisitor<SILPrinter> {
  raw_ostream &OS;

  llvm::DenseMap<const BasicBlock *, unsigned> BlocksToIDMap;
  ID getID(const BasicBlock *B);

  llvm::DenseMap<Value, unsigned> ValueToIDMap;
  ID getID(Value V);

public:
  SILPrinter(raw_ostream &OS) : OS(OS) {
  }

  void print(const BasicBlock *BB) {
    OS << getID(BB);

    if (!BB->bbarg_empty()) {
      OS << '(';
      for (auto I = BB->bbarg_begin(), E = BB->bbarg_end(); I != E; ++I) {
        if (I != BB->bbarg_begin()) OS << ", ";
        OS << getID(*I) << " : " << (*I)->getType().getString();
      }
      OS << ')';
    }

    OS << ":\t";

    if (!BB->pred_empty()) {
      OS << " ; Preds:";
      for (auto BBI = BB->pred_begin(), E = BB->pred_end(); BBI != E; ++BBI)
        OS << ' ' << getID(*BBI);
    }
    OS << '\n';

    for (const Instruction &I : *BB)
      print(&I);

    OS << '\n';
  }

  //===--------------------------------------------------------------------===//
  // Instruction Printing Logic

  void print(Value V) {
    OS << "  " << getID(V) << " = ";
    visit(V);
    OS << '\n';
  }
  void visitInstruction(Instruction *I) {
    assert(0 && "SILPrinter not implemented for this instruction!");
  }

  void visitAllocVarInst(AllocVarInst *AVI) {
    OS << "alloc_var " << AVI->getDecl()->getName()
       << ", type=" << AVI->getType().getString();

  }

  void visitAllocTmpInst(AllocTmpInst *ATI) {
    OS << "alloc_tmp type=" << ATI->getType().getString();
  }

  void visitAllocArrayInst(AllocArrayInst *AAI) {
    OS << "alloc_array element type=" << AAI->getElementType().getString()
       << ", " << getID(AAI->getNumElements());
  }

  void visitApplyInst(ApplyInst *AI) {
    OS << "apply " << getID(AI->getCallee()) << '(';
    bool first = true;
    for (auto arg : AI->getArguments()) {
      if (first)
        first = false;
      else
        OS << ", ";
      OS << getID(arg);
    }
    OS << ')';
  }

  void visitConstantRefInst(ConstantRefInst *DRI) {
    OS << "constantref " << DRI->getDecl()->getName()
    << ", type=" << DRI->getDecl()->getType().getString();
  }

  void visitZeroValueInst(ZeroValueInst *ZVI) {
    OS << "zerovalueinst " << ZVI->getType().getString();
  }

  void visitIntegerLiteralInst(IntegerLiteralInst *ILI) {
    const auto &lit = ILI->getValue();
    OS << "integerliteral " << lit << ", width=" << lit.getBitWidth();
  }
  void visitFloatLiteralInst(FloatLiteralInst *FLI) {
    SmallVector<char, 12> Buffer;
    FLI->getValue().toString(Buffer);
    OS << "floatliteral " << StringRef(Buffer.data(), Buffer.size());
  }
  void visitCharacterLiteralInst(CharacterLiteralInst *CLI) {
    OS << "characterliteral " << CLI->getValue();
  }
  void visitStringLiteralInst(StringLiteralInst *SLI) {
    OS << "stringliteral \"" << SLI->getValue() << "\"";
  }
  void visitLoadInst(LoadInst *LI) {
    OS << "load " << getID(LI->getLValue());
    if (LI->isTake())
      OS << " [take]";
  }
  void visitStoreInst(StoreInst *SI) {
    OS << "store " << getID(SI->getSrc()) << " -> "
       << getID(SI->getDest());
    if (SI->isInitialization())
      OS << " [initialization]";
  }
  void visitCopyInst(CopyInst *CI) {
    OS << "copy " << getID(CI->getSrc());
    if (CI->isTakeOfSrc())
      OS << " [take]";
    OS << " -> " << getID(CI->getDest());
    if (CI->isInitializationOfDest())
      OS << " [initialization]";
  }
  void visitSpecializeInst(SpecializeInst *SI) {
    OS << "specialize " << getID(SI->getOperand()) << " -> "
       << SI->getType().getString();
  }
  void visitTypeConversionInst(TypeConversionInst *TCI) {
    OS << "type_conversion " << getID(TCI->getOperand()) << " -> "
       << TCI->getType().getString();
  }
  void visitTupleInst(TupleInst *TI) {
    OS << "tuple (";
    bool isFirst = true;
    for (const auto &Elem : TI->getElements()) {
      if (isFirst)
        isFirst = false;
      else
        OS << ", ";
      OS << getID(Elem);
    }
    OS << ')';
  }
  void visitTupleElementInst(TupleElementInst *TEI) {
    OS << "tupleelement " << getID(TEI->getOperand()) << ", "
       << TEI->getFieldNo();
  }
  void visitMetatypeInst(MetatypeInst *MI) {
    OS << "metatype " << MI->getMetaType().getString();
  }

  void visitRetainInst(RetainInst *RI) {
    OS << "retain " << getID(RI->getOperand());
  }
  void visitReleaseInst(ReleaseInst *RI) {
    OS << "release " << getID(RI->getOperand());
  }
  void visitDeallocInst(DeallocInst *DI) {
    OS << "dealloc " << getID(DI->getOperand());
  }
  void visitDestroyInst(DestroyInst *DI) {
    OS << "destroy " << getID(DI->getOperand());
  }

  void visitIndexLValueInst(IndexLValueInst *ILI) {
    OS << "index_lvalue " << getID(ILI->getOperand()) << ", " <<ILI->getIndex();
  }

  void visitIntegerValueInst(IntegerValueInst *IVI) {
    OS << "integer_value " << IVI->getValue() << ", "
       << IVI->getType().getString();
  }

  void visitUnreachableInst(UnreachableInst *UI) {
    OS << "unreachable";
  }

  void visitReturnInst(ReturnInst *RI) {
    OS << "return " << '(' << getID(RI->getReturnValue()) << ')';
  }

  void visitBranchInst(BranchInst *UBI) {
    OS << "br " << getID(UBI->getDestBB());
  }

  void visitCondBranchInst(CondBranchInst *CBI) {
    OS << "condbranch " << getID(CBI->getCondition()) << ", "
       << getID(CBI->getTrueBB()) << ',' << getID(CBI->getFalseBB());
  }
};
} // end anonymous namespace

ID SILPrinter::getID(const BasicBlock *Block) {
  // Lazily initialize the Blocks-to-IDs mapping.
  if (BlocksToIDMap.empty()) {
    unsigned idx = 0;
    for (const BasicBlock &B : *Block->getParent())
      BlocksToIDMap[&B] = idx++;
  }

  ID R = { ID::BasicBlock, BlocksToIDMap[Block], -1 };
  return R;
}

ID SILPrinter::getID(Value V) {
  // Lazily initialize the instruction -> ID mapping.
  if (ValueToIDMap.empty()) {
    const BasicBlock *ParentBB;
    if (const Instruction *I = dyn_cast<Instruction>(V))
      ParentBB = I->getParent();
    else
      ParentBB = cast<BBArgument>(V)->getParent();

    unsigned idx = 0;
    for (auto &BB : *ParentBB->getParent()) {
      for (auto I = BB.bbarg_begin(), E = BB.bbarg_end(); I != E; ++I)
        ValueToIDMap[*I] = idx++;

      for (auto &I : BB)
        ValueToIDMap[&I] = idx++;
    }
  }

  int ResultNumber = -1;
  if (V.getDef()->getTypes().size() > 1)
    ResultNumber = V.getResultNumber();

  ID R = { ID::SSAValue, ValueToIDMap[V], ResultNumber };
  return R;
}

//===----------------------------------------------------------------------===//
// Printing for Instruction, BasicBlock, and Function
//===----------------------------------------------------------------------===//

void ValueBase::dump() const {
  print(llvm::errs());
}

void ValueBase::print(raw_ostream &OS) const {
  SILPrinter(OS).print(this);
}

void BasicBlock::dump() const {
  print(llvm::errs());
}

/// Pretty-print the BasicBlock with the designated stream.
void BasicBlock::print(raw_ostream &OS) const {
  SILPrinter(OS).print(this);
}

/// Pretty-print the basic block.
void Function::dump() const {
  print(llvm::errs());
}

/// Pretty-print the basi block with the designated stream.
void Function::print(llvm::raw_ostream &OS) const {
  SILPrinter Printer(OS);
  for (const BasicBlock &B : *this)
    Printer.print(&B);
}

<commit_msg>fix some SILPrinter bugs handling results with multiple values.<commit_after>//===--- SILPrinter.cpp - Pretty-printing of SIL Code ---------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file defines the logic to pretty-print SIL, Instructions, etc.
//
//===----------------------------------------------------------------------===//

#include "swift/SIL/SILVisitor.h"
#include "swift/AST/Decl.h"
#include "swift/AST/Expr.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/raw_ostream.h"
using namespace swift;

struct ID {
  enum {
    BasicBlock, SSAValue
  } Kind;
  unsigned Number;
  int ResultNumber;
};

raw_ostream &operator<<(raw_ostream &OS, ID i) {
  switch (i.Kind) {
  case ID::BasicBlock: OS << "bb"; break;
  case ID::SSAValue: OS << '%'; break;
  }
  OS << i.Number;

  if (i.ResultNumber != -1)
    OS << '#' << i.ResultNumber;
  return OS;
}

namespace {
/// SILPrinter class - This is the internal implementation details of printing
/// for SIL structures.
class SILPrinter : public SILVisitor<SILPrinter> {
  raw_ostream &OS;

  llvm::DenseMap<const BasicBlock *, unsigned> BlocksToIDMap;
  ID getID(const BasicBlock *B);

  llvm::DenseMap<const ValueBase*, unsigned> ValueToIDMap;
  ID getID(Value V);

public:
  SILPrinter(raw_ostream &OS) : OS(OS) {
  }

  void print(const BasicBlock *BB) {
    OS << getID(BB);

    if (!BB->bbarg_empty()) {
      OS << '(';
      for (auto I = BB->bbarg_begin(), E = BB->bbarg_end(); I != E; ++I) {
        if (I != BB->bbarg_begin()) OS << ", ";
        OS << getID(*I) << " : " << (*I)->getType().getString();
      }
      OS << ')';
    }

    OS << ":\t";

    if (!BB->pred_empty()) {
      OS << " ; Preds:";
      for (auto BBI = BB->pred_begin(), E = BB->pred_end(); BBI != E; ++BBI)
        OS << ' ' << getID(*BBI);
    }
    OS << '\n';

    for (const Instruction &I : *BB)
      print(&I);

    OS << '\n';
  }

  //===--------------------------------------------------------------------===//
  // Instruction Printing Logic

  void print(Value V) {
    ID Name = getID(V);
    Name.ResultNumber = -1;  // Don't print subresult number.
    OS << "  " << Name << " = ";
    visit(V);
    OS << '\n';
  }
  void visitInstruction(Instruction *I) {
    assert(0 && "SILPrinter not implemented for this instruction!");
  }

  void visitAllocVarInst(AllocVarInst *AVI) {
    OS << "alloc_var " << AVI->getDecl()->getName()
       << ", type=" << AVI->getType().getString();

  }

  void visitAllocTmpInst(AllocTmpInst *ATI) {
    OS << "alloc_tmp type=" << ATI->getType().getString();
  }

  void visitAllocArrayInst(AllocArrayInst *AAI) {
    OS << "alloc_array element type=" << AAI->getElementType().getString()
       << ", " << getID(AAI->getNumElements());
  }

  void visitApplyInst(ApplyInst *AI) {
    OS << "apply " << getID(AI->getCallee()) << '(';
    bool first = true;
    for (auto arg : AI->getArguments()) {
      if (first)
        first = false;
      else
        OS << ", ";
      OS << getID(arg);
    }
    OS << ')';
  }

  void visitConstantRefInst(ConstantRefInst *DRI) {
    OS << "constantref " << DRI->getDecl()->getName()
    << ", type=" << DRI->getDecl()->getType().getString();
  }

  void visitZeroValueInst(ZeroValueInst *ZVI) {
    OS << "zerovalueinst " << ZVI->getType().getString();
  }

  void visitIntegerLiteralInst(IntegerLiteralInst *ILI) {
    const auto &lit = ILI->getValue();
    OS << "integerliteral " << lit << ", width=" << lit.getBitWidth();
  }
  void visitFloatLiteralInst(FloatLiteralInst *FLI) {
    SmallVector<char, 12> Buffer;
    FLI->getValue().toString(Buffer);
    OS << "floatliteral " << StringRef(Buffer.data(), Buffer.size());
  }
  void visitCharacterLiteralInst(CharacterLiteralInst *CLI) {
    OS << "characterliteral " << CLI->getValue();
  }
  void visitStringLiteralInst(StringLiteralInst *SLI) {
    OS << "stringliteral \"" << SLI->getValue() << "\"";
  }
  void visitLoadInst(LoadInst *LI) {
    OS << "load " << getID(LI->getLValue());
    if (LI->isTake())
      OS << " [take]";
  }
  void visitStoreInst(StoreInst *SI) {
    OS << "store " << getID(SI->getSrc()) << " -> "
       << getID(SI->getDest());
    if (SI->isInitialization())
      OS << " [initialization]";
  }
  void visitCopyInst(CopyInst *CI) {
    OS << "copy " << getID(CI->getSrc());
    if (CI->isTakeOfSrc())
      OS << " [take]";
    OS << " -> " << getID(CI->getDest());
    if (CI->isInitializationOfDest())
      OS << " [initialization]";
  }
  void visitSpecializeInst(SpecializeInst *SI) {
    OS << "specialize " << getID(SI->getOperand()) << " -> "
       << SI->getType().getString();
  }
  void visitTypeConversionInst(TypeConversionInst *TCI) {
    OS << "type_conversion " << getID(TCI->getOperand()) << " -> "
       << TCI->getType().getString();
  }
  void visitTupleInst(TupleInst *TI) {
    OS << "tuple (";
    bool isFirst = true;
    for (const auto &Elem : TI->getElements()) {
      if (isFirst)
        isFirst = false;
      else
        OS << ", ";
      OS << getID(Elem);
    }
    OS << ')';
  }
  void visitTupleElementInst(TupleElementInst *TEI) {
    OS << "tupleelement " << getID(TEI->getOperand()) << ", "
       << TEI->getFieldNo();
  }
  void visitMetatypeInst(MetatypeInst *MI) {
    OS << "metatype " << MI->getMetaType().getString();
  }

  void visitRetainInst(RetainInst *RI) {
    OS << "retain " << getID(RI->getOperand());
  }
  void visitReleaseInst(ReleaseInst *RI) {
    OS << "release " << getID(RI->getOperand());
  }
  void visitDeallocInst(DeallocInst *DI) {
    OS << "dealloc " << getID(DI->getOperand());
  }
  void visitDestroyInst(DestroyInst *DI) {
    OS << "destroy " << getID(DI->getOperand());
  }

  void visitIndexLValueInst(IndexLValueInst *ILI) {
    OS << "index_lvalue " << getID(ILI->getOperand()) << ", " <<ILI->getIndex();
  }

  void visitIntegerValueInst(IntegerValueInst *IVI) {
    OS << "integer_value " << IVI->getValue() << ", "
       << IVI->getType().getString();
  }

  void visitUnreachableInst(UnreachableInst *UI) {
    OS << "unreachable";
  }

  void visitReturnInst(ReturnInst *RI) {
    OS << "return " << '(' << getID(RI->getReturnValue()) << ')';
  }

  void visitBranchInst(BranchInst *UBI) {
    OS << "br " << getID(UBI->getDestBB());
  }

  void visitCondBranchInst(CondBranchInst *CBI) {
    OS << "condbranch " << getID(CBI->getCondition()) << ", "
       << getID(CBI->getTrueBB()) << ',' << getID(CBI->getFalseBB());
  }
};
} // end anonymous namespace

ID SILPrinter::getID(const BasicBlock *Block) {
  // Lazily initialize the Blocks-to-IDs mapping.
  if (BlocksToIDMap.empty()) {
    unsigned idx = 0;
    for (const BasicBlock &B : *Block->getParent())
      BlocksToIDMap[&B] = idx++;
  }

  ID R = { ID::BasicBlock, BlocksToIDMap[Block], -1 };
  return R;
}

ID SILPrinter::getID(Value V) {
  // Lazily initialize the instruction -> ID mapping.
  if (ValueToIDMap.empty()) {
    const BasicBlock *ParentBB;
    if (const Instruction *I = dyn_cast<Instruction>(V))
      ParentBB = I->getParent();
    else
      ParentBB = cast<BBArgument>(V)->getParent();

    unsigned idx = 0;
    for (auto &BB : *ParentBB->getParent()) {
      for (auto I = BB.bbarg_begin(), E = BB.bbarg_end(); I != E; ++I)
        ValueToIDMap[*I] = idx++;

      for (auto &I : BB)
        ValueToIDMap[&I] = idx++;
    }
  }

  int ResultNumber = -1;
  if (V.getDef()->getTypes().size() > 1)
    ResultNumber = V.getResultNumber();

  ID R = { ID::SSAValue, ValueToIDMap[V.getDef()], ResultNumber };
  return R;
}

//===----------------------------------------------------------------------===//
// Printing for Instruction, BasicBlock, and Function
//===----------------------------------------------------------------------===//

void ValueBase::dump() const {
  print(llvm::errs());
}

void ValueBase::print(raw_ostream &OS) const {
  SILPrinter(OS).print(this);
}

void BasicBlock::dump() const {
  print(llvm::errs());
}

/// Pretty-print the BasicBlock with the designated stream.
void BasicBlock::print(raw_ostream &OS) const {
  SILPrinter(OS).print(this);
}

/// Pretty-print the basic block.
void Function::dump() const {
  print(llvm::errs());
}

/// Pretty-print the basi block with the designated stream.
void Function::print(llvm::raw_ostream &OS) const {
  SILPrinter Printer(OS);
  for (const BasicBlock &B : *this)
    Printer.print(&B);
}

<|endoftext|>