<commit_before>//===-- DWARFASTParserSwift.cpp ---------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "DWARFASTParserSwift.h"

#include "DWARFCompileUnit.h"
#include "DWARFDIE.h"
#include "DWARFDebugInfo.h"
#include "DWARFDefines.h"
#include "SymbolFileDWARF.h"

#include "swift/AST/ASTContext.h"

#include "lldb/Utility/Status.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SwiftASTContext.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/SwiftLanguageRuntime.h"
#include "lldb/Utility/Log.h"

using namespace lldb;
using namespace lldb_private;

DWARFASTParserSwift::DWARFASTParserSwift(SwiftASTContext &ast) : m_ast(ast) {}

DWARFASTParserSwift::~DWARFASTParserSwift() {}

lldb::TypeSP DWARFASTParserSwift::ParseTypeFromDWARF(const SymbolContext &sc,
                                                     const DWARFDIE &die,
                                                     Log *log,
                                                     bool *type_is_new_ptr) {
  lldb::TypeSP type_sp;
  CompilerType compiler_type;
  Status error;

  Declaration decl;
  ConstString mangled_name;
  ConstString name;

  DWARFAttributes attributes;
  const size_t num_attributes = die.GetAttributes(attributes);
  DWARFFormValue type_attr;

  if (num_attributes > 0) {
    uint32_t i;
    for (i = 0; i < num_attributes; ++i) {
      const dw_attr_t attr = attributes.AttributeAtIndex(i);
      DWARFFormValue form_value;
      if (attributes.ExtractFormValueAtIndex(i, form_value)) {
        switch (attr) {
        case DW_AT_decl_file:
          decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(
              form_value.Unsigned()));
          break;
        case DW_AT_decl_line:
          decl.SetLine(form_value.Unsigned());
          break;
        case DW_AT_decl_column:
          decl.SetColumn(form_value.Unsigned());
          break;
        case DW_AT_name:
          name.SetCString(form_value.AsCString());
          break;
        case DW_AT_linkage_name:
        case DW_AT_MIPS_linkage_name:
          mangled_name.SetCString(form_value.AsCString());
          break;
        default:
          break;
        }
      }
    }
  }

  if (!mangled_name && name) {
    if (SwiftLanguageRuntime::IsSwiftMangledName(name.GetCString()))
      mangled_name = name;
    else {
      const char *type_name_cstr = name.GetCString();
      // TODO: remove this once all mangled names are always included for all
      // types in DWARF
      swift::ModuleDecl *swift_module = m_ast.GetModule(decl.GetFile(), error);
      if (swift_module)
        compiler_type = m_ast.FindType(type_name_cstr, swift_module);

      if (!compiler_type) {
        // Anything from the swift module might be in a DW_TAG_typedef with a
        // name of "Int"
        // so we shuld also check the swift module if we fail to find our type
        // until we get
        // <rdar://problem/15290346> fixed.
        compiler_type =
            m_ast.FindFirstType(type_name_cstr, ConstString("Swift"));
      }
    }
  }

  if (mangled_name) {
    // see if we parsed this type already
    type_sp = m_ast.GetCachedType(mangled_name);
    if (type_sp)
      return type_sp;

    // otherwise figure it out yourself
    compiler_type =
        m_ast.GetTypeFromMangledTypename(mangled_name.GetCString(), error);
  }

  if (!compiler_type && name) {
    if (name.GetStringRef().startswith("$swift.") ||
        name.GetStringRef().startswith(SwiftLanguageRuntime::GetCurrentMangledName("_TtBp").c_str())) {  // This is the RawPointerType, need to figure out its name from the AST.
      swift::ASTContext *swift_ast_ctx = m_ast.GetASTContext();
      if (swift_ast_ctx)
        compiler_type =
            CompilerType(swift_ast_ctx, swift_ast_ctx->TheRawPointerType);
      else {
        if (log) {
          const char *file_name = "<unknown>";
          SymbolFile *sym_file = m_ast.GetSymbolFile();
          if (sym_file) {
            ObjectFile *obj_file = sym_file->GetObjectFile();
            if (obj_file) {
              ModuleSP module_sp = obj_file->GetModule();
              if (module_sp)
                file_name = module_sp->GetFileSpec().GetFilename().AsCString();
            }
          }
          log->Printf("Got null AST context while looking up %s in %s.",
                      name.AsCString(), file_name);
        }
        return TypeSP();
      }
    }
  }

  switch (die.Tag()) {
  case DW_TAG_inlined_subroutine:
  case DW_TAG_subprogram:
  case DW_TAG_subroutine_type:
    if (!compiler_type || !compiler_type.IsFunctionType()) {
      // Make sure we at least have some function type. The mangling for the
      // "top_level_code"
      // is currently returning the emptyTupleType (originally "_TtT_") which is not a function type...
      compiler_type = m_ast.GetVoidFunctionType();
    }
    break;
  default:
    break;
  }

  if (compiler_type) {
    type_sp = TypeSP(new Type(
        die.GetID(), die.GetDWARF(), compiler_type.GetTypeName(),
        compiler_type.GetByteSize(nullptr), NULL, LLDB_INVALID_UID,
        Type::eEncodingIsUID, &decl, compiler_type, Type::eResolveStateFull));
  }

  // cache this type
  if (type_sp && mangled_name
      && SwiftLanguageRuntime::IsSwiftMangledName(mangled_name.GetCString()))
    m_ast.SetCachedType(mangled_name, type_sp);

  return type_sp;
}

Function *DWARFASTParserSwift::ParseFunctionFromDWARF(const SymbolContext &sc,
                                                      const DWARFDIE &die) {
  DWARFRangeList func_ranges;
  const char *name = NULL;
  const char *mangled = NULL;
  int decl_file = 0;
  int decl_line = 0;
  int decl_column = 0;
  int call_file = 0;
  int call_line = 0;
  int call_column = 0;
  DWARFExpression frame_base(die.GetCU());

  if (die.Tag() != DW_TAG_subprogram)
    return NULL;

  if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line,
                               decl_column, call_file, call_line, call_column,
                               &frame_base)) {
    // Union of all ranges in the function DIE (if the function is
    // discontiguous)
    SymbolFileDWARF *dwarf = die.GetDWARF();
    AddressRange func_range;
    lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0);
    lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0);
    if (lowest_func_addr != LLDB_INVALID_ADDRESS &&
        lowest_func_addr <= highest_func_addr) {
      ModuleSP module_sp(dwarf->GetObjectFile()->GetModule());
      func_range.GetBaseAddress().ResolveAddressUsingFileSections(
          lowest_func_addr, module_sp->GetSectionList());
      if (func_range.GetBaseAddress().IsValid())
        func_range.SetByteSize(highest_func_addr - lowest_func_addr);
    }

    if (func_range.GetBaseAddress().IsValid()) {
      Mangled func_name;
      if (mangled)
        func_name.SetValue(ConstString(mangled), true);
      else
        func_name.SetValue(ConstString(name), false);

      // See if this function can throw.  We can't get that from the
      // mangled name (even though the information is often there)
      // because Swift reserves the right to omit it from the name
      // if it doesn't need it.  So instead we look for the
      // DW_TAG_thrown_error:

      bool can_throw = false;

      DWARFDebugInfoEntry *child(die.GetFirstChild().GetDIE());
      while (child)
      {
        if (child->Tag() == DW_TAG_thrown_type)
        {
          can_throw = true;
          break;
        }
        child = child->GetSibling();
      }

      FunctionSP func_sp;
      std::unique_ptr<Declaration> decl_ap;
      if (decl_file != 0 || decl_line != 0 || decl_column != 0)
        decl_ap.reset(new Declaration(
            sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),
            decl_line, decl_column));

      if (dwarf->FixupAddress(func_range.GetBaseAddress())) {
        const user_id_t func_user_id = die.GetID();
        func_sp.reset(new Function(sc.comp_unit, func_user_id, func_user_id,
                                   func_name, nullptr,
                                   func_range, can_throw)); // first address range

        if (func_sp.get() != NULL) {
          if (frame_base.IsValid())
            func_sp->GetFrameBaseExpression() = frame_base;
          sc.comp_unit->AddFunction(func_sp);
          return func_sp.get();
        }
      }
    }
  }
  return NULL;
}

lldb_private::CompilerDeclContext
DWARFASTParserSwift::GetDeclContextForUIDFromDWARF(const DWARFDIE &die) {
  return CompilerDeclContext();
}

lldb_private::CompilerDeclContext
DWARFASTParserSwift::GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) {
  return CompilerDeclContext();
}
<commit_msg>fix typo in comment<commit_after>//===-- DWARFASTParserSwift.cpp ---------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#include "DWARFASTParserSwift.h"

#include "DWARFCompileUnit.h"
#include "DWARFDIE.h"
#include "DWARFDebugInfo.h"
#include "DWARFDefines.h"
#include "SymbolFileDWARF.h"

#include "swift/AST/ASTContext.h"

#include "lldb/Utility/Status.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SwiftASTContext.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Target/SwiftLanguageRuntime.h"
#include "lldb/Utility/Log.h"

using namespace lldb;
using namespace lldb_private;

DWARFASTParserSwift::DWARFASTParserSwift(SwiftASTContext &ast) : m_ast(ast) {}

DWARFASTParserSwift::~DWARFASTParserSwift() {}

lldb::TypeSP DWARFASTParserSwift::ParseTypeFromDWARF(const SymbolContext &sc,
                                                     const DWARFDIE &die,
                                                     Log *log,
                                                     bool *type_is_new_ptr) {
  lldb::TypeSP type_sp;
  CompilerType compiler_type;
  Status error;

  Declaration decl;
  ConstString mangled_name;
  ConstString name;

  DWARFAttributes attributes;
  const size_t num_attributes = die.GetAttributes(attributes);
  DWARFFormValue type_attr;

  if (num_attributes > 0) {
    uint32_t i;
    for (i = 0; i < num_attributes; ++i) {
      const dw_attr_t attr = attributes.AttributeAtIndex(i);
      DWARFFormValue form_value;
      if (attributes.ExtractFormValueAtIndex(i, form_value)) {
        switch (attr) {
        case DW_AT_decl_file:
          decl.SetFile(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(
              form_value.Unsigned()));
          break;
        case DW_AT_decl_line:
          decl.SetLine(form_value.Unsigned());
          break;
        case DW_AT_decl_column:
          decl.SetColumn(form_value.Unsigned());
          break;
        case DW_AT_name:
          name.SetCString(form_value.AsCString());
          break;
        case DW_AT_linkage_name:
        case DW_AT_MIPS_linkage_name:
          mangled_name.SetCString(form_value.AsCString());
          break;
        default:
          break;
        }
      }
    }
  }

  if (!mangled_name && name) {
    if (SwiftLanguageRuntime::IsSwiftMangledName(name.GetCString()))
      mangled_name = name;
    else {
      const char *type_name_cstr = name.GetCString();
      // TODO: remove this once all mangled names are always included for all
      // types in DWARF
      swift::ModuleDecl *swift_module = m_ast.GetModule(decl.GetFile(), error);
      if (swift_module)
        compiler_type = m_ast.FindType(type_name_cstr, swift_module);

      if (!compiler_type) {
        // Anything from the swift module might be in a DW_TAG_typedef with a
        // name of "Int"
        // so we shuld also check the swift module if we fail to find our type
        // until we get
        // <rdar://problem/15290346> fixed.
        compiler_type =
            m_ast.FindFirstType(type_name_cstr, ConstString("Swift"));
      }
    }
  }

  if (mangled_name) {
    // see if we parsed this type already
    type_sp = m_ast.GetCachedType(mangled_name);
    if (type_sp)
      return type_sp;

    // otherwise figure it out yourself
    compiler_type =
        m_ast.GetTypeFromMangledTypename(mangled_name.GetCString(), error);
  }

  if (!compiler_type && name) {
    if (name.GetStringRef().startswith("$swift.") ||
        name.GetStringRef().startswith(SwiftLanguageRuntime::GetCurrentMangledName("_TtBp").c_str())) {  // This is the RawPointerType, need to figure out its name from the AST.
      swift::ASTContext *swift_ast_ctx = m_ast.GetASTContext();
      if (swift_ast_ctx)
        compiler_type =
            CompilerType(swift_ast_ctx, swift_ast_ctx->TheRawPointerType);
      else {
        if (log) {
          const char *file_name = "<unknown>";
          SymbolFile *sym_file = m_ast.GetSymbolFile();
          if (sym_file) {
            ObjectFile *obj_file = sym_file->GetObjectFile();
            if (obj_file) {
              ModuleSP module_sp = obj_file->GetModule();
              if (module_sp)
                file_name = module_sp->GetFileSpec().GetFilename().AsCString();
            }
          }
          log->Printf("Got null AST context while looking up %s in %s.",
                      name.AsCString(), file_name);
        }
        return TypeSP();
      }
    }
  }

  switch (die.Tag()) {
  case DW_TAG_inlined_subroutine:
  case DW_TAG_subprogram:
  case DW_TAG_subroutine_type:
    if (!compiler_type || !compiler_type.IsFunctionType()) {
      // Make sure we at least have some function type. The mangling for the
      // "top_level_code"
      // is currently returning the emptyTupleType (originally "_TtT_") which is not a function type...
      compiler_type = m_ast.GetVoidFunctionType();
    }
    break;
  default:
    break;
  }

  if (compiler_type) {
    type_sp = TypeSP(new Type(
        die.GetID(), die.GetDWARF(), compiler_type.GetTypeName(),
        compiler_type.GetByteSize(nullptr), NULL, LLDB_INVALID_UID,
        Type::eEncodingIsUID, &decl, compiler_type, Type::eResolveStateFull));
  }

  // cache this type
  if (type_sp && mangled_name
      && SwiftLanguageRuntime::IsSwiftMangledName(mangled_name.GetCString()))
    m_ast.SetCachedType(mangled_name, type_sp);

  return type_sp;
}

Function *DWARFASTParserSwift::ParseFunctionFromDWARF(const SymbolContext &sc,
                                                      const DWARFDIE &die) {
  DWARFRangeList func_ranges;
  const char *name = NULL;
  const char *mangled = NULL;
  int decl_file = 0;
  int decl_line = 0;
  int decl_column = 0;
  int call_file = 0;
  int call_line = 0;
  int call_column = 0;
  DWARFExpression frame_base(die.GetCU());

  if (die.Tag() != DW_TAG_subprogram)
    return NULL;

  if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line,
                               decl_column, call_file, call_line, call_column,
                               &frame_base)) {
    // Union of all ranges in the function DIE (if the function is
    // discontiguous)
    SymbolFileDWARF *dwarf = die.GetDWARF();
    AddressRange func_range;
    lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0);
    lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0);
    if (lowest_func_addr != LLDB_INVALID_ADDRESS &&
        lowest_func_addr <= highest_func_addr) {
      ModuleSP module_sp(dwarf->GetObjectFile()->GetModule());
      func_range.GetBaseAddress().ResolveAddressUsingFileSections(
          lowest_func_addr, module_sp->GetSectionList());
      if (func_range.GetBaseAddress().IsValid())
        func_range.SetByteSize(highest_func_addr - lowest_func_addr);
    }

    if (func_range.GetBaseAddress().IsValid()) {
      Mangled func_name;
      if (mangled)
        func_name.SetValue(ConstString(mangled), true);
      else
        func_name.SetValue(ConstString(name), false);

      // See if this function can throw.  We can't get that from the
      // mangled name (even though the information is often there)
      // because Swift reserves the right to omit it from the name
      // if it doesn't need it.  So instead we look for the
      // DW_TAG_thrown_type:

      bool can_throw = false;

      DWARFDebugInfoEntry *child(die.GetFirstChild().GetDIE());
      while (child)
      {
        if (child->Tag() == DW_TAG_thrown_type)
        {
          can_throw = true;
          break;
        }
        child = child->GetSibling();
      }

      FunctionSP func_sp;
      std::unique_ptr<Declaration> decl_ap;
      if (decl_file != 0 || decl_line != 0 || decl_column != 0)
        decl_ap.reset(new Declaration(
            sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file),
            decl_line, decl_column));

      if (dwarf->FixupAddress(func_range.GetBaseAddress())) {
        const user_id_t func_user_id = die.GetID();
        func_sp.reset(new Function(sc.comp_unit, func_user_id, func_user_id,
                                   func_name, nullptr,
                                   func_range, can_throw)); // first address range

        if (func_sp.get() != NULL) {
          if (frame_base.IsValid())
            func_sp->GetFrameBaseExpression() = frame_base;
          sc.comp_unit->AddFunction(func_sp);
          return func_sp.get();
        }
      }
    }
  }
  return NULL;
}

lldb_private::CompilerDeclContext
DWARFASTParserSwift::GetDeclContextForUIDFromDWARF(const DWARFDIE &die) {
  return CompilerDeclContext();
}

lldb_private::CompilerDeclContext
DWARFASTParserSwift::GetDeclContextContainingUIDFromDWARF(const DWARFDIE &die) {
  return CompilerDeclContext();
}
<|endoftext|>


<commit_before>// Copyright 2012 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 "subprocess.h"

#include "test.h"

#ifndef _WIN32
// SetWithLots need setrlimit.
#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#endif

namespace {

#ifdef _WIN32
const char* kSimpleCommand = "cmd /c dir \\";
#else
const char* kSimpleCommand = "ls /";
#endif

struct SubprocessTest : public testing::Test {
  SubprocessSet subprocs_;
};

}  // anonymous namespace

// Run a command that fails and emits to stderr.
TEST_F(SubprocessTest, BadCommandStderr) {
  Subprocess* subproc = subprocs_.Add("cmd /c ninja_no_such_command");
  ASSERT_NE((Subprocess *) 0, subproc);

  while (!subproc->Done()) {
    // Pretend we discovered that stderr was ready for writing.
    subprocs_.DoWork();
  }

  EXPECT_EQ(ExitFailure, subproc->Finish());
  EXPECT_NE("", subproc->GetOutput());
}

// Run a command that does not exist
TEST_F(SubprocessTest, NoSuchCommand) {
  Subprocess* subproc = subprocs_.Add("ninja_no_such_command");
  ASSERT_NE((Subprocess *) 0, subproc);

  while (!subproc->Done()) {
    // Pretend we discovered that stderr was ready for writing.
    subprocs_.DoWork();
  }

  EXPECT_EQ(ExitFailure, subproc->Finish());
  EXPECT_NE("", subproc->GetOutput());
#ifdef _WIN32
  ASSERT_EQ("CreateProcess failed: The system cannot find the file "
            "specified.\n", subproc->GetOutput());
#endif
}

#ifndef _WIN32

TEST_F(SubprocessTest, InterruptChild) {
  Subprocess* subproc = subprocs_.Add("kill -INT $$");
  ASSERT_NE((Subprocess *) 0, subproc);

  while (!subproc->Done()) {
    subprocs_.DoWork();
  }

  EXPECT_EQ(ExitInterrupted, subproc->Finish());
}

TEST_F(SubprocessTest, InterruptParent) {
  Subprocess* subproc = subprocs_.Add("kill -INT $PPID ; sleep 1");
  ASSERT_NE((Subprocess *) 0, subproc);

  while (!subproc->Done()) {
    bool interrupted = subprocs_.DoWork();
    if (interrupted)
      return;
  }

  ASSERT_FALSE("We should have been interrupted");
}

TEST_F(SubprocessTest, Console) {
  // Skip test if we don't have the console ourselves.
  if (isatty(0) && isatty(1) && isatty(2)) {
    Subprocess* subproc = subprocs_.Add("test -t 0 -a -t 1 -a -t 2",
                                        /*use_console=*/true);
    ASSERT_NE((Subprocess *) 0, subproc);

    while (!subproc->Done()) {
      subprocs_.DoWork();
    }

    EXPECT_EQ(ExitSuccess, subproc->Finish());
  }
}

#endif

TEST_F(SubprocessTest, SetWithSingle) {
  Subprocess* subproc = subprocs_.Add(kSimpleCommand);
  ASSERT_NE((Subprocess *) 0, subproc);

  while (!subproc->Done()) {
    subprocs_.DoWork();
  }
  ASSERT_EQ(ExitSuccess, subproc->Finish());
  ASSERT_NE("", subproc->GetOutput());

  ASSERT_EQ(1u, subprocs_.finished_.size());
}

TEST_F(SubprocessTest, SetWithMulti) {
  Subprocess* processes[3];
  const char* kCommands[3] = {
    kSimpleCommand,
#ifdef _WIN32
    "cmd /c echo hi",
    "cmd /c time /t",
#else
    "whoami",
    "pwd",
#endif
  };

  for (int i = 0; i < 3; ++i) {
    processes[i] = subprocs_.Add(kCommands[i]);
    ASSERT_NE((Subprocess *) 0, processes[i]);
  }

  ASSERT_EQ(3u, subprocs_.running_.size());
  for (int i = 0; i < 3; ++i) {
    ASSERT_FALSE(processes[i]->Done());
    ASSERT_EQ("", processes[i]->GetOutput());
  }

  while (!processes[0]->Done() || !processes[1]->Done() ||
         !processes[2]->Done()) {
    ASSERT_GT(subprocs_.running_.size(), 0u);
    subprocs_.DoWork();
  }

  ASSERT_EQ(0u, subprocs_.running_.size());
  ASSERT_EQ(3u, subprocs_.finished_.size());

  for (int i = 0; i < 3; ++i) {
    ASSERT_EQ(ExitSuccess, processes[i]->Finish());
    ASSERT_NE("", processes[i]->GetOutput());
    delete processes[i];
  }
}

// OS X's process limit is less than 1025 by default
// (|sysctl kern.maxprocperuid| is 709 on 10.7 and 10.8 and less prior to that).
#if !defined(__APPLE__) && !defined(_WIN32)
TEST_F(SubprocessTest, SetWithLots) {
  // Arbitrary big number; needs to be over 1024 to confirm we're no longer
  // hostage to pselect.
  const size_t kNumProcs = 1025;

  // Make sure [ulimit -n] isn't going to stop us from working.
  rlimit rlim;
  ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &rlim));
  if (!EXPECT_GT(rlim.rlim_cur, kNumProcs)) {
    printf("Raise [ulimit -n] well above %u to make this test go\n", kNumProcs);
    return;
  }

  vector<Subprocess*> procs;
  for (size_t i = 0; i < kNumProcs; ++i) {
    Subprocess* subproc = subprocs_.Add("/bin/echo");
    ASSERT_NE((Subprocess *) 0, subproc);
    procs.push_back(subproc);
  }
  while (!subprocs_.running_.empty())
    subprocs_.DoWork();
  for (size_t i = 0; i < procs.size(); ++i) {
    ASSERT_EQ(ExitSuccess, procs[i]->Finish());
    ASSERT_NE("", procs[i]->GetOutput());
  }
  ASSERT_EQ(kNumProcs, subprocs_.finished_.size());
}
#endif  // !__APPLE__ && !_WIN32

// TODO: this test could work on Windows, just not sure how to simply
// read stdin.
#ifndef _WIN32
// Verify that a command that attempts to read stdin correctly thinks
// that stdin is closed.
TEST_F(SubprocessTest, ReadStdin) {
  Subprocess* subproc = subprocs_.Add("cat -");
  while (!subproc->Done()) {
    subprocs_.DoWork();
  }
  ASSERT_EQ(ExitSuccess, subproc->Finish());
  ASSERT_EQ(1u, subprocs_.finished_.size());
}
#endif  // _WIN32
<commit_msg>fix warning<commit_after>// Copyright 2012 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 "subprocess.h"

#include "test.h"

#ifndef _WIN32
// SetWithLots need setrlimit.
#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#endif

namespace {

#ifdef _WIN32
const char* kSimpleCommand = "cmd /c dir \\";
#else
const char* kSimpleCommand = "ls /";
#endif

struct SubprocessTest : public testing::Test {
  SubprocessSet subprocs_;
};

}  // anonymous namespace

// Run a command that fails and emits to stderr.
TEST_F(SubprocessTest, BadCommandStderr) {
  Subprocess* subproc = subprocs_.Add("cmd /c ninja_no_such_command");
  ASSERT_NE((Subprocess *) 0, subproc);

  while (!subproc->Done()) {
    // Pretend we discovered that stderr was ready for writing.
    subprocs_.DoWork();
  }

  EXPECT_EQ(ExitFailure, subproc->Finish());
  EXPECT_NE("", subproc->GetOutput());
}

// Run a command that does not exist
TEST_F(SubprocessTest, NoSuchCommand) {
  Subprocess* subproc = subprocs_.Add("ninja_no_such_command");
  ASSERT_NE((Subprocess *) 0, subproc);

  while (!subproc->Done()) {
    // Pretend we discovered that stderr was ready for writing.
    subprocs_.DoWork();
  }

  EXPECT_EQ(ExitFailure, subproc->Finish());
  EXPECT_NE("", subproc->GetOutput());
#ifdef _WIN32
  ASSERT_EQ("CreateProcess failed: The system cannot find the file "
            "specified.\n", subproc->GetOutput());
#endif
}

#ifndef _WIN32

TEST_F(SubprocessTest, InterruptChild) {
  Subprocess* subproc = subprocs_.Add("kill -INT $$");
  ASSERT_NE((Subprocess *) 0, subproc);

  while (!subproc->Done()) {
    subprocs_.DoWork();
  }

  EXPECT_EQ(ExitInterrupted, subproc->Finish());
}

TEST_F(SubprocessTest, InterruptParent) {
  Subprocess* subproc = subprocs_.Add("kill -INT $PPID ; sleep 1");
  ASSERT_NE((Subprocess *) 0, subproc);

  while (!subproc->Done()) {
    bool interrupted = subprocs_.DoWork();
    if (interrupted)
      return;
  }

  ASSERT_FALSE("We should have been interrupted");
}

TEST_F(SubprocessTest, Console) {
  // Skip test if we don't have the console ourselves.
  if (isatty(0) && isatty(1) && isatty(2)) {
    Subprocess* subproc = subprocs_.Add("test -t 0 -a -t 1 -a -t 2",
                                        /*use_console=*/true);
    ASSERT_NE((Subprocess *) 0, subproc);

    while (!subproc->Done()) {
      subprocs_.DoWork();
    }

    EXPECT_EQ(ExitSuccess, subproc->Finish());
  }
}

#endif

TEST_F(SubprocessTest, SetWithSingle) {
  Subprocess* subproc = subprocs_.Add(kSimpleCommand);
  ASSERT_NE((Subprocess *) 0, subproc);

  while (!subproc->Done()) {
    subprocs_.DoWork();
  }
  ASSERT_EQ(ExitSuccess, subproc->Finish());
  ASSERT_NE("", subproc->GetOutput());

  ASSERT_EQ(1u, subprocs_.finished_.size());
}

TEST_F(SubprocessTest, SetWithMulti) {
  Subprocess* processes[3];
  const char* kCommands[3] = {
    kSimpleCommand,
#ifdef _WIN32
    "cmd /c echo hi",
    "cmd /c time /t",
#else
    "whoami",
    "pwd",
#endif
  };

  for (int i = 0; i < 3; ++i) {
    processes[i] = subprocs_.Add(kCommands[i]);
    ASSERT_NE((Subprocess *) 0, processes[i]);
  }

  ASSERT_EQ(3u, subprocs_.running_.size());
  for (int i = 0; i < 3; ++i) {
    ASSERT_FALSE(processes[i]->Done());
    ASSERT_EQ("", processes[i]->GetOutput());
  }

  while (!processes[0]->Done() || !processes[1]->Done() ||
         !processes[2]->Done()) {
    ASSERT_GT(subprocs_.running_.size(), 0u);
    subprocs_.DoWork();
  }

  ASSERT_EQ(0u, subprocs_.running_.size());
  ASSERT_EQ(3u, subprocs_.finished_.size());

  for (int i = 0; i < 3; ++i) {
    ASSERT_EQ(ExitSuccess, processes[i]->Finish());
    ASSERT_NE("", processes[i]->GetOutput());
    delete processes[i];
  }
}

// OS X's process limit is less than 1025 by default
// (|sysctl kern.maxprocperuid| is 709 on 10.7 and 10.8 and less prior to that).
#if !defined(__APPLE__) && !defined(_WIN32)
TEST_F(SubprocessTest, SetWithLots) {
  // Arbitrary big number; needs to be over 1024 to confirm we're no longer
  // hostage to pselect.
  const unsigned kNumProcs = 1025;

  // Make sure [ulimit -n] isn't going to stop us from working.
  rlimit rlim;
  ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &rlim));
  if (!EXPECT_GT(rlim.rlim_cur, kNumProcs)) {
    printf("Raise [ulimit -n] well above %u to make this test go\n", kNumProcs);
    return;
  }

  vector<Subprocess*> procs;
  for (size_t i = 0; i < kNumProcs; ++i) {
    Subprocess* subproc = subprocs_.Add("/bin/echo");
    ASSERT_NE((Subprocess *) 0, subproc);
    procs.push_back(subproc);
  }
  while (!subprocs_.running_.empty())
    subprocs_.DoWork();
  for (size_t i = 0; i < procs.size(); ++i) {
    ASSERT_EQ(ExitSuccess, procs[i]->Finish());
    ASSERT_NE("", procs[i]->GetOutput());
  }
  ASSERT_EQ(kNumProcs, subprocs_.finished_.size());
}
#endif  // !__APPLE__ && !_WIN32

// TODO: this test could work on Windows, just not sure how to simply
// read stdin.
#ifndef _WIN32
// Verify that a command that attempts to read stdin correctly thinks
// that stdin is closed.
TEST_F(SubprocessTest, ReadStdin) {
  Subprocess* subproc = subprocs_.Add("cat -");
  while (!subproc->Done()) {
    subprocs_.DoWork();
  }
  ASSERT_EQ(ExitSuccess, subproc->Finish());
  ASSERT_EQ(1u, subprocs_.finished_.size());
}
#endif  // _WIN32
<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN
#include "catch.hpp"

#include "../src/cxxopts.hpp"

class Argv {
  public:

  Argv(int n, const char** argv)
  : m_argv(new char*[n])
  {
    for (int i = 0; i != n; ++i) {
      auto len = strlen(argv[i]) + 1;
      auto ptr = std::unique_ptr<char[]>(new char[len]);

      strcpy(ptr.get(), argv[i]);
      m_args.push_back(std::move(ptr));
      m_argv.get()[i] = m_args.back().get();
    }
  }

  char** argv() const {
    return m_argv.get();
  }

  private:

  std::vector<std::unique_ptr<char[]>> m_args;
  std::unique_ptr<char*[]> m_argv;
};

TEST_CASE("Basic options", "[options]")
{

  cxxopts::Options options("tester", " - test basic options");

  options.add_options()
    ("long", "a long option")
    ("s,short", "a short option")
    ("value", "an option with a value", cxxopts::value<std::string>())
    ("a,av", "a short option with a value", cxxopts::value<std::string>());

  const char* args[] = {
    "tester",
    "--long",
    "-s",
    "--value",
    "value",
    "-a",
    "b"
  };

  int argc = sizeof(args) / sizeof(args[0]);

  Argv argv(argc, args);

  char** actual_argv = argv.argv();

  options.parse(argc, actual_argv);

  CHECK(options.count("long") == 1);
}
<commit_msg>add some more tests<commit_after>#define CATCH_CONFIG_MAIN
#include "catch.hpp"

#include "../src/cxxopts.hpp"

class Argv {
  public:

  Argv(int n, const char** argv)
  : m_argv(new char*[n])
  {
    for (int i = 0; i != n; ++i) {
      auto len = strlen(argv[i]) + 1;
      auto ptr = std::unique_ptr<char[]>(new char[len]);

      strcpy(ptr.get(), argv[i]);
      m_args.push_back(std::move(ptr));
      m_argv.get()[i] = m_args.back().get();
    }
  }

  char** argv() const {
    return m_argv.get();
  }

  private:

  std::vector<std::unique_ptr<char[]>> m_args;
  std::unique_ptr<char*[]> m_argv;
};

TEST_CASE("Basic options", "[options]")
{

  cxxopts::Options options("tester", " - test basic options");

  options.add_options()
    ("long", "a long option")
    ("s,short", "a short option")
    ("value", "an option with a value", cxxopts::value<std::string>())
    ("a,av", "a short option with a value", cxxopts::value<std::string>());

  const char* args[] = {
    "tester",
    "--long",
    "-s",
    "--value",
    "value",
    "-a",
    "b"
  };

  int argc = sizeof(args) / sizeof(args[0]);

  Argv argv(argc, args);

  char** actual_argv = argv.argv();

  options.parse(argc, actual_argv);

  CHECK(options.count("long") == 1);
  CHECK(options.count("s") == 1);
  CHECK(options.count("value") == 1);
  CHECK(options.count("a") == 1);
  CHECK(options["value"].as<std::string>() == "value");
  CHECK(options["a"].as<std::string>() == "b");
}
<|endoftext|>


<commit_before>/* Copyright (c) 2010-2013, AOYAMA Kazuharu
 * All rights reserved.
 *
 * This software may be used and distributed according to the terms of
 * the New BSD License, which is incorporated herein by reference.
 */

#include <TAbstractModel>
#include <TSqlObject>
#include <TModelObject>

/*!
  \class TAbstractModel
  \brief The TAbstractModel class is the abstract base class of models,
  providing functionality common to models.
*/

/*!
  Returns true if this model is null; otherwise returns false.
 */
bool TAbstractModel::isNull() const
{
    return mdata()->isNull();
}

/*!
  Returns true if this model is new, not created; otherwise returns false.
 */
bool TAbstractModel::isNew() const
{
    return mdata()->isNull();
}

/*!
  Returns true if this model is not saved; otherwise returns false.
 */
bool TAbstractModel::isSaved() const
{
    return !mdata()->isNull();
}

/*!
  Creates the model as a new data to the data storage.
 */
bool TAbstractModel::create()
{
    return mdata()->create();
}

/*!
  Saves the model to the data storage.

  If the model exists in the data storage, calls update();
  otherwise calls create().
 */
bool TAbstractModel::save()
{
    return (mdata()->isNull()) ? mdata()->create() : mdata()->update();
}

/*!
  Updates the model to the data storage.
 */
bool TAbstractModel::update()
{
    return mdata()->update();
}

/*!
  Removes the model from the data storage.
 */
bool TAbstractModel::remove()
{
    return mdata()->remove();
}

/*!
  Returns a map with all properties of this text format.
 */
QVariantMap TAbstractModel::toVariantMap() const
{
    QVariantMap ret;

    QVariantMap map = mdata()->toVariantMap();
    for (QMapIterator<QString, QVariant> it(map); it.hasNext(); ) {
        it.next();
        ret.insert(fieldNameToVariableName(it.key()), it.value());
    }
    return ret;
}

/*!
  Sets the \a properties.
 */
void TAbstractModel::setProperties(const QVariantMap &properties)
{
    // Creates a map of the original property name and the converted name
    QStringList soprops = mdata()->propertyNames();
    QMap<QString, QString> sopropMap;
    for (QStringListIterator it(soprops); it.hasNext(); ) {
        const QString &orig = it.next();
        sopropMap.insert(fieldNameToVariableName(orig), orig);
    }

    QVariantMap props;
    for (QMapIterator<QString, QVariant> it(properties); it.hasNext(); ) {
        it.next();
        const QString &p = sopropMap[it.key()];
        if (!p.isEmpty()) {
            props.insert(p, it.value());
        }
    }

    mdata()->setProperties(props);
}

/*!
  \fn virtual TModelObject *TAbstractModel::modelData()

  This function is reimplemented in subclasses to return a pointer
  to the data stored in the model object.
*/

/*!
  \fn virtual const TModelObject *TAbstractModel::modelData() const

  This function is reimplemented in subclasses to return a pointer
  to the data stored in the model object.
*/

TModelObject *TAbstractModel::mdata()
{
    return modelData() ? modelData() : data();
}

const TModelObject *TAbstractModel::mdata() const
{
    return modelData() ? modelData() : data();
}
<commit_msg>modified save() function to call create() instead of mdata()->create().<commit_after>/* Copyright (c) 2010-2013, AOYAMA Kazuharu
 * All rights reserved.
 *
 * This software may be used and distributed according to the terms of
 * the New BSD License, which is incorporated herein by reference.
 */

#include <TAbstractModel>
#include <TSqlObject>
#include <TModelObject>

/*!
  \class TAbstractModel
  \brief The TAbstractModel class is the abstract base class of models,
  providing functionality common to models.
*/

/*!
  Returns true if this model is null; otherwise returns false.
 */
bool TAbstractModel::isNull() const
{
    return mdata()->isNull();
}

/*!
  Returns true if this model is new, not created; otherwise returns false.
 */
bool TAbstractModel::isNew() const
{
    return mdata()->isNull();
}

/*!
  Returns true if this model is not saved; otherwise returns false.
 */
bool TAbstractModel::isSaved() const
{
    return !mdata()->isNull();
}

/*!
  Creates the model as a new data to the data storage.
 */
bool TAbstractModel::create()
{
    return mdata()->create();
}

/*!
  Saves the model to the data storage.

  If the model exists in the data storage, calls update();
  otherwise calls create().
 */
bool TAbstractModel::save()
{
    return (mdata()->isNull()) ? create() : update();
}

/*!
  Updates the model to the data storage.
 */
bool TAbstractModel::update()
{
    return mdata()->update();
}

/*!
  Removes the model from the data storage.
 */
bool TAbstractModel::remove()
{
    return mdata()->remove();
}

/*!
  Returns a map with all properties of this text format.
 */
QVariantMap TAbstractModel::toVariantMap() const
{
    QVariantMap ret;

    QVariantMap map = mdata()->toVariantMap();
    for (QMapIterator<QString, QVariant> it(map); it.hasNext(); ) {
        it.next();
        ret.insert(fieldNameToVariableName(it.key()), it.value());
    }
    return ret;
}

/*!
  Sets the \a properties.
 */
void TAbstractModel::setProperties(const QVariantMap &properties)
{
    // Creates a map of the original property name and the converted name
    QStringList soprops = mdata()->propertyNames();
    QMap<QString, QString> sopropMap;
    for (QStringListIterator it(soprops); it.hasNext(); ) {
        const QString &orig = it.next();
        sopropMap.insert(fieldNameToVariableName(orig), orig);
    }

    QVariantMap props;
    for (QMapIterator<QString, QVariant> it(properties); it.hasNext(); ) {
        it.next();
        const QString &p = sopropMap[it.key()];
        if (!p.isEmpty()) {
            props.insert(p, it.value());
        }
    }

    mdata()->setProperties(props);
}

/*!
  \fn virtual TModelObject *TAbstractModel::modelData()

  This function is reimplemented in subclasses to return a pointer
  to the data stored in the model object.
*/

/*!
  \fn virtual const TModelObject *TAbstractModel::modelData() const

  This function is reimplemented in subclasses to return a pointer
  to the data stored in the model object.
*/

TModelObject *TAbstractModel::mdata()
{
    return modelData() ? modelData() : data();
}

const TModelObject *TAbstractModel::mdata() const
{
    return modelData() ? modelData() : data();
}
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"

template<typename MatrixType> void product(const MatrixType& m)
{
  /* this test covers the following files:
     Identity.h Product.h
  */

  typedef typename MatrixType::Scalar Scalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;

  int rows = m.rows();
  int cols = m.cols();

  // this test relies a lot on Random.h, and there's not much more that we can do
  // to test it, hence I consider that we will have tested Random.h
  MatrixType m1 = MatrixType::random(rows, cols),
             m2 = MatrixType::random(rows, cols),
             m3(rows, cols),
             mzero = MatrixType::zero(rows, cols);
  SquareMatrixType
             identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
                              ::identity(rows, rows),
             square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
                              ::random(rows, rows);
  VectorType v1 = VectorType::random(rows),
             v2 = VectorType::random(rows),
             vzero = VectorType::zero(rows);

  Scalar s1 = ei_random<Scalar>();

  int r = ei_random<int>(0, rows-1),
      c = ei_random<int>(0, cols-1);

  // begin testing Product.h: only associativity for now
  // (we use Transpose.h but this doesn't count as a test for it)
  VERIFY_IS_APPROX((m1*m1.transpose())*m2,  m1*(m1.transpose()*m2));
  m3 = m1;
  m3 *= (m1.transpose() * m2);
  VERIFY_IS_APPROX(m3,                      m1 * (m1.transpose()*m2));
  VERIFY_IS_APPROX(m3,                      m1.lazy() * (m1.transpose()*m2));

  // continue testing Product.h: distributivity
  VERIFY_IS_APPROX(square*(m1 + m2),        square*m1+square*m2);
  VERIFY_IS_APPROX(square*(m1 - m2),        square*m1-square*m2);

  // continue testing Product.h: compatibility with ScalarMultiple.h
  VERIFY_IS_APPROX(s1*(square*m1),          (s1*square)*m1);
  VERIFY_IS_APPROX(s1*(square*m1),          square*(m1*s1));

  // continue testing Product.h: lazy product
  VERIFY_IS_APPROX(square.lazy() * m1,  square*m1);
  VERIFY_IS_APPROX(square * m1.lazy(),  square*m1);
  // again, test operator() to check const-qualification
  s1 += (square.lazy() * m1)(r,c);

  // test Product.h together with Identity.h
  VERIFY_IS_APPROX(m1,                      identity*m1);
  VERIFY_IS_APPROX(v1,                      identity*v1);
  // again, test operator() to check const-qualification
  VERIFY_IS_APPROX(MatrixType::identity(rows, cols)(r,c), static_cast<Scalar>(r==c));

  if (rows!=cols)
    VERIFY_RAISES_ASSERT(m3 = m1*m1);
}

void test_product()
{
//   for(int i = 0; i < g_repeat; i++) {
//     CALL_SUBTEST( product(Matrix<float, 1, 1>()) );
//     CALL_SUBTEST( product(Matrix<float, 3, 3>()) );
//     CALL_SUBTEST( product(Matrix<float, 4, 2>()) );
//     CALL_SUBTEST( product(Matrix4d()) );
//   }
  for(int i = 0; i < g_repeat; i++) {
    int rows = ei_random<int>(1,320);
    int cols = ei_random<int>(1,320);
    std::cout << "test MatrixXf " << rows << "x" << cols << "\n";
    CALL_SUBTEST( product(MatrixXf(rows, cols)) );
    std::cout << "test MatrixXd " << rows << "x" << cols << "\n";
    CALL_SUBTEST( product(MatrixXd(rows, cols)) );
//     CALL_SUBTEST( product(MatrixXi(rows, cols)) );
//     CALL_SUBTEST( product(MatrixXcf(rows, cols)) );
//     CALL_SUBTEST( product(MatrixXcd(rows, cols)) );
  }
}
<commit_msg>restored the product test<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra. Eigen itself is part of the KDE project.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob@math.jussieu.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"

template<typename MatrixType> void product(const MatrixType& m)
{
  /* this test covers the following files:
     Identity.h Product.h
  */

  typedef typename MatrixType::Scalar Scalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;

  int rows = m.rows();
  int cols = m.cols();

  // this test relies a lot on Random.h, and there's not much more that we can do
  // to test it, hence I consider that we will have tested Random.h
  MatrixType m1 = MatrixType::random(rows, cols),
             m2 = MatrixType::random(rows, cols),
             m3(rows, cols),
             mzero = MatrixType::zero(rows, cols);
  SquareMatrixType
             identity = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
                              ::identity(rows, rows),
             square = Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime>
                              ::random(rows, rows);
  VectorType v1 = VectorType::random(rows),
             v2 = VectorType::random(rows),
             vzero = VectorType::zero(rows);

  Scalar s1 = ei_random<Scalar>();

  int r = ei_random<int>(0, rows-1),
      c = ei_random<int>(0, cols-1);

  // begin testing Product.h: only associativity for now
  // (we use Transpose.h but this doesn't count as a test for it)
  VERIFY_IS_APPROX((m1*m1.transpose())*m2,  m1*(m1.transpose()*m2));
  m3 = m1;
  m3 *= (m1.transpose() * m2);
  VERIFY_IS_APPROX(m3,                      m1 * (m1.transpose()*m2));
  VERIFY_IS_APPROX(m3,                      m1.lazy() * (m1.transpose()*m2));

  // continue testing Product.h: distributivity
  VERIFY_IS_APPROX(square*(m1 + m2),        square*m1+square*m2);
  VERIFY_IS_APPROX(square*(m1 - m2),        square*m1-square*m2);

  // continue testing Product.h: compatibility with ScalarMultiple.h
  VERIFY_IS_APPROX(s1*(square*m1),          (s1*square)*m1);
  VERIFY_IS_APPROX(s1*(square*m1),          square*(m1*s1));

  // continue testing Product.h: lazy product
  VERIFY_IS_APPROX(square.lazy() * m1,  square*m1);
  VERIFY_IS_APPROX(square * m1.lazy(),  square*m1);
  // again, test operator() to check const-qualification
  s1 += (square.lazy() * m1)(r,c);

  // test Product.h together with Identity.h
  VERIFY_IS_APPROX(m1,                      identity*m1);
  VERIFY_IS_APPROX(v1,                      identity*v1);
  // again, test operator() to check const-qualification
  VERIFY_IS_APPROX(MatrixType::identity(rows, cols)(r,c), static_cast<Scalar>(r==c));

  if (rows!=cols)
    VERIFY_RAISES_ASSERT(m3 = m1*m1);
}

void test_product()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST( product(Matrix<float, 1, 1>()) );
    CALL_SUBTEST( product(Matrix<float, 3, 3>()) );
    CALL_SUBTEST( product(Matrix<float, 4, 2>()) );
    CALL_SUBTEST( product(Matrix4d()) );
  }
  for(int i = 0; i < g_repeat; i++) {
    int rows = ei_random<int>(1,320);
    int cols = ei_random<int>(1,320);
    CALL_SUBTEST( product(MatrixXf(rows, cols)) );
    CALL_SUBTEST( product(MatrixXd(rows, cols)) );
    CALL_SUBTEST( product(MatrixXi(rows, cols)) );
    CALL_SUBTEST( product(MatrixXcf(rows, cols)) );
    CALL_SUBTEST( product(MatrixXcd(rows, cols)) );
  }
}
<|endoftext|>


<commit_before>#include <sys/types.h>
#include <sys/wait.h>

#include <chord_types.h>

#include <qhash.h>
#include "merkle.h"
#include "merkle_tree_disk.h"
#include <misc_utils.h>
#include <id_utils.h>

typedef bhash<chordID, hashID> keys_t;

static char *indexpath = "/tmp/index.mrk";
static char *internalpath = "/tmp/internal.mrk";
static char *leafpath  = "/tmp/leaf.mrk";
static char *indexpathro = "/tmp/index.mrk.ro";
static char *internalpathro = "/tmp/internal.mrk.ro";
static char *leafpathro  = "/tmp/leaf.mrk.ro";

void
cleanup ()
{
  unlink (indexpath);
  unlink (internalpath);
  unlink (leafpath);
  unlink (indexpathro);
  unlink (internalpathro);
  unlink (leafpathro);
}

bool
reap (int pid, bool wait = true)
{
  int wpid, status, options = 0;

  if (!wait)
    options = WNOHANG;
  wpid = waitpid (pid, &status, options);
  if (wpid < 0) {
    perror("waitpid");
    exit (1);
  }
  if (!wait && (wpid == 0))
    return false;
  if (wpid != pid)
    fatal ("unexpected pid reaped: %d\n", wpid);
  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
    fatal << "child exited unhappily\n";
  return true;
}

void
insert_blocks (merkle_tree *mtree, int upto, bool random,
    keys_t *keys = NULL)
{
  for (int i = 1; i <= upto; i++) {
    merkle_hash key;
    if (random)
      key.randomize ();
    else
      key = i;

    if (keys)
      keys->insert (static_cast<bigint> (key));
    mtree->insert (key);
  }
}

void
test_numkeys (merkle_tree *tree, unsigned int cnt)
{
  merkle_node *root = tree->get_root ();
  assert (root->count == cnt);
  tree->lookup_release (root);
}

void
test_insertions (str msg,
    merkle_tree *mtree, uint nkeys, bool rand, keys_t &keys)
{
  uint okeyssz = keys.size ();
  warn << msg << " bulk insertion... ";
  u_int64_t start = getusec ();
  mtree->set_rehash_on_modification (false);
  insert_blocks (mtree, nkeys, rand, &keys);
  warn << "completed in: " << (getusec ()-start)/1000 << "ms... ";
  assert ((keys.size () - okeyssz) == nkeys);
  warn << "OK\n";

  warn << msg << " hash full tree... ";
  start = getusec ();
  mtree->hash_tree ();
  warn << "completed in: " << (getusec ()-start)/1000 << "ms... ";
  test_numkeys (mtree, keys.size ());
  warn << "OK\n";

  warn << msg << " check invariants... ";
  mtree->check_invariants ();
  warn << "OK.\n";

  mtree->set_rehash_on_modification (true);
}

const vec<chordID> &
test_reads (merkle_tree *mtree, const keys_t &keys)
{
  static vec<chordID> intree;
  intree.clear ();
  unsigned int nkeys = keys.size ();

  warn << "All key read (get_keyrange)... ";
  intree = mtree->get_keyrange (
      0, (chordID (1) << 160) - 1, nkeys + 1);
  assert (intree.size () == nkeys);
  for (uint i = 0; i < intree.size (); i++) {
    assert (keys[intree[i]]);
  }
  warn << "OK\n";

  warn << "Randomized key lookups... ";
  uint limit = 128 + int(nkeys * 0.2);
  if (limit > nkeys)
    limit = nkeys;
  uint order[nkeys];
  for (uint i=0; i<nkeys; i++) order[i] = i;
  for (uint i = 0; i < limit; i++) {
    uint j = i + random() % (nkeys-i);
    uint key = order[j]; order[j] = order[i]; order[i] = key;
    assert (mtree->key_exists (intree[key]));
    merkle_node *n = mtree->lookup (intree[key]);
    assert (n);
    assert (n->isleaf ());
  }
  warn << "OK\n";

  warn << "Missing key lookups... ";
  int todo = limit;
  while (todo) {
    chordID c = make_randomID ();
    if (keys[c])
      continue;
    todo--;
    assert (!mtree->key_exists (c));
    merkle_node *n = mtree->lookup (c);
    assert (n);
  }
  warn << "OK\n";

  warn << "Random range reads... ";
  chordID highest = (((chordID) 1) << 160) - 1;
  for (int i = 0; i < 32; i++) {
    chordID min = make_randomID ();
    chordID max = min + make_randomID () % (highest - min);
    //warn << "  get_keyrange (" << min << ", " << max << ", " << nkeys << ")\n";
    vec<chordID> rangekeys = mtree->get_keyrange (min, max, nkeys);

    keys_t subset;
    for (uint j = 0; j < nkeys; j++)
      if (betweenbothincl (min, max, intree[j]))
	subset.insert (intree[j]);
    assert (subset.size () == rangekeys.size ());
    for (uint j = 0; j < rangekeys.size (); j++)
      assert (subset[rangekeys[j]]);
  }
  warn << "OK\n";
  return intree;
}

void
test (str msg, merkle_tree *mtree, uint nkeys, bool rand = true)
{
  warn << "\n=================== " << msg
       << " test_" << (rand ? "rand" : "incr")
       << " nkeys " << nkeys << "\n";

  keys_t keys;
  keys.clear ();

  test_insertions ("Initial", mtree, nkeys, rand, keys);
  const vec<chordID> intree = test_reads (mtree, keys);

  warn << "Removes... ";
  uint limit = (nkeys < 128) ? nkeys : (128 + int (nkeys * 0.2));
  uint order[nkeys];
  for (uint i=0; i<nkeys; i++) order[i] = i;
  for (uint i = 0; i < limit; i++) {
    // warnx << "  " << i+1 << "/" << limit << ".\n";
    uint j = i + random() % (nkeys-i);
    uint key = order[j]; order[j] = order[i]; order[i] = key;
    mtree->remove (intree[key]);
    keys.remove (intree[key]);
    test_numkeys (mtree, nkeys - (i + 1));
    assert (keys.size () == (nkeys - (i + 1)));
  }
  warn << "OK\n";

  warn << "Post-remove tree contents check... ";
  for (uint i = 0; i < nkeys; i++) {
    if (i < limit)
      assert (!mtree->key_exists (intree[order[i]]));
    else
      assert (mtree->key_exists (intree[order[i]]));
  }
  mtree->check_invariants ();
  warn << "OK\n";

  if (rand)
    test_insertions ("Post-remove", mtree, 2*limit, rand, keys);
  test_reads (mtree, keys);
}

void
test_merkle_disk_specific ()
{
  warn << "\n=================== Merkle Disk Specific Tests\n";
  merkle_tree *mtree =
      New merkle_tree_disk (indexpath, internalpath, leafpath, true);

  keys_t keys;
  keys.clear ();

  test_insertions ("Initial", mtree, 256, true, keys);
  delete mtree;

  warn << "Static child read... \n";
  int pid = fork ();
  if (pid < 0)
    fatal ("fork: %m\n");
  if (pid == 0) {
    // Child
    mtree =
      New merkle_tree_disk (indexpath, internalpath, leafpath, false);

    const vec<chordID> intree = test_reads (mtree, keys);
    exit (0);
  }
  reap (pid);
  warn << "Static child read OK\n";

  warn << "Dynamic child reads... \n";
  vec<chordID> tobeinserted;
  for (int i = 0; i < 3200; i++)
    tobeinserted.push_back (make_randomID ());
  pid = fork ();
  if (pid > 0) {
    // Parent
    bool reaped = false;
    mtree =
      New merkle_tree_disk (indexpath, internalpath, leafpath, true);
    for (int i = 0; i < 32; i++) {
      warn << "  Parent insertion burst " << i+1 << "\n";
      for (int j = 0; j < 100; j++) {
	mtree->insert (tobeinserted[100*i + j]);
	keys.insert (tobeinserted[100*i + j]);
      }
      if (!reaped)
	reaped = reap (pid, false);
      mtree->sync ();
      sleep (1);
    }
    if (!reaped)
      reap (pid);
  } else {
    chordID highest = (((chordID) 1) << 160) - 1;
    mtree =
      New merkle_tree_disk (indexpath, internalpath, leafpath, false);
    for (int i = 0; i < 32; i++) {
      warn << "  Child read-range " << i+1 << "\n";
      chordID min = make_randomID ();
      chordID max = min + make_randomID () % (highest - min);
      vec<chordID> rangekeys = mtree->get_keyrange (min, max, 10000);
      for (uint j = 0; j < rangekeys.size (); j++)
	assert (betweenbothincl (min, max, rangekeys[j]));
      mtree->check_invariants ();
      mtree->sync ();
      sleep (1);
    }
    exit (0);
  }
  warn << "Dynamic child reads seem OK\n";
}

int
main (int argc, char *argv[])
{
  // Make sure no confusion from previous crashes.
  cleanup ();

  // Any arguments mean we skip the "normal" tests.
  if (argc == 1) {
    int sz[] = { 1, 64, 256, 64*64+1, 10000 };
    for (uint i = 0; i < sizeof (sz) / sizeof (sz[0]); i++) {
      merkle_tree *t = New merkle_tree_mem ();
      test ("In-memory", t, sz[i], false);
      delete t; t = NULL;

      t = New merkle_tree_mem ();
      test ("In-memory", t, sz[i], true);
      delete t; t = NULL;
    }

    for (uint i = 0; i < sizeof (sz) / sizeof (sz[0]); i++) {
      merkle_tree *t =
	New merkle_tree_disk (indexpath, internalpath, leafpath, true);
      test ("Disk", t, sz[i]);
      delete t; t = NULL;
      cleanup ();
    }
  }

  test_merkle_disk_specific ();
  cleanup ();
}
<commit_msg>Fix output regressions from getusec changes.<commit_after>#include <sys/types.h>
#include <sys/wait.h>

#include <chord_types.h>

#include <qhash.h>
#include "merkle.h"
#include "merkle_tree_disk.h"
#include <misc_utils.h>
#include <id_utils.h>

typedef bhash<chordID, hashID> keys_t;

static char *indexpath = "/tmp/index.mrk";
static char *internalpath = "/tmp/internal.mrk";
static char *leafpath  = "/tmp/leaf.mrk";
static char *indexpathro = "/tmp/index.mrk.ro";
static char *internalpathro = "/tmp/internal.mrk.ro";
static char *leafpathro  = "/tmp/leaf.mrk.ro";

void
cleanup ()
{
  unlink (indexpath);
  unlink (internalpath);
  unlink (leafpath);
  unlink (indexpathro);
  unlink (internalpathro);
  unlink (leafpathro);
}

bool
reap (int pid, bool wait = true)
{
  int wpid, status, options = 0;

  if (!wait)
    options = WNOHANG;
  wpid = waitpid (pid, &status, options);
  if (wpid < 0) {
    perror("waitpid");
    exit (1);
  }
  if (!wait && (wpid == 0))
    return false;
  if (wpid != pid)
    fatal ("unexpected pid reaped: %d\n", wpid);
  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
    fatal << "child exited unhappily\n";
  return true;
}

void
insert_blocks (merkle_tree *mtree, int upto, bool random,
    keys_t *keys = NULL)
{
  for (int i = 1; i <= upto; i++) {
    merkle_hash key;
    if (random)
      key.randomize ();
    else
      key = i;

    if (keys)
      keys->insert (static_cast<bigint> (key));
    mtree->insert (key);
  }
}

void
test_numkeys (merkle_tree *tree, unsigned int cnt)
{
  merkle_node *root = tree->get_root ();
  assert (root->count == cnt);
  tree->lookup_release (root);
}

void
test_insertions (str msg,
    merkle_tree *mtree, uint nkeys, bool rand, keys_t &keys)
{
  uint okeyssz = keys.size ();
  warn << msg << " bulk insertion... ";
  u_int64_t start = getusec (true);
  mtree->set_rehash_on_modification (false);
  insert_blocks (mtree, nkeys, rand, &keys);
  warn << "completed in: " << (getusec (true)-start)/1000 << "ms... ";
  assert ((keys.size () - okeyssz) == nkeys);
  warn << "OK\n";

  warn << msg << " hash full tree... ";
  start = getusec (true);
  mtree->hash_tree ();
  warn << "completed in: " << (getusec (true)-start)/1000 << "ms... ";
  test_numkeys (mtree, keys.size ());
  warn << "OK\n";

  warn << msg << " check invariants... ";
  mtree->check_invariants ();
  warn << "OK.\n";

  mtree->set_rehash_on_modification (true);
}

const vec<chordID> &
test_reads (merkle_tree *mtree, const keys_t &keys)
{
  static vec<chordID> intree;
  intree.clear ();
  unsigned int nkeys = keys.size ();

  warn << "All key read (get_keyrange)... ";
  intree = mtree->get_keyrange (
      0, (chordID (1) << 160) - 1, nkeys + 1);
  assert (intree.size () == nkeys);
  for (uint i = 0; i < intree.size (); i++) {
    assert (keys[intree[i]]);
  }
  warn << "OK\n";

  warn << "Randomized key lookups... ";
  uint limit = 128 + int(nkeys * 0.2);
  if (limit > nkeys)
    limit = nkeys;
  uint order[nkeys];
  for (uint i=0; i<nkeys; i++) order[i] = i;
  for (uint i = 0; i < limit; i++) {
    uint j = i + random() % (nkeys-i);
    uint key = order[j]; order[j] = order[i]; order[i] = key;
    assert (mtree->key_exists (intree[key]));
    merkle_node *n = mtree->lookup (intree[key]);
    assert (n);
    assert (n->isleaf ());
  }
  warn << "OK\n";

  warn << "Missing key lookups... ";
  int todo = limit;
  while (todo) {
    chordID c = make_randomID ();
    if (keys[c])
      continue;
    todo--;
    assert (!mtree->key_exists (c));
    merkle_node *n = mtree->lookup (c);
    assert (n);
  }
  warn << "OK\n";

  warn << "Random range reads... ";
  chordID highest = (((chordID) 1) << 160) - 1;
  for (int i = 0; i < 32; i++) {
    chordID min = make_randomID ();
    chordID max = min + make_randomID () % (highest - min);
    //warn << "  get_keyrange (" << min << ", " << max << ", " << nkeys << ")\n";
    vec<chordID> rangekeys = mtree->get_keyrange (min, max, nkeys);

    keys_t subset;
    for (uint j = 0; j < nkeys; j++)
      if (betweenbothincl (min, max, intree[j]))
	subset.insert (intree[j]);
    assert (subset.size () == rangekeys.size ());
    for (uint j = 0; j < rangekeys.size (); j++)
      assert (subset[rangekeys[j]]);
  }
  warn << "OK\n";
  return intree;
}

void
test (str msg, merkle_tree *mtree, uint nkeys, bool rand = true)
{
  warn << "\n=================== " << msg
       << " test_" << (rand ? "rand" : "incr")
       << " nkeys " << nkeys << "\n";

  keys_t keys;
  keys.clear ();

  test_insertions ("Initial", mtree, nkeys, rand, keys);
  const vec<chordID> intree = test_reads (mtree, keys);

  warn << "Removes... ";
  uint limit = (nkeys < 128) ? nkeys : (128 + int (nkeys * 0.2));
  uint order[nkeys];
  for (uint i=0; i<nkeys; i++) order[i] = i;
  for (uint i = 0; i < limit; i++) {
    // warnx << "  " << i+1 << "/" << limit << ".\n";
    uint j = i + random() % (nkeys-i);
    uint key = order[j]; order[j] = order[i]; order[i] = key;
    mtree->remove (intree[key]);
    keys.remove (intree[key]);
    test_numkeys (mtree, nkeys - (i + 1));
    assert (keys.size () == (nkeys - (i + 1)));
  }
  warn << "OK\n";

  warn << "Post-remove tree contents check... ";
  for (uint i = 0; i < nkeys; i++) {
    if (i < limit)
      assert (!mtree->key_exists (intree[order[i]]));
    else
      assert (mtree->key_exists (intree[order[i]]));
  }
  mtree->check_invariants ();
  warn << "OK\n";

  if (rand)
    test_insertions ("Post-remove", mtree, 2*limit, rand, keys);
  test_reads (mtree, keys);
}

void
test_merkle_disk_specific ()
{
  warn << "\n=================== Merkle Disk Specific Tests\n";
  merkle_tree *mtree =
      New merkle_tree_disk (indexpath, internalpath, leafpath, true);

  keys_t keys;
  keys.clear ();

  test_insertions ("Initial", mtree, 256, true, keys);
  delete mtree;

  warn << "Static child read... \n";
  int pid = fork ();
  if (pid < 0)
    fatal ("fork: %m\n");
  if (pid == 0) {
    // Child
    mtree =
      New merkle_tree_disk (indexpath, internalpath, leafpath, false);

    const vec<chordID> intree = test_reads (mtree, keys);
    exit (0);
  }
  reap (pid);
  warn << "Static child read OK\n";

  warn << "Dynamic child reads... \n";
  vec<chordID> tobeinserted;
  for (int i = 0; i < 3200; i++)
    tobeinserted.push_back (make_randomID ());
  pid = fork ();
  if (pid > 0) {
    // Parent
    bool reaped = false;
    mtree =
      New merkle_tree_disk (indexpath, internalpath, leafpath, true);
    for (int i = 0; i < 32; i++) {
      warn << "  Parent insertion burst " << i+1 << "\n";
      for (int j = 0; j < 100; j++) {
	mtree->insert (tobeinserted[100*i + j]);
	keys.insert (tobeinserted[100*i + j]);
      }
      if (!reaped)
	reaped = reap (pid, false);
      mtree->sync ();
      sleep (1);
    }
    if (!reaped)
      reap (pid);
  } else {
    chordID highest = (((chordID) 1) << 160) - 1;
    mtree =
      New merkle_tree_disk (indexpath, internalpath, leafpath, false);
    for (int i = 0; i < 32; i++) {
      warn << "  Child read-range " << i+1 << "\n";
      chordID min = make_randomID ();
      chordID max = min + make_randomID () % (highest - min);
      vec<chordID> rangekeys = mtree->get_keyrange (min, max, 10000);
      for (uint j = 0; j < rangekeys.size (); j++)
	assert (betweenbothincl (min, max, rangekeys[j]));
      mtree->check_invariants ();
      mtree->sync ();
      sleep (1);
    }
    exit (0);
  }
  warn << "Dynamic child reads seem OK\n";
}

int
main (int argc, char *argv[])
{
  // Make sure no confusion from previous crashes.
  cleanup ();

  // Any arguments mean we skip the "normal" tests.
  if (argc == 1) {
    int sz[] = { 1, 64, 256, 64*64+1, 10000 };
    for (uint i = 0; i < sizeof (sz) / sizeof (sz[0]); i++) {
      merkle_tree *t = New merkle_tree_mem ();
      test ("In-memory", t, sz[i], false);
      delete t; t = NULL;

      t = New merkle_tree_mem ();
      test ("In-memory", t, sz[i], true);
      delete t; t = NULL;
    }

    for (uint i = 0; i < sizeof (sz) / sizeof (sz[0]); i++) {
      merkle_tree *t =
	New merkle_tree_disk (indexpath, internalpath, leafpath, true);
      test ("Disk", t, sz[i]);
      delete t; t = NULL;
      cleanup ();
    }
  }

  test_merkle_disk_specific ();
  cleanup ();
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/core/p9_hcd_core_stopclocks.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file  p9_hcd_core_stopclocks.C
/// @brief Core Clock Stop
///
/// Procedure Summary:

// *HWP HWP Owner          : David Du       <daviddu@us.ibm.com>
// *HWP Backup HWP Owner   : Greg Still     <stillgs@us.ibm.com>
// *HWP FW Owner           : Sangeetha T S  <sangeet2@in.ibm.com>
// *HWP Team               : PM
// *HWP Consumed by        : HB:PREV
// *HWP Level              : 2

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------

#include <p9_misc_scom_addresses.H>
#include <p9_quad_scom_addresses.H>
#include <p9_hcd_common.H>
#include <p9_common_clk_ctrl_state.H>
#include "p9_hcd_core_stopclocks.H"

//------------------------------------------------------------------------------
// Constant Definitions
//------------------------------------------------------------------------------

enum P9_HCD_CORE_STOPCLOCKS_CONSTANTS
{
    CORE_PCB_MUX_POLLING_HW_NS_DELAY      = 10000,
    CORE_PCB_MUX_POLLING_SIM_CYCLE_DELAY  = 320000,
    CORE_CLK_SYNC_POLLING_HW_NS_DELAY     = 10000,
    CORE_CLK_SYNC_POLLING_SIM_CYCLE_DELAY = 320000,
    CORE_CLK_STOP_POLLING_HW_NS_DELAY     = 10000,
    CORE_CLK_STOP_POLLING_SIM_CYCLE_DELAY = 320000
};

//------------------------------------------------------------------------------
// Procedure: Core Clock Stop
//------------------------------------------------------------------------------

fapi2::ReturnCode
p9_hcd_core_stopclocks(
    const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target)
{
    FAPI_INF(">>p9_hcd_core_stopclocks");
    fapi2::ReturnCode                              l_rc;
    fapi2::buffer<uint64_t>                        l_ccsr;
    fapi2::buffer<uint64_t>                        l_data64;
    fapi2::buffer<uint64_t>                        l_temp64;
    uint32_t                                       l_loops1ms;
    uint8_t                                        l_attr_chip_unit_pos;
    uint8_t                                        l_attr_vdm_enable;
    uint8_t                                        l_attr_sdisn_setup;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> l_sys;
    auto  l_quad = i_target.getParent<fapi2::TARGET_TYPE_EQ>();
    auto  l_perv = i_target.getParent<fapi2::TARGET_TYPE_PERV>();
    auto  l_chip = i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_SDISN_SETUP, l_chip,
                           l_attr_sdisn_setup));

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_VDM_ENABLE,       l_sys,
                           l_attr_vdm_enable));
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS,    l_perv,
                           l_attr_chip_unit_pos));
    l_attr_chip_unit_pos = (l_attr_chip_unit_pos -
                            p9hcd::PERV_TO_CORE_POS_OFFSET) % 4;

    // ----------------------------
    // Prepare to stop core clocks
    // ----------------------------

    FAPI_DBG("Check PM_RESET_STATE_INDICATOR via GPMMR[15]");
    FAPI_TRY(getScom(i_target, C_PPM_GPMMR_SCOM, l_data64));

    if (!l_data64.getBit<15>())
    {
        FAPI_DBG("Gracefully turn off power management, continue anyways if fail");
        /// @todo RTC158181 suspend_pm()
    }

    FAPI_DBG("Check core clock controller status");
    l_rc = p9_common_clk_ctrl_state<fapi2::TARGET_TYPE_CORE>(i_target);

    if (l_rc)
    {
        FAPI_INF("Clock controller of this core chiplet is inaccessible, return");
        goto fapi_try_exit;
    }

    FAPI_DBG("Check cache clock controller status");
    l_rc = p9_common_clk_ctrl_state<fapi2::TARGET_TYPE_EQ>(l_quad);

    if (l_rc)
    {
        FAPI_INF("WARNING: core is enabled while cache is not, continue anyways");
    }
    else
    {

        FAPI_DBG("Check PERV clock status for access to CME via CLOCK_STAT[4]");
        FAPI_TRY(getScom(l_quad, EQ_CLOCK_STAT_SL, l_data64));

        FAPI_DBG("Check PERV fence status for access to CME via CPLT_CTRL1[4]");
        FAPI_TRY(getScom(l_quad, EQ_CPLT_CTRL1, l_temp64));

        if (l_data64.getBit<4>() == 0 && l_temp64.getBit<4>() == 0)
        {
            //halt cme(poll for halted, if timeout, print warnning keep going).

            FAPI_DBG("Assert Core-L2/CC Quiesces via CME_SCOM_SICR[6,8]/[7,9]");
            FAPI_TRY(putScom(l_quad,
                             (l_attr_chip_unit_pos < 2) ?
                             EX_0_CME_SCOM_SICR_OR : EX_1_CME_SCOM_SICR_OR,
                             (BIT64(6 + (l_attr_chip_unit_pos % 2)) |
                              BIT64(8 + (l_attr_chip_unit_pos % 2)))));
        }
    }

    FAPI_DBG("Assert pm_mux_disable to get PCB Mux from CME via SLAVE_CONFIG[7]");
    FAPI_TRY(getScom(i_target, C_SLAVE_CONFIG_REG, l_data64));
    FAPI_TRY(putScom(i_target, C_SLAVE_CONFIG_REG, DATA_SET(7)));

    FAPI_DBG("Override possible PPM write protection to CME via CPPM_CPMMR[1]");
    FAPI_TRY(putScom(i_target, C_CPPM_CPMMR_OR, MASK_SET(1)));

    FAPI_DBG("Assert chiplet fence via NET_CTRL0[18]");
    FAPI_TRY(putScom(i_target, C_NET_CTRL0_WOR, MASK_SET(18)));

    // -------------------------------
    // Stop core clocks
    // -------------------------------

    FAPI_DBG("Clear all SCAN_REGION_TYPE bits");
    FAPI_TRY(putScom(i_target, C_SCAN_REGION_TYPE, MASK_ZERO));

    FAPI_DBG("Stop core clocks(all but pll) via CLK_REGION");
    l_data64 = (p9hcd::CLK_STOP_CMD           |
                p9hcd::CLK_REGION_ALL_BUT_PLL |
                p9hcd::CLK_THOLD_ALL);
    FAPI_TRY(putScom(i_target, C_CLK_REGION, l_data64));

    FAPI_DBG("Poll for core clocks stopped via CPLT_STAT0[8]");
    l_loops1ms = 1E6 / CORE_CLK_STOP_POLLING_HW_NS_DELAY;

    do
    {
        fapi2::delay(CORE_CLK_STOP_POLLING_HW_NS_DELAY,
                     CORE_CLK_STOP_POLLING_SIM_CYCLE_DELAY);

        FAPI_TRY(getScom(i_target, C_CPLT_STAT0, l_data64));
    }
    while((l_data64.getBit<8>() != 1) && ((--l_loops1ms) != 0));

    FAPI_ASSERT((l_loops1ms != 0),
                fapi2::PMPROC_CORECLKSTOP_TIMEOUT().set_CORECPLTSTAT(l_data64),
                "Core Clock Stop Timeout");

    FAPI_DBG("Check core clocks stopped via CLOCK_STAT_SL[4-13]");
    FAPI_TRY(getScom(i_target, C_CLOCK_STAT_SL, l_data64));

    FAPI_ASSERT((((~l_data64) & p9hcd::CLK_REGION_ALL_BUT_PLL) == 0),
                fapi2::PMPROC_CORECLKSTOP_FAILED().set_CORECLKSTAT(l_data64),
                "Core Clock Stop Failed");
    FAPI_DBG("Core clocks stopped now");

    // -------------------------------
    // Disable core clock sync
    // -------------------------------

    FAPI_DBG("Drop core clock sync enable via CPPM_CACCR[15]");
    FAPI_TRY(putScom(i_target, C_CPPM_CACCR_CLEAR, MASK_SET(15)));

    FAPI_DBG("Poll for core clock sync done to drop via CPPM_CACSR[13]");
    l_loops1ms = 1E6 / CORE_CLK_SYNC_POLLING_HW_NS_DELAY;

    do
    {
        fapi2::delay(CORE_CLK_SYNC_POLLING_HW_NS_DELAY,
                     CORE_CLK_SYNC_POLLING_SIM_CYCLE_DELAY);

        FAPI_TRY(getScom(i_target, C_CPPM_CACSR, l_data64));
    }
    while((l_data64.getBit<13>() == 1) && ((--l_loops1ms) != 0));

    FAPI_ASSERT((l_loops1ms != 0),
                fapi2::PMPROC_CORECLKSYNCDROP_TIMEOUT().set_COREPPMCACSR(l_data64),
                "Core Clock Sync Drop Timeout");
    FAPI_DBG("Core clock sync done dropped");

    // -------------------------------
    // Fence up
    // -------------------------------

    FAPI_DBG("Assert skew sense to skew adjust fence via NET_CTRL0[22]");
    FAPI_TRY(putScom(i_target, C_NET_CTRL0_WOR, MASK_SET(22)));

    FAPI_DBG("Drop ABIST_SRAM_MODE_DC to support ABIST Recovery via BIST[1]");
    FAPI_TRY(getScom(i_target, C_BIST, l_data64));
    FAPI_TRY(putScom(i_target, C_BIST, DATA_UNSET(1)));

    FAPI_DBG("Assert vital fence via CPLT_CTRL1[3]");
    FAPI_TRY(putScom(i_target, C_CPLT_CTRL1_OR, MASK_SET(3)));

    FAPI_DBG("Assert regional fences via CPLT_CTRL1[4-14]");
    FAPI_TRY(putScom(i_target, C_CPLT_CTRL1_OR, p9hcd::CLK_REGION_ALL));

    if (l_attr_sdisn_setup)
    {
        FAPI_DBG("DD1 Only: Drop sdis_n(flushing LCBES condition) vai CPLT_CONF0[34]");
        FAPI_TRY(putScom(i_target, C_CPLT_CONF0_CLEAR, MASK_SET(34)));
    }

    // -------------------------------
    // Disable VDM
    // -------------------------------

    if (l_attr_vdm_enable == fapi2::ENUM_ATTR_VDM_ENABLE_ON)
    {
        FAPI_DBG("Drop vdm enable via CPPM_VDMCR[0]");
        FAPI_TRY(putScom(i_target, C_PPM_VDMCR_CLEAR, MASK_SET(0)));
    }

    // -------------------------------
    // Update stop history
    // -------------------------------

    FAPI_DBG("Set core as stopped in STOP history register");
    FAPI_TRY(putScom(i_target, C_PPM_SSHSRC, BIT64(0)));

    // -------------------------------
    // Clean up
    // -------------------------------

    FAPI_DBG("Return possible PPM write protection to CME via CPPM_CPMMR[1]");
    FAPI_TRY(putScom(i_target, C_CPPM_CPMMR_CLEAR, MASK_SET(1)));

    FAPI_DBG("Drop pm_mux_disable to release PCB Mux via SLAVE_CONFIG[7]");
    FAPI_TRY(getScom(i_target, C_SLAVE_CONFIG_REG, l_data64));
    FAPI_TRY(putScom(i_target, C_SLAVE_CONFIG_REG, DATA_UNSET(7)));

fapi_try_exit:

    FAPI_INF("<<p9_hcd_core_stopclocks");
    return fapi2::current_err;
}
<commit_msg>Pstate: Remove legacy VDM code<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/core/p9_hcd_core_stopclocks.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file  p9_hcd_core_stopclocks.C
/// @brief Core Clock Stop
///
/// Procedure Summary:

// *HWP HWP Owner          : David Du       <daviddu@us.ibm.com>
// *HWP Backup HWP Owner   : Greg Still     <stillgs@us.ibm.com>
// *HWP FW Owner           : Sangeetha T S  <sangeet2@in.ibm.com>
// *HWP Team               : PM
// *HWP Consumed by        : HB:PREV
// *HWP Level              : 2

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------

#include <p9_misc_scom_addresses.H>
#include <p9_quad_scom_addresses.H>
#include <p9_hcd_common.H>
#include <p9_common_clk_ctrl_state.H>
#include "p9_hcd_core_stopclocks.H"

//------------------------------------------------------------------------------
// Constant Definitions
//------------------------------------------------------------------------------

enum P9_HCD_CORE_STOPCLOCKS_CONSTANTS
{
    CORE_PCB_MUX_POLLING_HW_NS_DELAY      = 10000,
    CORE_PCB_MUX_POLLING_SIM_CYCLE_DELAY  = 320000,
    CORE_CLK_SYNC_POLLING_HW_NS_DELAY     = 10000,
    CORE_CLK_SYNC_POLLING_SIM_CYCLE_DELAY = 320000,
    CORE_CLK_STOP_POLLING_HW_NS_DELAY     = 10000,
    CORE_CLK_STOP_POLLING_SIM_CYCLE_DELAY = 320000
};

//------------------------------------------------------------------------------
// Procedure: Core Clock Stop
//------------------------------------------------------------------------------

fapi2::ReturnCode
p9_hcd_core_stopclocks(
    const fapi2::Target<fapi2::TARGET_TYPE_CORE>& i_target)
{
    FAPI_INF(">>p9_hcd_core_stopclocks");
    fapi2::ReturnCode                              l_rc;
    fapi2::buffer<uint64_t>                        l_ccsr;
    fapi2::buffer<uint64_t>                        l_data64;
    fapi2::buffer<uint64_t>                        l_temp64;
    uint32_t                                       l_loops1ms;
    uint8_t                                        l_attr_chip_unit_pos;
    uint8_t                                        l_attr_vdm_enable;
    uint8_t                                        l_attr_sdisn_setup;
    const fapi2::Target<fapi2::TARGET_TYPE_SYSTEM> l_sys;
    auto  l_quad = i_target.getParent<fapi2::TARGET_TYPE_EQ>();
    auto  l_perv = i_target.getParent<fapi2::TARGET_TYPE_PERV>();
    auto  l_chip = i_target.getParent<fapi2::TARGET_TYPE_PROC_CHIP>();

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_EC_FEATURE_SDISN_SETUP, l_chip,
                           l_attr_sdisn_setup));

    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_VDM_ENABLE,       l_sys,
                           l_attr_vdm_enable));
    FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS,    l_perv,
                           l_attr_chip_unit_pos));
    l_attr_chip_unit_pos = (l_attr_chip_unit_pos -
                            p9hcd::PERV_TO_CORE_POS_OFFSET) % 4;

    // ----------------------------
    // Prepare to stop core clocks
    // ----------------------------

    FAPI_DBG("Check PM_RESET_STATE_INDICATOR via GPMMR[15]");
    FAPI_TRY(getScom(i_target, C_PPM_GPMMR_SCOM, l_data64));

    if (!l_data64.getBit<15>())
    {
        FAPI_DBG("Gracefully turn off power management, continue anyways if fail");
        /// @todo RTC158181 suspend_pm()
    }

    FAPI_DBG("Check core clock controller status");
    l_rc = p9_common_clk_ctrl_state<fapi2::TARGET_TYPE_CORE>(i_target);

    if (l_rc)
    {
        FAPI_INF("Clock controller of this core chiplet is inaccessible, return");
        goto fapi_try_exit;
    }

    FAPI_DBG("Check cache clock controller status");
    l_rc = p9_common_clk_ctrl_state<fapi2::TARGET_TYPE_EQ>(l_quad);

    if (l_rc)
    {
        FAPI_INF("WARNING: core is enabled while cache is not, continue anyways");
    }
    else
    {

        FAPI_DBG("Check PERV clock status for access to CME via CLOCK_STAT[4]");
        FAPI_TRY(getScom(l_quad, EQ_CLOCK_STAT_SL, l_data64));

        FAPI_DBG("Check PERV fence status for access to CME via CPLT_CTRL1[4]");
        FAPI_TRY(getScom(l_quad, EQ_CPLT_CTRL1, l_temp64));

        if (l_data64.getBit<4>() == 0 && l_temp64.getBit<4>() == 0)
        {
            //halt cme(poll for halted, if timeout, print warnning keep going).

            FAPI_DBG("Assert Core-L2/CC Quiesces via CME_SCOM_SICR[6,8]/[7,9]");
            FAPI_TRY(putScom(l_quad,
                             (l_attr_chip_unit_pos < 2) ?
                             EX_0_CME_SCOM_SICR_OR : EX_1_CME_SCOM_SICR_OR,
                             (BIT64(6 + (l_attr_chip_unit_pos % 2)) |
                              BIT64(8 + (l_attr_chip_unit_pos % 2)))));
        }
    }

    FAPI_DBG("Assert pm_mux_disable to get PCB Mux from CME via SLAVE_CONFIG[7]");
    FAPI_TRY(getScom(i_target, C_SLAVE_CONFIG_REG, l_data64));
    FAPI_TRY(putScom(i_target, C_SLAVE_CONFIG_REG, DATA_SET(7)));

    FAPI_DBG("Override possible PPM write protection to CME via CPPM_CPMMR[1]");
    FAPI_TRY(putScom(i_target, C_CPPM_CPMMR_OR, MASK_SET(1)));

    FAPI_DBG("Assert chiplet fence via NET_CTRL0[18]");
    FAPI_TRY(putScom(i_target, C_NET_CTRL0_WOR, MASK_SET(18)));

    // -------------------------------
    // Stop core clocks
    // -------------------------------

    FAPI_DBG("Clear all SCAN_REGION_TYPE bits");
    FAPI_TRY(putScom(i_target, C_SCAN_REGION_TYPE, MASK_ZERO));

    FAPI_DBG("Stop core clocks(all but pll) via CLK_REGION");
    l_data64 = (p9hcd::CLK_STOP_CMD           |
                p9hcd::CLK_REGION_ALL_BUT_PLL |
                p9hcd::CLK_THOLD_ALL);
    FAPI_TRY(putScom(i_target, C_CLK_REGION, l_data64));

    FAPI_DBG("Poll for core clocks stopped via CPLT_STAT0[8]");
    l_loops1ms = 1E6 / CORE_CLK_STOP_POLLING_HW_NS_DELAY;

    do
    {
        fapi2::delay(CORE_CLK_STOP_POLLING_HW_NS_DELAY,
                     CORE_CLK_STOP_POLLING_SIM_CYCLE_DELAY);

        FAPI_TRY(getScom(i_target, C_CPLT_STAT0, l_data64));
    }
    while((l_data64.getBit<8>() != 1) && ((--l_loops1ms) != 0));

    FAPI_ASSERT((l_loops1ms != 0),
                fapi2::PMPROC_CORECLKSTOP_TIMEOUT().set_CORECPLTSTAT(l_data64),
                "Core Clock Stop Timeout");

    FAPI_DBG("Check core clocks stopped via CLOCK_STAT_SL[4-13]");
    FAPI_TRY(getScom(i_target, C_CLOCK_STAT_SL, l_data64));

    FAPI_ASSERT((((~l_data64) & p9hcd::CLK_REGION_ALL_BUT_PLL) == 0),
                fapi2::PMPROC_CORECLKSTOP_FAILED().set_CORECLKSTAT(l_data64),
                "Core Clock Stop Failed");
    FAPI_DBG("Core clocks stopped now");

    // -------------------------------
    // Disable core clock sync
    // -------------------------------

    FAPI_DBG("Drop core clock sync enable via CPPM_CACCR[15]");
    FAPI_TRY(putScom(i_target, C_CPPM_CACCR_CLEAR, MASK_SET(15)));

    FAPI_DBG("Poll for core clock sync done to drop via CPPM_CACSR[13]");
    l_loops1ms = 1E6 / CORE_CLK_SYNC_POLLING_HW_NS_DELAY;

    do
    {
        fapi2::delay(CORE_CLK_SYNC_POLLING_HW_NS_DELAY,
                     CORE_CLK_SYNC_POLLING_SIM_CYCLE_DELAY);

        FAPI_TRY(getScom(i_target, C_CPPM_CACSR, l_data64));
    }
    while((l_data64.getBit<13>() == 1) && ((--l_loops1ms) != 0));

    FAPI_ASSERT((l_loops1ms != 0),
                fapi2::PMPROC_CORECLKSYNCDROP_TIMEOUT().set_COREPPMCACSR(l_data64),
                "Core Clock Sync Drop Timeout");
    FAPI_DBG("Core clock sync done dropped");

    // -------------------------------
    // Fence up
    // -------------------------------

    FAPI_DBG("Assert skew sense to skew adjust fence via NET_CTRL0[22]");
    FAPI_TRY(putScom(i_target, C_NET_CTRL0_WOR, MASK_SET(22)));

    FAPI_DBG("Drop ABIST_SRAM_MODE_DC to support ABIST Recovery via BIST[1]");
    FAPI_TRY(getScom(i_target, C_BIST, l_data64));
    FAPI_TRY(putScom(i_target, C_BIST, DATA_UNSET(1)));

    FAPI_DBG("Assert vital fence via CPLT_CTRL1[3]");
    FAPI_TRY(putScom(i_target, C_CPLT_CTRL1_OR, MASK_SET(3)));

    FAPI_DBG("Assert regional fences via CPLT_CTRL1[4-14]");
    FAPI_TRY(putScom(i_target, C_CPLT_CTRL1_OR, p9hcd::CLK_REGION_ALL));

    if (l_attr_sdisn_setup)
    {
        FAPI_DBG("DD1 Only: Drop sdis_n(flushing LCBES condition) vai CPLT_CONF0[34]");
        FAPI_TRY(putScom(i_target, C_CPLT_CONF0_CLEAR, MASK_SET(34)));
    }

    // -------------------------------
    // Disable VDM
    // -------------------------------

    if (l_attr_vdm_enable == fapi2::ENUM_ATTR_VDM_ENABLE_ON)
    {
        FAPI_DBG("Set VDM Disable via CPPM_VDMCR[1]");
        FAPI_TRY(putScom(i_target, C_PPM_VDMCR_OR, MASK_SET(1)));
        FAPI_DBG("Drop VDM Poweron via CPPM_VDMCR[0]");
        FAPI_TRY(putScom(i_target, C_PPM_VDMCR_CLEAR, MASK_SET(0)));
    }

    // -------------------------------
    // Update stop history
    // -------------------------------

    FAPI_DBG("Set core as stopped in STOP history register");
    FAPI_TRY(putScom(i_target, C_PPM_SSHSRC, BIT64(0)));

    // -------------------------------
    // Clean up
    // -------------------------------

    FAPI_DBG("Return possible PPM write protection to CME via CPPM_CPMMR[1]");
    FAPI_TRY(putScom(i_target, C_CPPM_CPMMR_CLEAR, MASK_SET(1)));

    FAPI_DBG("Drop pm_mux_disable to release PCB Mux via SLAVE_CONFIG[7]");
    FAPI_TRY(getScom(i_target, C_SLAVE_CONFIG_REG, l_data64));
    FAPI_TRY(putScom(i_target, C_SLAVE_CONFIG_REG, DATA_UNSET(7)));

fapi_try_exit:

    FAPI_INF("<<p9_hcd_core_stopclocks");
    return fapi2::current_err;
}
<|endoftext|>