<commit_before>//===- InlineCost.cpp - Cost analysis for inliner -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements inline cost analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/InlineCost.h"
#include "llvm/Support/CallSite.h"
#include "llvm/CallingConv.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;

// CountCodeReductionForConstant - Figure out an approximation for how many
// instructions will be constant folded if the specified value is constant.
//
unsigned InlineCostAnalyzer::FunctionInfo::
         CountCodeReductionForConstant(Value *V) {
  unsigned Reduction = 0;
  for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI)
    if (isa<BranchInst>(*UI))
      Reduction += 40;          // Eliminating a conditional branch is a big win
    else if (SwitchInst *SI = dyn_cast<SwitchInst>(*UI))
      // Eliminating a switch is a big win, proportional to the number of edges
      // deleted.
      Reduction += (SI->getNumSuccessors()-1) * 40;
    else if (CallInst *CI = dyn_cast<CallInst>(*UI)) {
      // Turning an indirect call into a direct call is a BIG win
      Reduction += CI->getCalledValue() == V ? 500 : 0;
    } else if (InvokeInst *II = dyn_cast<InvokeInst>(*UI)) {
      // Turning an indirect call into a direct call is a BIG win
      Reduction += II->getCalledValue() == V ? 500 : 0;
    } else {
      // Figure out if this instruction will be removed due to simple constant
      // propagation.
      Instruction &Inst = cast<Instruction>(**UI);

      // We can't constant propagate instructions which have effects or
      // read memory.
      //
      // FIXME: It would be nice to capture the fact that a load from a
      // pointer-to-constant-global is actually a *really* good thing to zap.
      // Unfortunately, we don't know the pointer that may get propagated here,
      // so we can't make this decision.
      if (Inst.mayReadFromMemory() || Inst.mayHaveSideEffects() ||
          isa<AllocationInst>(Inst))
        continue;

      bool AllOperandsConstant = true;
      for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i)
        if (!isa<Constant>(Inst.getOperand(i)) && Inst.getOperand(i) != V) {
          AllOperandsConstant = false;
          break;
        }

      if (AllOperandsConstant) {
        // We will get to remove this instruction...
        Reduction += 7;

        // And any other instructions that use it which become constants
        // themselves.
        Reduction += CountCodeReductionForConstant(&Inst);
      }
    }

  return Reduction;
}

// CountCodeReductionForAlloca - Figure out an approximation of how much smaller
// the function will be if it is inlined into a context where an argument
// becomes an alloca.
//
unsigned InlineCostAnalyzer::FunctionInfo::
         CountCodeReductionForAlloca(Value *V) {
  if (!isa<PointerType>(V->getType())) return 0;  // Not a pointer
  unsigned Reduction = 0;
  for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){
    Instruction *I = cast<Instruction>(*UI);
    if (isa<LoadInst>(I) || isa<StoreInst>(I))
      Reduction += 10;
    else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I)) {
      // If the GEP has variable indices, we won't be able to do much with it.
      if (!GEP->hasAllConstantIndices())
        Reduction += CountCodeReductionForAlloca(GEP)+15;
    } else {
      // If there is some other strange instruction, we're not going to be able
      // to do much if we inline this.
      return 0;
    }
  }

  return Reduction;
}

/// analyzeBasicBlock - Fill in the current structure with information gleaned
/// from the specified block.
void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) {
  ++NumBlocks;

  for (BasicBlock::const_iterator II = BB->begin(), E = BB->end();
       II != E; ++II) {
    if (isa<PHINode>(II)) continue;           // PHI nodes don't count.

    // Special handling for calls.
    if (isa<CallInst>(II) || isa<InvokeInst>(II)) {
      if (isa<DbgInfoIntrinsic>(II))
        continue;  // Debug intrinsics don't count as size.

      CallSite CS = CallSite::get(const_cast<Instruction*>(&*II));

      // If this function contains a call to setjmp or _setjmp, never inline
      // it.  This is a hack because we depend on the user marking their local
      // variables as volatile if they are live across a setjmp call, and they
      // probably won't do this in callers.
      if (Function *F = CS.getCalledFunction())
        if (F->isDeclaration() &&
            (F->getName() == "setjmp" || F->getName() == "_setjmp")) {
          NeverInline = true;
          return;
        }

      // Calls often compile into many machine instructions.  Bump up their
      // cost to reflect this.
      if (!isa<IntrinsicInst>(II))
        NumInsts += InlineConstants::CallPenalty;
    }

    // These, too, are calls.
    if (isa<MallocInst>(II) || isa<FreeInst>(II))
      NumInsts += InlineConstants::CallPenalty;

    if (const AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
      if (!AI->isStaticAlloca())
        this->usesDynamicAlloca = true;
    }

    if (isa<ExtractElementInst>(II) || isa<VectorType>(II->getType()))
      ++NumVectorInsts;

    // Noop casts, including ptr <-> int,  don't count.
    if (const CastInst *CI = dyn_cast<CastInst>(II)) {
      if (CI->isLosslessCast() || isa<IntToPtrInst>(CI) ||
          isa<PtrToIntInst>(CI))
        continue;
    } else if (const GetElementPtrInst *GEPI =
               dyn_cast<GetElementPtrInst>(II)) {
      // If a GEP has all constant indices, it will probably be folded with
      // a load/store.
      if (GEPI->hasAllConstantIndices())
        continue;
    }

    if (isa<ReturnInst>(II))
      ++NumRets;

    ++NumInsts;
  }
}

/// analyzeFunction - Fill in the current structure with information gleaned
/// from the specified function.
void CodeMetrics::analyzeFunction(Function *F) {
  // Look at the size of the callee.
  for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
    analyzeBasicBlock(&*BB);
}

/// analyzeFunction - Fill in the current structure with information gleaned
/// from the specified function.
void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) {
  Metrics.analyzeFunction(F);

  // A function with exactly one return has it removed during the inlining
  // process (see InlineFunction), so don't count it.
  // FIXME: This knowledge should really be encoded outside of FunctionInfo.
  if (Metrics.NumRets==1)
    --Metrics.NumInsts;

  // Check out all of the arguments to the function, figuring out how much
  // code can be eliminated if one of the arguments is a constant.
  for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
    ArgumentWeights.push_back(ArgInfo(CountCodeReductionForConstant(I),
                                      CountCodeReductionForAlloca(I)));
}

// getInlineCost - The heuristic used to determine if we should inline the
// function call or not.
//
InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS,
                               SmallPtrSet<const Function *, 16> &NeverInline) {
  Instruction *TheCall = CS.getInstruction();
  Function *Callee = CS.getCalledFunction();
  Function *Caller = TheCall->getParent()->getParent();

  // Don't inline functions which can be redefined at link-time to mean
  // something else.  Don't inline functions marked noinline.
  if (Callee->mayBeOverridden() ||
      Callee->hasFnAttr(Attribute::NoInline) || NeverInline.count(Callee))
    return llvm::InlineCost::getNever();

  // InlineCost - This value measures how good of an inline candidate this call
  // site is to inline.  A lower inline cost make is more likely for the call to
  // be inlined.  This value may go negative.
  //
  int InlineCost = 0;

  // If there is only one call of the function, and it has internal linkage,
  // make it almost guaranteed to be inlined.
  //
  if (Callee->hasLocalLinkage() && Callee->hasOneUse())
    InlineCost += InlineConstants::LastCallToStaticBonus;

  // If this function uses the coldcc calling convention, prefer not to inline
  // it.
  if (Callee->getCallingConv() == CallingConv::Cold)
    InlineCost += InlineConstants::ColdccPenalty;

  // If the instruction after the call, or if the normal destination of the
  // invoke is an unreachable instruction, the function is noreturn.  As such,
  // there is little point in inlining this.
  if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
    if (isa<UnreachableInst>(II->getNormalDest()->begin()))
      InlineCost += InlineConstants::NoreturnPenalty;
  } else if (isa<UnreachableInst>(++BasicBlock::iterator(TheCall)))
    InlineCost += InlineConstants::NoreturnPenalty;

  // Get information about the callee...
  FunctionInfo &CalleeFI = CachedFunctionInfo[Callee];

  // If we haven't calculated this information yet, do so now.
  if (CalleeFI.Metrics.NumBlocks == 0)
    CalleeFI.analyzeFunction(Callee);

  // If we should never inline this, return a huge cost.
  if (CalleeFI.Metrics.NeverInline)
    return InlineCost::getNever();

  // FIXME: It would be nice to kill off CalleeFI.NeverInline. Then we
  // could move this up and avoid computing the FunctionInfo for
  // things we are going to just return always inline for. This
  // requires handling setjmp somewhere else, however.
  if (!Callee->isDeclaration() && Callee->hasFnAttr(Attribute::AlwaysInline))
    return InlineCost::getAlways();

  if (CalleeFI.Metrics.usesDynamicAlloca) {
    // Get infomation about the caller...
    FunctionInfo &CallerFI = CachedFunctionInfo[Caller];

    // If we haven't calculated this information yet, do so now.
    if (CallerFI.Metrics.NumBlocks == 0)
      CallerFI.analyzeFunction(Caller);

    // Don't inline a callee with dynamic alloca into a caller without them.
    // Functions containing dynamic alloca's are inefficient in various ways;
    // don't create more inefficiency.
    if (!CallerFI.Metrics.usesDynamicAlloca)
      return InlineCost::getNever();
  }

  // Add to the inline quality for properties that make the call valuable to
  // inline.  This includes factors that indicate that the result of inlining
  // the function will be optimizable.  Currently this just looks at arguments
  // passed into the function.
  //
  unsigned ArgNo = 0;
  for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
       I != E; ++I, ++ArgNo) {
    // Each argument passed in has a cost at both the caller and the callee
    // sides.  This favors functions that take many arguments over functions
    // that take few arguments.
    InlineCost -= 20;

    // If this is a function being passed in, it is very likely that we will be
    // able to turn an indirect function call into a direct function call.
    if (isa<Function>(I))
      InlineCost -= 100;

    // If an alloca is passed in, inlining this function is likely to allow
    // significant future optimization possibilities (like scalar promotion, and
    // scalarization), so encourage the inlining of the function.
    //
    else if (isa<AllocaInst>(I)) {
      if (ArgNo < CalleeFI.ArgumentWeights.size())
        InlineCost -= CalleeFI.ArgumentWeights[ArgNo].AllocaWeight;

      // If this is a constant being passed into the function, use the argument
      // weights calculated for the callee to determine how much will be folded
      // away with this information.
    } else if (isa<Constant>(I)) {
      if (ArgNo < CalleeFI.ArgumentWeights.size())
        InlineCost -= CalleeFI.ArgumentWeights[ArgNo].ConstantWeight;
    }
  }

  // Now that we have considered all of the factors that make the call site more
  // likely to be inlined, look at factors that make us not want to inline it.

  // Don't inline into something too big, which would make it bigger.
  // "size" here is the number of basic blocks, not instructions.
  //
  InlineCost += Caller->size()/15;

  // Look at the size of the callee. Each instruction counts as 5.
  InlineCost += CalleeFI.Metrics.NumInsts*5;

  return llvm::InlineCost::get(InlineCost);
}

// getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a
// higher threshold to determine if the function call should be inlined.
float InlineCostAnalyzer::getInlineFudgeFactor(CallSite CS) {
  Function *Callee = CS.getCalledFunction();

  // Get information about the callee...
  FunctionInfo &CalleeFI = CachedFunctionInfo[Callee];

  // If we haven't calculated this information yet, do so now.
  if (CalleeFI.Metrics.NumBlocks == 0)
    CalleeFI.analyzeFunction(Callee);

  float Factor = 1.0f;
  // Single BB functions are often written to be inlined.
  if (CalleeFI.Metrics.NumBlocks == 1)
    Factor += 0.5f;

  // Be more aggressive if the function contains a good chunk (if it mades up
  // at least 10% of the instructions) of vector instructions.
  if (CalleeFI.Metrics.NumVectorInsts > CalleeFI.Metrics.NumInsts/2)
    Factor += 2.0f;
  else if (CalleeFI.Metrics.NumVectorInsts > CalleeFI.Metrics.NumInsts/10)
    Factor += 1.5f;
  return Factor;
}
<commit_msg>Compute a full cost value even when a setjmp call is found.<commit_after>//===- InlineCost.cpp - Cost analysis for inliner -------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements inline cost analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/InlineCost.h"
#include "llvm/Support/CallSite.h"
#include "llvm/CallingConv.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/ADT/SmallPtrSet.h"
using namespace llvm;

// CountCodeReductionForConstant - Figure out an approximation for how many
// instructions will be constant folded if the specified value is constant.
//
unsigned InlineCostAnalyzer::FunctionInfo::
         CountCodeReductionForConstant(Value *V) {
  unsigned Reduction = 0;
  for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI)
    if (isa<BranchInst>(*UI))
      Reduction += 40;          // Eliminating a conditional branch is a big win
    else if (SwitchInst *SI = dyn_cast<SwitchInst>(*UI))
      // Eliminating a switch is a big win, proportional to the number of edges
      // deleted.
      Reduction += (SI->getNumSuccessors()-1) * 40;
    else if (CallInst *CI = dyn_cast<CallInst>(*UI)) {
      // Turning an indirect call into a direct call is a BIG win
      Reduction += CI->getCalledValue() == V ? 500 : 0;
    } else if (InvokeInst *II = dyn_cast<InvokeInst>(*UI)) {
      // Turning an indirect call into a direct call is a BIG win
      Reduction += II->getCalledValue() == V ? 500 : 0;
    } else {
      // Figure out if this instruction will be removed due to simple constant
      // propagation.
      Instruction &Inst = cast<Instruction>(**UI);

      // We can't constant propagate instructions which have effects or
      // read memory.
      //
      // FIXME: It would be nice to capture the fact that a load from a
      // pointer-to-constant-global is actually a *really* good thing to zap.
      // Unfortunately, we don't know the pointer that may get propagated here,
      // so we can't make this decision.
      if (Inst.mayReadFromMemory() || Inst.mayHaveSideEffects() ||
          isa<AllocationInst>(Inst))
        continue;

      bool AllOperandsConstant = true;
      for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i)
        if (!isa<Constant>(Inst.getOperand(i)) && Inst.getOperand(i) != V) {
          AllOperandsConstant = false;
          break;
        }

      if (AllOperandsConstant) {
        // We will get to remove this instruction...
        Reduction += 7;

        // And any other instructions that use it which become constants
        // themselves.
        Reduction += CountCodeReductionForConstant(&Inst);
      }
    }

  return Reduction;
}

// CountCodeReductionForAlloca - Figure out an approximation of how much smaller
// the function will be if it is inlined into a context where an argument
// becomes an alloca.
//
unsigned InlineCostAnalyzer::FunctionInfo::
         CountCodeReductionForAlloca(Value *V) {
  if (!isa<PointerType>(V->getType())) return 0;  // Not a pointer
  unsigned Reduction = 0;
  for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){
    Instruction *I = cast<Instruction>(*UI);
    if (isa<LoadInst>(I) || isa<StoreInst>(I))
      Reduction += 10;
    else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(I)) {
      // If the GEP has variable indices, we won't be able to do much with it.
      if (!GEP->hasAllConstantIndices())
        Reduction += CountCodeReductionForAlloca(GEP)+15;
    } else {
      // If there is some other strange instruction, we're not going to be able
      // to do much if we inline this.
      return 0;
    }
  }

  return Reduction;
}

/// analyzeBasicBlock - Fill in the current structure with information gleaned
/// from the specified block.
void CodeMetrics::analyzeBasicBlock(const BasicBlock *BB) {
  ++NumBlocks;

  for (BasicBlock::const_iterator II = BB->begin(), E = BB->end();
       II != E; ++II) {
    if (isa<PHINode>(II)) continue;           // PHI nodes don't count.

    // Special handling for calls.
    if (isa<CallInst>(II) || isa<InvokeInst>(II)) {
      if (isa<DbgInfoIntrinsic>(II))
        continue;  // Debug intrinsics don't count as size.

      CallSite CS = CallSite::get(const_cast<Instruction*>(&*II));

      // If this function contains a call to setjmp or _setjmp, never inline
      // it.  This is a hack because we depend on the user marking their local
      // variables as volatile if they are live across a setjmp call, and they
      // probably won't do this in callers.
      if (Function *F = CS.getCalledFunction())
        if (F->isDeclaration() &&
            (F->getName() == "setjmp" || F->getName() == "_setjmp"))
          NeverInline = true;

      // Calls often compile into many machine instructions.  Bump up their
      // cost to reflect this.
      if (!isa<IntrinsicInst>(II))
        NumInsts += InlineConstants::CallPenalty;
    }

    // These, too, are calls.
    if (isa<MallocInst>(II) || isa<FreeInst>(II))
      NumInsts += InlineConstants::CallPenalty;

    if (const AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
      if (!AI->isStaticAlloca())
        this->usesDynamicAlloca = true;
    }

    if (isa<ExtractElementInst>(II) || isa<VectorType>(II->getType()))
      ++NumVectorInsts;

    // Noop casts, including ptr <-> int,  don't count.
    if (const CastInst *CI = dyn_cast<CastInst>(II)) {
      if (CI->isLosslessCast() || isa<IntToPtrInst>(CI) ||
          isa<PtrToIntInst>(CI))
        continue;
    } else if (const GetElementPtrInst *GEPI =
               dyn_cast<GetElementPtrInst>(II)) {
      // If a GEP has all constant indices, it will probably be folded with
      // a load/store.
      if (GEPI->hasAllConstantIndices())
        continue;
    }

    if (isa<ReturnInst>(II))
      ++NumRets;

    ++NumInsts;
  }
}

/// analyzeFunction - Fill in the current structure with information gleaned
/// from the specified function.
void CodeMetrics::analyzeFunction(Function *F) {
  // Look at the size of the callee.
  for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
    analyzeBasicBlock(&*BB);
}

/// analyzeFunction - Fill in the current structure with information gleaned
/// from the specified function.
void InlineCostAnalyzer::FunctionInfo::analyzeFunction(Function *F) {
  Metrics.analyzeFunction(F);

  // A function with exactly one return has it removed during the inlining
  // process (see InlineFunction), so don't count it.
  // FIXME: This knowledge should really be encoded outside of FunctionInfo.
  if (Metrics.NumRets==1)
    --Metrics.NumInsts;

  // Check out all of the arguments to the function, figuring out how much
  // code can be eliminated if one of the arguments is a constant.
  for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
    ArgumentWeights.push_back(ArgInfo(CountCodeReductionForConstant(I),
                                      CountCodeReductionForAlloca(I)));
}

// getInlineCost - The heuristic used to determine if we should inline the
// function call or not.
//
InlineCost InlineCostAnalyzer::getInlineCost(CallSite CS,
                               SmallPtrSet<const Function *, 16> &NeverInline) {
  Instruction *TheCall = CS.getInstruction();
  Function *Callee = CS.getCalledFunction();
  Function *Caller = TheCall->getParent()->getParent();

  // Don't inline functions which can be redefined at link-time to mean
  // something else.  Don't inline functions marked noinline.
  if (Callee->mayBeOverridden() ||
      Callee->hasFnAttr(Attribute::NoInline) || NeverInline.count(Callee))
    return llvm::InlineCost::getNever();

  // InlineCost - This value measures how good of an inline candidate this call
  // site is to inline.  A lower inline cost make is more likely for the call to
  // be inlined.  This value may go negative.
  //
  int InlineCost = 0;

  // If there is only one call of the function, and it has internal linkage,
  // make it almost guaranteed to be inlined.
  //
  if (Callee->hasLocalLinkage() && Callee->hasOneUse())
    InlineCost += InlineConstants::LastCallToStaticBonus;

  // If this function uses the coldcc calling convention, prefer not to inline
  // it.
  if (Callee->getCallingConv() == CallingConv::Cold)
    InlineCost += InlineConstants::ColdccPenalty;

  // If the instruction after the call, or if the normal destination of the
  // invoke is an unreachable instruction, the function is noreturn.  As such,
  // there is little point in inlining this.
  if (InvokeInst *II = dyn_cast<InvokeInst>(TheCall)) {
    if (isa<UnreachableInst>(II->getNormalDest()->begin()))
      InlineCost += InlineConstants::NoreturnPenalty;
  } else if (isa<UnreachableInst>(++BasicBlock::iterator(TheCall)))
    InlineCost += InlineConstants::NoreturnPenalty;

  // Get information about the callee...
  FunctionInfo &CalleeFI = CachedFunctionInfo[Callee];

  // If we haven't calculated this information yet, do so now.
  if (CalleeFI.Metrics.NumBlocks == 0)
    CalleeFI.analyzeFunction(Callee);

  // If we should never inline this, return a huge cost.
  if (CalleeFI.Metrics.NeverInline)
    return InlineCost::getNever();

  // FIXME: It would be nice to kill off CalleeFI.NeverInline. Then we
  // could move this up and avoid computing the FunctionInfo for
  // things we are going to just return always inline for. This
  // requires handling setjmp somewhere else, however.
  if (!Callee->isDeclaration() && Callee->hasFnAttr(Attribute::AlwaysInline))
    return InlineCost::getAlways();

  if (CalleeFI.Metrics.usesDynamicAlloca) {
    // Get infomation about the caller...
    FunctionInfo &CallerFI = CachedFunctionInfo[Caller];

    // If we haven't calculated this information yet, do so now.
    if (CallerFI.Metrics.NumBlocks == 0)
      CallerFI.analyzeFunction(Caller);

    // Don't inline a callee with dynamic alloca into a caller without them.
    // Functions containing dynamic alloca's are inefficient in various ways;
    // don't create more inefficiency.
    if (!CallerFI.Metrics.usesDynamicAlloca)
      return InlineCost::getNever();
  }

  // Add to the inline quality for properties that make the call valuable to
  // inline.  This includes factors that indicate that the result of inlining
  // the function will be optimizable.  Currently this just looks at arguments
  // passed into the function.
  //
  unsigned ArgNo = 0;
  for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
       I != E; ++I, ++ArgNo) {
    // Each argument passed in has a cost at both the caller and the callee
    // sides.  This favors functions that take many arguments over functions
    // that take few arguments.
    InlineCost -= 20;

    // If this is a function being passed in, it is very likely that we will be
    // able to turn an indirect function call into a direct function call.
    if (isa<Function>(I))
      InlineCost -= 100;

    // If an alloca is passed in, inlining this function is likely to allow
    // significant future optimization possibilities (like scalar promotion, and
    // scalarization), so encourage the inlining of the function.
    //
    else if (isa<AllocaInst>(I)) {
      if (ArgNo < CalleeFI.ArgumentWeights.size())
        InlineCost -= CalleeFI.ArgumentWeights[ArgNo].AllocaWeight;

      // If this is a constant being passed into the function, use the argument
      // weights calculated for the callee to determine how much will be folded
      // away with this information.
    } else if (isa<Constant>(I)) {
      if (ArgNo < CalleeFI.ArgumentWeights.size())
        InlineCost -= CalleeFI.ArgumentWeights[ArgNo].ConstantWeight;
    }
  }

  // Now that we have considered all of the factors that make the call site more
  // likely to be inlined, look at factors that make us not want to inline it.

  // Don't inline into something too big, which would make it bigger.
  // "size" here is the number of basic blocks, not instructions.
  //
  InlineCost += Caller->size()/15;

  // Look at the size of the callee. Each instruction counts as 5.
  InlineCost += CalleeFI.Metrics.NumInsts*5;

  return llvm::InlineCost::get(InlineCost);
}

// getInlineFudgeFactor - Return a > 1.0 factor if the inliner should use a
// higher threshold to determine if the function call should be inlined.
float InlineCostAnalyzer::getInlineFudgeFactor(CallSite CS) {
  Function *Callee = CS.getCalledFunction();

  // Get information about the callee...
  FunctionInfo &CalleeFI = CachedFunctionInfo[Callee];

  // If we haven't calculated this information yet, do so now.
  if (CalleeFI.Metrics.NumBlocks == 0)
    CalleeFI.analyzeFunction(Callee);

  float Factor = 1.0f;
  // Single BB functions are often written to be inlined.
  if (CalleeFI.Metrics.NumBlocks == 1)
    Factor += 0.5f;

  // Be more aggressive if the function contains a good chunk (if it mades up
  // at least 10% of the instructions) of vector instructions.
  if (CalleeFI.Metrics.NumVectorInsts > CalleeFI.Metrics.NumInsts/2)
    Factor += 2.0f;
  else if (CalleeFI.Metrics.NumVectorInsts > CalleeFI.Metrics.NumInsts/10)
    Factor += 1.5f;
  return Factor;
}
<|endoftext|>


<commit_before>/*

Copyright (c) 2006, Arvid Norberg
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 author 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.

*/

#include <boost/version.hpp>
#include "libtorrent/pch.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/error_code.hpp"

#include <iostream>

namespace libtorrent
{
	using boost::multi_index::nth_index;
	using boost::multi_index::get;

	boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p
		, int m, error_code& ec)
	{
		TORRENT_ASSERT(st != 0);
		TORRENT_ASSERT(p.is_complete());
		TORRENT_ASSERT((m & file::rw_mask) == file::read_only
			|| (m & file::rw_mask) == file::read_write);
		boost::mutex::scoped_lock l(m_mutex);
		typedef nth_index<file_set, 0>::type path_view;
		path_view& pt = get<0>(m_files);
		path_view::iterator i = pt.find(p);
		if (i != pt.end())
		{
			lru_file_entry e = *i;
			e.last_use = time_now();

			if (e.key != st)
			{
				// this means that another instance of the storage
				// is using the exact same file.
#if BOOST_VERSION >= 103500
				ec = error_code(errors::file_collision, libtorrent_category);
#endif
				return boost::shared_ptr<file>();
			}

			e.key = st;
			// if we asked for a file in write mode,
			// and the cached file is is not opened in
			// write mode, re-open it
			if (((e.mode & file::rw_mask) != file::read_write)
				&& ((m & file::rw_mask) == file::read_write))
			{
				// close the file before we open it with
				// the new read/write privilages
				i->file_ptr.reset();
				TORRENT_ASSERT(e.file_ptr.unique());
				e.file_ptr->close();
				if (!e.file_ptr->open(p, m, ec))
				{
					m_files.erase(i);
					return boost::shared_ptr<file>();
				}
				TORRENT_ASSERT(e.file_ptr->is_open());
				e.mode = m;
			}
			pt.replace(i, e);
			TORRENT_ASSERT((e.mode & ~file::rw_mask) == (m & ~file::rw_mask));
			return e.file_ptr;
		}
		// the file is not in our cache
		if ((int)m_files.size() >= m_size)
		{
			// the file cache is at its maximum size, close
			// the least recently used (lru) file from it
			typedef nth_index<file_set, 1>::type lru_view;
			lru_view& lt = get<1>(m_files);
			lru_view::iterator i = lt.begin();
			// the first entry in this view is the least recently used
			TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use));
			lt.erase(i);
		}
		lru_file_entry e;
		e.file_ptr.reset(new (std::nothrow)file);
		if (!e.file_ptr)
		{
			ec = error_code(ENOMEM, get_posix_category());
			return e.file_ptr;
		}
		if (!e.file_ptr->open(p, m, ec))
			return boost::shared_ptr<file>();
		e.mode = m;
		e.key = st;
		e.file_path = p;
		pt.insert(e);
		TORRENT_ASSERT(e.file_ptr->is_open());
		return e.file_ptr;
	}

	void file_pool::release(fs::path const& p)
	{
		boost::mutex::scoped_lock l(m_mutex);

		typedef nth_index<file_set, 0>::type path_view;
		path_view& pt = get<0>(m_files);
		path_view::iterator i = pt.find(p);
		if (i != pt.end()) pt.erase(i);
	}

	void file_pool::release(void* st)
	{
		boost::mutex::scoped_lock l(m_mutex);
		TORRENT_ASSERT(st != 0);
		using boost::tie;

		typedef nth_index<file_set, 2>::type key_view;
		key_view& kt = get<2>(m_files);

		key_view::iterator start, end;
		tie(start, end) = kt.equal_range(st);
		kt.erase(start, end);
	}

	void file_pool::resize(int size)
	{
		TORRENT_ASSERT(size > 0);
		if (size == m_size) return;
		boost::mutex::scoped_lock l(m_mutex);
		m_size = size;
		if (int(m_files.size()) <= m_size) return;

		// close the least recently used files
		typedef nth_index<file_set, 1>::type lru_view;
		lru_view& lt = get<1>(m_files);
		lru_view::iterator i = lt.begin();
		while (int(m_files.size()) > m_size)
		{
			// the first entry in this view is the least recently used
			TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use));
			lt.erase(i++);
		}
	}

}
<commit_msg>allow torrents sharing files as long as they're both opened in read-only mode<commit_after>/*

Copyright (c) 2006, Arvid Norberg
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 author 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.

*/

#include <boost/version.hpp>
#include "libtorrent/pch.hpp"
#include "libtorrent/file_pool.hpp"
#include "libtorrent/error_code.hpp"

#include <iostream>

namespace libtorrent
{
	using boost::multi_index::nth_index;
	using boost::multi_index::get;

	boost::shared_ptr<file> file_pool::open_file(void* st, fs::path const& p
		, int m, error_code& ec)
	{
		TORRENT_ASSERT(st != 0);
		TORRENT_ASSERT(p.is_complete());
		TORRENT_ASSERT((m & file::rw_mask) == file::read_only
			|| (m & file::rw_mask) == file::read_write);
		boost::mutex::scoped_lock l(m_mutex);
		typedef nth_index<file_set, 0>::type path_view;
		path_view& pt = get<0>(m_files);
		path_view::iterator i = pt.find(p);
		if (i != pt.end())
		{
			lru_file_entry e = *i;
			e.last_use = time_now();

			if (e.key != st && ((e.mode & file::rw_mask) != file::read_only
				|| (m & file::rw_mask) != file::read_only))
			{
				// this means that another instance of the storage
				// is using the exact same file.
#if BOOST_VERSION >= 103500
				ec = error_code(errors::file_collision, libtorrent_category);
#endif
				return boost::shared_ptr<file>();
			}

			e.key = st;
			// if we asked for a file in write mode,
			// and the cached file is is not opened in
			// write mode, re-open it
			if (((e.mode & file::rw_mask) != file::read_write)
				&& ((m & file::rw_mask) == file::read_write))
			{
				// close the file before we open it with
				// the new read/write privilages
				i->file_ptr.reset();
				TORRENT_ASSERT(e.file_ptr.unique());
				e.file_ptr->close();
				if (!e.file_ptr->open(p, m, ec))
				{
					m_files.erase(i);
					return boost::shared_ptr<file>();
				}
				TORRENT_ASSERT(e.file_ptr->is_open());
				e.mode = m;
			}
			pt.replace(i, e);
			TORRENT_ASSERT((e.mode & ~file::rw_mask) == (m & ~file::rw_mask));
			return e.file_ptr;
		}
		// the file is not in our cache
		if ((int)m_files.size() >= m_size)
		{
			// the file cache is at its maximum size, close
			// the least recently used (lru) file from it
			typedef nth_index<file_set, 1>::type lru_view;
			lru_view& lt = get<1>(m_files);
			lru_view::iterator i = lt.begin();
			// the first entry in this view is the least recently used
			TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use));
			lt.erase(i);
		}
		lru_file_entry e;
		e.file_ptr.reset(new (std::nothrow)file);
		if (!e.file_ptr)
		{
			ec = error_code(ENOMEM, get_posix_category());
			return e.file_ptr;
		}
		if (!e.file_ptr->open(p, m, ec))
			return boost::shared_ptr<file>();
		e.mode = m;
		e.key = st;
		e.file_path = p;
		pt.insert(e);
		TORRENT_ASSERT(e.file_ptr->is_open());
		return e.file_ptr;
	}

	void file_pool::release(fs::path const& p)
	{
		boost::mutex::scoped_lock l(m_mutex);

		typedef nth_index<file_set, 0>::type path_view;
		path_view& pt = get<0>(m_files);
		path_view::iterator i = pt.find(p);
		if (i != pt.end()) pt.erase(i);
	}

	void file_pool::release(void* st)
	{
		boost::mutex::scoped_lock l(m_mutex);
		TORRENT_ASSERT(st != 0);
		using boost::tie;

		typedef nth_index<file_set, 2>::type key_view;
		key_view& kt = get<2>(m_files);

		key_view::iterator start, end;
		tie(start, end) = kt.equal_range(st);
		kt.erase(start, end);
	}

	void file_pool::resize(int size)
	{
		TORRENT_ASSERT(size > 0);
		if (size == m_size) return;
		boost::mutex::scoped_lock l(m_mutex);
		m_size = size;
		if (int(m_files.size()) <= m_size) return;

		// close the least recently used files
		typedef nth_index<file_set, 1>::type lru_view;
		lru_view& lt = get<1>(m_files);
		lru_view::iterator i = lt.begin();
		while (int(m_files.size()) > m_size)
		{
			// the first entry in this view is the least recently used
			TORRENT_ASSERT(lt.size() == 1 || (i->last_use <= boost::next(i)->last_use));
			lt.erase(i++);
		}
	}

}
<|endoftext|>


<commit_before><commit_msg>don't run the component manager gc in a job each<commit_after><|endoftext|>


<commit_before>/*-------------FDTD.cpp-------------------------------------------------------//
*
*              Finite Difference Time Domain
*
* Purpose: To replicate the results of our invisible lense raytracer with
*          FDTD. Woo!
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>

// This is the function we writs the bulk of the code in
void FDTD(std::vector<double>& Ez, std::vector<double>& Hy,
          const int final_time, const double eps, std::ofstream& output);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/

int main(){

    // defines output
    std::ofstream output("FDTD.dat", std::ofstream::out);

    int space = 200, final_time = 200;
    double eps = 377.0;

    // define initial E and H fields
    std::vector<double> Ez(space, 0.0), Hy(space, 0.0);

    FDTD(Ez, Hy, final_time, eps, output);

}

/*----------------------------------------------------------------------------//
* SUBROUTINES
*-----------------------------------------------------------------------------*/

// This is the function we writs the bulk of the code in
void FDTD(std::vector<double>& Ez, std::vector<double>& Hy,
          const int final_time, const double eps, std::ofstream& output){

    int space = Hy.size();

    // Time looping
    for (size_t t = 0; t < final_time; t++){

        // update magnetic field
        for (size_t dx = 0 ; dx < space - 1; dx++){
            Hy[dx] += (Ez[dx + 1] - Ez[dx]) / eps;
        }

        // update electric field
        for (size_t dx = 1; dx < space; dx++){
            Ez[dx] += (Hy[dx] - Hy[dx-1]) / eps;
        }

        // set src for next step
        Ez[0] = exp(-(t - 30.0) * (t - 30.0)/100.0);

        output << Ez[50] << '\n';

    }
}
<commit_msg>fixed a small bug, accidentally divided by eps<commit_after>/*-------------FDTD.cpp-------------------------------------------------------//
*
*              Finite Difference Time Domain
*
* Purpose: To replicate the results of our invisible lense raytracer with
*          FDTD. Woo!
*
*-----------------------------------------------------------------------------*/

#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>

// This is the function we writs the bulk of the code in
void FDTD(std::vector<double>& Ez, std::vector<double>& Hy,
          const int final_time, const double eps, const int space,
          std::ofstream& output);

/*----------------------------------------------------------------------------//
* MAIN
*-----------------------------------------------------------------------------*/

int main(){

    // defines output
    std::ofstream output("FDTD.dat", std::ofstream::out);

    int space = 200, final_time = 200;
    double eps = 377.0;

    // define initial E and H fields
    std::vector<double> Ez(space, 0.0), Hy(space, 0.0);

    FDTD(Ez, Hy, final_time, eps, space, output);

}

/*----------------------------------------------------------------------------//
* SUBROUTINES
*-----------------------------------------------------------------------------*/

// This is the function we writs the bulk of the code in
void FDTD(std::vector<double>& Ez, std::vector<double>& Hy,
          const int final_time, const double eps, const int space,
          std::ofstream& output){

    // Time looping
    for (size_t t = 0; t < final_time; t++){

        // update magnetic field
        for (size_t dx = 0; dx < space - 1; dx++){
            Hy[dx] += (Ez[dx + 1] - Ez[dx]) / eps;
        }

        // update electric field
        for (size_t dx = 1; dx < space; dx++){
            Ez[dx] += (Hy[dx] - Hy[dx-1]) * eps;
            output << Ez[dx] << '\n';
        }

        // set src for next step
        Ez[0] = exp(-(t - 30.0) * (t - 30.0)/100.0);

        output << '\n' << '\n';

    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xolefactory.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 18:46:20 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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 for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef __XFACTORY_HXX_
#define __XFACTORY_HXX_

#ifndef _COM_SUN_STAR_EMBED_XEMBEDOBJECTCREATOR_HPP_
#include <com/sun/star/embed/XEmbedObjectCreator.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XEMBEDOBJECTFACTORY_HPP_
#include <com/sun/star/embed/XEmbedObjectFactory.hpp>
#endif
#ifndef _COM_SUN_STAR_EMBED_XLINKCREATOR_HPP_
#include <com/sun/star/embed/XLinkCreator.hpp>
#endif

#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _CPPUHELPER_IMPLBASE4_HXX_
#include <cppuhelper/implbase4.hxx>
#endif

class OleEmbeddedObjectFactory : public ::cppu::WeakImplHelper4<
                                                ::com::sun::star::embed::XEmbedObjectCreator,
                                                ::com::sun::star::embed::XEmbedObjectFactory,
                                                ::com::sun::star::embed::XLinkCreator,
                                                ::com::sun::star::lang::XServiceInfo >
{
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory;

public:
    OleEmbeddedObjectFactory(
        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory )
    : m_xFactory( xFactory )
    {
        OSL_ENSURE( xFactory.is(), "No service manager is provided!\n" );
    }

    static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL impl_staticGetSupportedServiceNames();

    static ::rtl::OUString SAL_CALL impl_staticGetImplementationName();

    static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
        impl_staticCreateSelfInstance(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager );

    // XEmbedObjectCreator
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitNew( const ::com::sun::star::uno::Sequence< sal_Int8 >& aClassID, const ::rtl::OUString& aClassName, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitFromEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMedDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitFromMediaDescriptor( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XEmbedObjectFactory
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceUserInit( const ::com::sun::star::uno::Sequence< sal_Int8 >& aClassID, const ::rtl::OUString& aClassName, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, sal_Int32 nEntryConnectionMode, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArguments, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XLinkCreator
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceLink( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName() throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (::com::sun::star::uno::RuntimeException);

};

#endif

<commit_msg>INTEGRATION: CWS changefileheader (1.6.122); FILE MERGED 2008/04/01 15:13:51 thb 1.6.122.3: #i85898# Stripping all external header guards 2008/04/01 12:28:54 thb 1.6.122.2: #i85898# Stripping all external header guards 2008/03/31 13:33:21 rt 1.6.122.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: xolefactory.hxx,v $
 * $Revision: 1.7 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef __XFACTORY_HXX_
#define __XFACTORY_HXX_

#include <com/sun/star/embed/XEmbedObjectCreator.hpp>
#include <com/sun/star/embed/XEmbedObjectFactory.hpp>
#include <com/sun/star/embed/XLinkCreator.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>

#include <cppuhelper/implbase4.hxx>

class OleEmbeddedObjectFactory : public ::cppu::WeakImplHelper4<
                                                ::com::sun::star::embed::XEmbedObjectCreator,
                                                ::com::sun::star::embed::XEmbedObjectFactory,
                                                ::com::sun::star::embed::XLinkCreator,
                                                ::com::sun::star::lang::XServiceInfo >
{
    ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > m_xFactory;

public:
    OleEmbeddedObjectFactory(
        const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xFactory )
    : m_xFactory( xFactory )
    {
        OSL_ENSURE( xFactory.is(), "No service manager is provided!\n" );
    }

    static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL impl_staticGetSupportedServiceNames();

    static ::rtl::OUString SAL_CALL impl_staticGetImplementationName();

    static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
        impl_staticCreateSelfInstance(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager );

    // XEmbedObjectCreator
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitNew( const ::com::sun::star::uno::Sequence< sal_Int8 >& aClassID, const ::rtl::OUString& aClassName, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitFromEntry( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMedDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceInitFromMediaDescriptor( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XEmbedObjectFactory
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceUserInit( const ::com::sun::star::uno::Sequence< sal_Int8 >& aClassID, const ::rtl::OUString& aClassName, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, sal_Int32 nEntryConnectionMode, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lArguments, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XLinkCreator
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL createInstanceLink( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, const ::rtl::OUString& sEntName, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescr, const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lObjArgs ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException);

    // XServiceInfo
    virtual ::rtl::OUString SAL_CALL getImplementationName() throw (::com::sun::star::uno::RuntimeException);
    virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw (::com::sun::star::uno::RuntimeException);

};

#endif

<|endoftext|>


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

#include "file_request.hxx"
#include "static_headers.hxx"
#include "HttpResponseHandler.hxx"
#include "strmap.hxx"
#include "istream/UnusedPtr.hxx"
#include "istream/FileIstream.hxx"
#include "istream/FdIstream.hxx"
#include "istream/UringIstream.hxx"
#include "pool/pool.hxx"
#include "io/Open.hxx"
#include "io/UniqueFileDescriptor.hxx"
#include "system/Error.hxx"
#include "http/Status.h"

#ifdef HAVE_URING
#include "io/uring/Handler.hxx"
#include "io/uring/OpenStat.hxx"
#include "util/Cancellable.hxx"
#include <sys/sysmacros.h> // for makedev()
#endif

#include <assert.h>
#include <sys/stat.h>
#include <fcntl.h>

#ifdef HAVE_URING

class UringStaticFileGet final : Uring::OpenStatHandler, Cancellable {
	struct pool &pool;
	EventLoop &event_loop;

	const char *const path;
	const char *const content_type;

	Uring::OpenStat open_stat;

	HttpResponseHandler &handler;

public:
	UringStaticFileGet(EventLoop &_event_loop, Uring::Queue &uring,
			   struct pool &_pool,
			   const char *_path,
			   const char *_content_type,
			   HttpResponseHandler &_handler) noexcept
		:pool(_pool), event_loop(_event_loop),
		 path(_path),
		 content_type(_content_type),
		 open_stat(uring, *this),
		 handler(_handler) {}

	void Start(CancellablePointer &cancel_ptr) noexcept {
		cancel_ptr = *this;
		open_stat.StartOpenStatReadOnly(path);
	}

private:
	void Destroy() noexcept {
		this->~UringStaticFileGet();
	}

	/* virtual methods from class Cancellable */
	void Cancel() noexcept override {
		Destroy();
	}

	/* virtual methods from class Uring::OpenStatHandler */
	void OnOpenStat(UniqueFileDescriptor fd,
			struct statx &st) noexcept override;

	void OnOpenStatError(std::exception_ptr e) noexcept override {
		auto &_handler = handler;
		Destroy();
		_handler.InvokeError(std::move(e));
	}
};

void
UringStaticFileGet::OnOpenStat(UniqueFileDescriptor fd,
			       struct statx &stx) noexcept
{
	const char *_content_type = content_type;
	auto &_handler = handler;

	Destroy();

	if (S_ISCHR(stx.stx_mode)) {
		_handler.InvokeResponse(HTTP_STATUS_OK, {},
					NewFdIstream(event_loop, pool, path,
						     std::move(fd),
						     FdType::FD_CHARDEV));
		return;
	} else if (!S_ISREG(stx.stx_mode)) {
		_handler.InvokeResponse(pool, HTTP_STATUS_NOT_FOUND,
					"Not a regular file");
		return;
	}

	/* copy the struct statx to an old-style struct stat (this can
	   be removed once be migrate everything to struct statx) */
	struct stat st;
	st.st_mode = stx.stx_mode;
	st.st_size = stx.stx_size;
	st.st_mtime = stx.stx_mtime.tv_sec;
	st.st_dev = makedev(stx.stx_dev_major, stx.stx_dev_minor);
	st.st_ino = stx.stx_ino;

	auto headers = static_response_headers(pool, fd, st, _content_type);

	_handler.InvokeResponse(HTTP_STATUS_OK,
				std::move(headers),
				NewUringIstream(open_stat.GetQueue(), pool,
						path, std::move(fd),
						0, stx.stx_size));
}

#endif

void
static_file_get(EventLoop &event_loop,
#ifdef HAVE_URING
		Uring::Queue *uring,
#endif
		struct pool &pool,
		const char *path, const char *content_type,
		HttpResponseHandler &handler, CancellablePointer &cancel_ptr)
{
	assert(path != nullptr);

#ifdef HAVE_URING
	if (uring != nullptr) {
		auto *o = NewFromPool<UringStaticFileGet>(pool, event_loop,
							  *uring, pool,
							  path, content_type,
							  handler);
		o->Start(cancel_ptr);
		return;
	}
#else
	(void)cancel_ptr;
#endif

	UniqueFileDescriptor fd;
	struct stat st;

	try {
		fd = OpenReadOnly(path, O_NOFOLLOW);
		if (fstat(fd.Get(), &st) < 0)
			throw FormatErrno("Failed to stat %s", path);
	} catch (...) {
		handler.InvokeError(std::current_exception());
		return;
	}

	if (S_ISCHR(st.st_mode)) {
		handler.InvokeResponse(HTTP_STATUS_OK, {},
				       NewFdIstream(event_loop, pool, path,
						    std::move(fd),
						    FdType::FD_CHARDEV));
		return;
	} else if (!S_ISREG(st.st_mode)) {
		handler.InvokeResponse(pool, HTTP_STATUS_NOT_FOUND,
				       "Not a regular file");
		return;
	}

	auto headers = static_response_headers(pool, fd, st, content_type);

	handler.InvokeResponse(HTTP_STATUS_OK,
			       std::move(headers),
#ifdef HAVE_URING
			       uring != nullptr
			       ? NewUringIstream(*uring, pool, path,
						 std::move(fd), 0, st.st_size)
			       :
#endif
			       istream_file_fd_new(event_loop, pool, path,
						   std::move(fd),
						   0, st.st_size));
}
<commit_msg>file_request: remove unreachable io_uring code<commit_after>/*
 * Copyright 2007-2020 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "file_request.hxx"
#include "static_headers.hxx"
#include "HttpResponseHandler.hxx"
#include "strmap.hxx"
#include "istream/UnusedPtr.hxx"
#include "istream/FileIstream.hxx"
#include "istream/FdIstream.hxx"
#include "istream/UringIstream.hxx"
#include "pool/pool.hxx"
#include "io/Open.hxx"
#include "io/UniqueFileDescriptor.hxx"
#include "system/Error.hxx"
#include "http/Status.h"

#ifdef HAVE_URING
#include "io/uring/Handler.hxx"
#include "io/uring/OpenStat.hxx"
#include "util/Cancellable.hxx"
#include <sys/sysmacros.h> // for makedev()
#endif

#include <assert.h>
#include <sys/stat.h>
#include <fcntl.h>

#ifdef HAVE_URING

class UringStaticFileGet final : Uring::OpenStatHandler, Cancellable {
	struct pool &pool;
	EventLoop &event_loop;

	const char *const path;
	const char *const content_type;

	Uring::OpenStat open_stat;

	HttpResponseHandler &handler;

public:
	UringStaticFileGet(EventLoop &_event_loop, Uring::Queue &uring,
			   struct pool &_pool,
			   const char *_path,
			   const char *_content_type,
			   HttpResponseHandler &_handler) noexcept
		:pool(_pool), event_loop(_event_loop),
		 path(_path),
		 content_type(_content_type),
		 open_stat(uring, *this),
		 handler(_handler) {}

	void Start(CancellablePointer &cancel_ptr) noexcept {
		cancel_ptr = *this;
		open_stat.StartOpenStatReadOnly(path);
	}

private:
	void Destroy() noexcept {
		this->~UringStaticFileGet();
	}

	/* virtual methods from class Cancellable */
	void Cancel() noexcept override {
		Destroy();
	}

	/* virtual methods from class Uring::OpenStatHandler */
	void OnOpenStat(UniqueFileDescriptor fd,
			struct statx &st) noexcept override;

	void OnOpenStatError(std::exception_ptr e) noexcept override {
		auto &_handler = handler;
		Destroy();
		_handler.InvokeError(std::move(e));
	}
};

void
UringStaticFileGet::OnOpenStat(UniqueFileDescriptor fd,
			       struct statx &stx) noexcept
{
	const char *_content_type = content_type;
	auto &_handler = handler;

	Destroy();

	if (S_ISCHR(stx.stx_mode)) {
		_handler.InvokeResponse(HTTP_STATUS_OK, {},
					NewFdIstream(event_loop, pool, path,
						     std::move(fd),
						     FdType::FD_CHARDEV));
		return;
	} else if (!S_ISREG(stx.stx_mode)) {
		_handler.InvokeResponse(pool, HTTP_STATUS_NOT_FOUND,
					"Not a regular file");
		return;
	}

	/* copy the struct statx to an old-style struct stat (this can
	   be removed once be migrate everything to struct statx) */
	struct stat st;
	st.st_mode = stx.stx_mode;
	st.st_size = stx.stx_size;
	st.st_mtime = stx.stx_mtime.tv_sec;
	st.st_dev = makedev(stx.stx_dev_major, stx.stx_dev_minor);
	st.st_ino = stx.stx_ino;

	auto headers = static_response_headers(pool, fd, st, _content_type);

	_handler.InvokeResponse(HTTP_STATUS_OK,
				std::move(headers),
				NewUringIstream(open_stat.GetQueue(), pool,
						path, std::move(fd),
						0, stx.stx_size));
}

#endif

void
static_file_get(EventLoop &event_loop,
#ifdef HAVE_URING
		Uring::Queue *uring,
#endif
		struct pool &pool,
		const char *path, const char *content_type,
		HttpResponseHandler &handler, CancellablePointer &cancel_ptr)
{
	assert(path != nullptr);

#ifdef HAVE_URING
	if (uring != nullptr) {
		auto *o = NewFromPool<UringStaticFileGet>(pool, event_loop,
							  *uring, pool,
							  path, content_type,
							  handler);
		o->Start(cancel_ptr);
		return;
	}
#else
	(void)cancel_ptr;
#endif

	UniqueFileDescriptor fd;
	struct stat st;

	try {
		fd = OpenReadOnly(path, O_NOFOLLOW);
		if (fstat(fd.Get(), &st) < 0)
			throw FormatErrno("Failed to stat %s", path);
	} catch (...) {
		handler.InvokeError(std::current_exception());
		return;
	}

	if (S_ISCHR(st.st_mode)) {
		handler.InvokeResponse(HTTP_STATUS_OK, {},
				       NewFdIstream(event_loop, pool, path,
						    std::move(fd),
						    FdType::FD_CHARDEV));
		return;
	} else if (!S_ISREG(st.st_mode)) {
		handler.InvokeResponse(pool, HTTP_STATUS_NOT_FOUND,
				       "Not a regular file");
		return;
	}

	auto headers = static_response_headers(pool, fd, st, content_type);

	handler.InvokeResponse(HTTP_STATUS_OK,
			       std::move(headers),
			       istream_file_fd_new(event_loop, pool, path,
						   std::move(fd),
						   0, st.st_size));
}
<|endoftext|>


<commit_before>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011  Martin Raiber
*
*    This program is free software: 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 3 of the License, or
*    (at your option) any later version.
*
*    This program 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 General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "../vld.h"
#include <fstream>
#include <iostream>
#ifdef _WIN32
#	include <conio.h>
#endif
#include "../Interface/Server.h"
#include "CTCPFileServ.h"
#include "settings.h"
#include "../stringtools.h"
#include "CampusThread.h"
#include "log.h"

std::fstream logfile;
#ifdef CAMPUS
CCampusThread *ct=NULL;
#endif
CTCPFileServ *TCPServer=NULL;

#ifdef _DEBUG
#ifdef _WIN32
#pragma comment(lib, "vld.lib")
#endif
#endif

#ifdef LINUX
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#endif

#ifdef DLL_EXPORT
#	define EXPORT_METHOD_INT 5
#endif

void WriteReg(void)
{
#ifndef LINUX
	HKEY hkey;
	LONG ret=RegCreateKeyExA(HKEY_LOCAL_MACHINE,"SOFTWARE\\UrInstaller\\settings",0,0,REG_OPTION_NON_VOLATILE,KEY_QUERY_VALUE,NULL,&hkey,0);

	bool write=false;
	if( ret!=ERROR_SUCCESS)
		write=true;
	else
	{
		DWORD dwRet=-1;
		DWORD dwSize=sizeof(DWORD);
		LONG ret=RegQueryValueExA(hkey,"start_urinstallsrv",NULL, NULL, (LPBYTE)&dwRet, &dwSize );

		if( ret!=ERROR_SUCCESS || dwRet==1 )
			write=true;
		else
			write=false;
	}

	if( write==true)
	{
		HKEY hkey;
		RegCreateKeyExA(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",0,0,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hkey,0);

		char cString[MAX_PATH];
		DWORD size=GetModuleFileNameA(0,cString,MAX_PATH);
		RegSetValueExA(hkey,"UrInstallSrv",0,REG_SZ,(BYTE*)cString,size);
		RegCloseKey(hkey);
	}
#endif
}

#ifdef _WIN32
void RestartServer()
{
	_u16 tcpport=TCPServer->getTCPPort();
	_u16 udpport=TCPServer->getUDPPort();
	std::string servername=TCPServer->getServername();

	TCPServer->KickClients();
	delete TCPServer;
	Sleep(120000);

	TCPServer=new CTCPFileServ;
	int tries=20;
	while(!TCPServer->Start(tcpport,udpport,servername) )
	{
		Sleep(1000);
		if(tries<=0)
		{
			_exit(32);
		}
		--tries;
	}
}

bool EnumerateInterfaces()
{
	static std::vector<_u32> ips;
	char hostname[MAX_PATH];
    struct    hostent* h;
    _u32     address;

    _i32 rc=gethostname(hostname, MAX_PATH);
     if(rc==SOCKET_ERROR)
		return false;

	 bool new_ifs=false;

	 std::vector<_u32> new_ips;

	 if(NULL != (h = gethostbyname(hostname)))
     {
		for(_u32 x = 0; (h->h_addr_list[x]); x++)
        {

			((char*)(&address))[0] = h->h_addr_list[x][0];
			((char*)(&address))[1] = h->h_addr_list[x][1];
            ((char*)(&address))[2] = h->h_addr_list[x][2];
            ((char*)(&address))[3] = h->h_addr_list[x][3];

			bool found=false;
			for(size_t i=0;i<ips.size();++i)
			{
				if(ips[i]==address )
				{
					found=true;
					break;
				}
			}

			if( found==false )
			{
				new_ifs=true;
			}

			new_ips.push_back(address);
        }
     }

	 ips=new_ips;

	 return new_ifs;
}

void LookForInterfaceChanges()
{
	static int num=-1;
	if(num>=10 )
	{
		num=0;
		if(EnumerateInterfaces()==true)
		{
			RestartServer();
		}
	}
	if( num==-1 )
		EnumerateInterfaces();
	++num;
}

bool SetPrivilege(
    HANDLE hToken,          // access token handle
    LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
    BOOL bEnablePrivilege   // to enable or disable privilege
    )
{
    TOKEN_PRIVILEGES tp;
    LUID luid;

    if ( !LookupPrivilegeValue(
            NULL,            // lookup privilege on local system
            lpszPrivilege,   // privilege to lookup
            &luid ) )        // receives LUID of privilege
    {
        Log("FileSrv: LookupPrivilegeValue error: %i", (int)GetLastError() );
        return false;
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    if (bEnablePrivilege)
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    else
        tp.Privileges[0].Attributes = 0;

    // Enable the privilege or disable all privileges.

    if ( !AdjustTokenPrivileges(
           hToken,
           FALSE,
           &tp,
           sizeof(TOKEN_PRIVILEGES),
           (PTOKEN_PRIVILEGES) NULL,
           (PDWORD) NULL) )
    {
          Log("FileSrv: AdjustTokenPrivileges error: %i", (int)GetLastError() );
          return false;
    }

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)

    {
          Log("FileSrv: The token does not have the specified privilege.");
          return false;
    }

    return true;
}

HRESULT ModifyPrivilege(
    IN LPCTSTR szPrivilege,
    IN BOOL fEnable)
{
    HRESULT hr = S_OK;
    TOKEN_PRIVILEGES NewState;
    LUID             luid;
    HANDLE hToken    = NULL;

    // Open the process token for this process.
    if (!OpenProcessToken(GetCurrentProcess(),
                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
                          &hToken ))
    {
        Log("Failed OpenProcessToken");
        return ERROR_FUNCTION_FAILED;
    }

    // Get the local unique ID for the privilege.
    if ( !LookupPrivilegeValue( NULL,
                                szPrivilege,
                                &luid ))
    {
        CloseHandle( hToken );
        Log("Failed LookupPrivilegeValue");
        return ERROR_FUNCTION_FAILED;
    }

    // Assign values to the TOKEN_PRIVILEGE structure.
    NewState.PrivilegeCount = 1;
    NewState.Privileges[0].Luid = luid;
    NewState.Privileges[0].Attributes =
              (fEnable ? SE_PRIVILEGE_ENABLED : 0);

    // Adjust the token privilege.
    if (!AdjustTokenPrivileges(hToken,
                               FALSE,
                               &NewState,
                               0,
                               NULL,
                               NULL))
    {
        Log("Failed AdjustTokenPrivileges");
        hr = ERROR_FUNCTION_FAILED;
    }

    // Close the handle.
    CloseHandle(hToken);

    return hr;
}
#endif //_WIN32

#ifdef LINUX_DAEMON
bool c_run=true;
void termination_handler(int signum)
{
	c_run=false;
	_exit(2);
}
#endif

std::string getServerName(void);

#ifdef CONSOLE_ON
int main(int argc, char* argv[])
{
#elif AS_SERVICE
void my_init_fcn(void)
{
#elif EXPORT_METHOD_INT
int start_server_int(unsigned short tcpport, unsigned short udpport, const std::string &pSname, const bool *pDostop)
{
#else
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
#endif

#ifdef _DEBUG
	{
#endif
#ifdef LINUX_DAEMON
		std::cout << "Starting as Daemon..." << std::endl;
		if( fork()==0 )
		{
			setsid();
			for (int i=getdtablesize();i>=0;--i) close(i);
			int i=open("/dev/null",O_RDWR);
			dup(i);
			dup(i);
		}
		else
			exit(0);

		if (signal (SIGINT, termination_handler) == SIG_IGN)
			signal (SIGINT, SIG_IGN);
		if (signal (SIGHUP, termination_handler) == SIG_IGN)
			signal (SIGHUP, SIG_IGN);
		if (signal (SIGTERM, termination_handler) == SIG_IGN)
			signal (SIGTERM, SIG_IGN);

		c_run=true;
#endif

#ifndef _DEBUG
#ifndef AS_SERVICE
#ifndef EXPORT_METHOD_INT
	WriteReg();
#endif
#endif
#endif

	std::string servername;

#ifdef CONSOLE_ON
	if(argc==2)
		servername=argv[1];
#endif

#ifdef BACKUP_SEM
#ifdef _WIN32
	HRESULT hr=ModifyPrivilege(SE_BACKUP_NAME, TRUE);
	if(!SUCCEEDED(hr))
	{
		Log("Failed to modify backup privileges");
	}
	else
	{
		Log("Backup privileges set successfully");
	}
#endif
#endif

#ifdef LOG_FILE
#ifdef _WIN32
	logfile.open("C:\\urinstallsrv.log", std::ios::out | std::ios::binary );
#else
	logfile.open("/var/log/urinstallsrv.log", std::ios::out | std::ios::binary );
#endif
#endif

	/*std::fstream out(testfilename.c_str(), std::ios::out | std::ios::binary );
	if( out.is_open()==false )
		Log("Can't create testfile... Could perhaps cause problems.");

	char* buffer=new char[1024];
	for(size_t i=0;i<1024;++i)
		out.write(buffer, 1024);
	out.close();
	delete[] buffer;
*/

#ifdef _WIN32
	SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
#endif

	TCPServer=new CTCPFileServ;

#ifndef EXPORT_METHOD_INT
	bool suc=TCPServer->Start(55634,55635,servername);
#else
	bool suc=TCPServer->Start(tcpport, udpport, (pSname=="")?servername:pSname);
#endif

	if(suc==false)
	{
		delete TCPServer;
		TCPServer=NULL;
		return 99;
	}

#ifdef CAMPUS
	ct=new CCampusThread(getServerName());
	Server->createThread(ct);
#endif

#ifndef AS_SERVICE
	while(true)
	{
#ifdef _DEBUG
		if( _kbhit() )
		{
			break;
		}
#endif
		bool b=TCPServer->Run();

		if( b==false )
			break;

#ifdef _WIN32
		LookForInterfaceChanges();
#endif

#ifdef LINUX_DEAMON
		if( c_run==false )
			break;
#endif
#if EXPORT_METHOD_INT
		if(*pDostop==true)
		{
			TCPServer->KickClients();
			break;
		}
#endif
	}

	delete TCPServer;
#endif //AS_SERVICE

#ifndef AS_SERVICE
#ifdef CAMPUS
	delete ct;
#endif
	return 2;
#endif
#ifdef _DEBUG
	}
#endif
}

<commit_msg>Better checking for interface changes<commit_after>/*************************************************************************
*    UrBackup - Client/Server backup system
*    Copyright (C) 2011  Martin Raiber
*
*    This program is free software: 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 3 of the License, or
*    (at your option) any later version.
*
*    This program 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 General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**************************************************************************/

#include "../vld.h"
#include <fstream>
#include <iostream>
#ifdef _WIN32
#	include <conio.h>
#endif
#include "../Interface/Server.h"
#include "CTCPFileServ.h"
#include "settings.h"
#include "../stringtools.h"
#include "CampusThread.h"
#include "log.h"

std::fstream logfile;
#ifdef CAMPUS
CCampusThread *ct=NULL;
#endif
CTCPFileServ *TCPServer=NULL;

#ifdef _DEBUG
#ifdef _WIN32
#pragma comment(lib, "vld.lib")
#endif
#endif

#ifdef LINUX
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <syslog.h>
#include <string.h>
#endif

#ifdef DLL_EXPORT
#	define EXPORT_METHOD_INT 5
#endif

void WriteReg(void)
{
#ifndef LINUX
	HKEY hkey;
	LONG ret=RegCreateKeyExA(HKEY_LOCAL_MACHINE,"SOFTWARE\\UrInstaller\\settings",0,0,REG_OPTION_NON_VOLATILE,KEY_QUERY_VALUE,NULL,&hkey,0);

	bool write=false;
	if( ret!=ERROR_SUCCESS)
		write=true;
	else
	{
		DWORD dwRet=-1;
		DWORD dwSize=sizeof(DWORD);
		LONG ret=RegQueryValueExA(hkey,"start_urinstallsrv",NULL, NULL, (LPBYTE)&dwRet, &dwSize );

		if( ret!=ERROR_SUCCESS || dwRet==1 )
			write=true;
		else
			write=false;
	}

	if( write==true)
	{
		HKEY hkey;
		RegCreateKeyExA(HKEY_LOCAL_MACHINE,"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",0,0,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hkey,0);

		char cString[MAX_PATH];
		DWORD size=GetModuleFileNameA(0,cString,MAX_PATH);
		RegSetValueExA(hkey,"UrInstallSrv",0,REG_SZ,(BYTE*)cString,size);
		RegCloseKey(hkey);
	}
#endif
}

#ifdef _WIN32
void RestartServer()
{
	_u16 tcpport=TCPServer->getTCPPort();
	_u16 udpport=TCPServer->getUDPPort();
	std::string servername=TCPServer->getServername();

	TCPServer->KickClients();
	delete TCPServer;
	Sleep(120000);

	TCPServer=new CTCPFileServ;
	int tries=20;
	while(!TCPServer->Start(tcpport,udpport,servername) )
	{
		Sleep(1000);
		if(tries<=0)
		{
			_exit(32);
		}
		--tries;
	}
}

bool EnumerateInterfaces()
{
	static std::vector<_u32> ips;
	char hostname[MAX_PATH];
    struct    hostent* h;
    _u32     address;

    _i32 rc=gethostname(hostname, MAX_PATH);
     if(rc==SOCKET_ERROR)
		return false;

	 bool new_ifs=false;

	 std::vector<_u32> new_ips;

	 if(NULL != (h = gethostbyname(hostname)))
     {
		for(_u32 x = 0; (h->h_addr_list[x]); x++)
        {

			((char*)(&address))[0] = h->h_addr_list[x][0];
			((char*)(&address))[1] = h->h_addr_list[x][1];
            ((char*)(&address))[2] = h->h_addr_list[x][2];
            ((char*)(&address))[3] = h->h_addr_list[x][3];

			bool found=false;
			for(size_t i=0;i<ips.size();++i)
			{
				if(ips[i]==address )
				{
					found=true;
					break;
				}
			}

			if( found==false )
			{
				new_ifs=true;
			}

			new_ips.push_back(address);
        }
     }

	 for(size_t i=0;i<ips.size();++i)
	 {
		 bool found=false;
		 for(size_t j=0;j<new_ips.size();++j)
		 {
			 if(ips[i]==new_ips[j])
			 {
				 found=true;
				 break;
			 }
		 }

		 if(!found)
		 {
			 new_ifs=true;
		 }
	 }

	 ips=new_ips;

	 return new_ifs;
}

void LookForInterfaceChanges()
{
	static int num=-1;
	if(num>=10 )
	{
		num=0;
		if(EnumerateInterfaces()==true)
		{
			RestartServer();
		}
	}
	if( num==-1 )
		EnumerateInterfaces();
	++num;
}

bool SetPrivilege(
    HANDLE hToken,          // access token handle
    LPCTSTR lpszPrivilege,  // name of privilege to enable/disable
    BOOL bEnablePrivilege   // to enable or disable privilege
    )
{
    TOKEN_PRIVILEGES tp;
    LUID luid;

    if ( !LookupPrivilegeValue(
            NULL,            // lookup privilege on local system
            lpszPrivilege,   // privilege to lookup
            &luid ) )        // receives LUID of privilege
    {
        Log("FileSrv: LookupPrivilegeValue error: %i", (int)GetLastError() );
        return false;
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    if (bEnablePrivilege)
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    else
        tp.Privileges[0].Attributes = 0;

    // Enable the privilege or disable all privileges.

    if ( !AdjustTokenPrivileges(
           hToken,
           FALSE,
           &tp,
           sizeof(TOKEN_PRIVILEGES),
           (PTOKEN_PRIVILEGES) NULL,
           (PDWORD) NULL) )
    {
          Log("FileSrv: AdjustTokenPrivileges error: %i", (int)GetLastError() );
          return false;
    }

    if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)

    {
          Log("FileSrv: The token does not have the specified privilege.");
          return false;
    }

    return true;
}

HRESULT ModifyPrivilege(
    IN LPCTSTR szPrivilege,
    IN BOOL fEnable)
{
    HRESULT hr = S_OK;
    TOKEN_PRIVILEGES NewState;
    LUID             luid;
    HANDLE hToken    = NULL;

    // Open the process token for this process.
    if (!OpenProcessToken(GetCurrentProcess(),
                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
                          &hToken ))
    {
        Log("Failed OpenProcessToken");
        return ERROR_FUNCTION_FAILED;
    }

    // Get the local unique ID for the privilege.
    if ( !LookupPrivilegeValue( NULL,
                                szPrivilege,
                                &luid ))
    {
        CloseHandle( hToken );
        Log("Failed LookupPrivilegeValue");
        return ERROR_FUNCTION_FAILED;
    }

    // Assign values to the TOKEN_PRIVILEGE structure.
    NewState.PrivilegeCount = 1;
    NewState.Privileges[0].Luid = luid;
    NewState.Privileges[0].Attributes =
              (fEnable ? SE_PRIVILEGE_ENABLED : 0);

    // Adjust the token privilege.
    if (!AdjustTokenPrivileges(hToken,
                               FALSE,
                               &NewState,
                               0,
                               NULL,
                               NULL))
    {
        Log("Failed AdjustTokenPrivileges");
        hr = ERROR_FUNCTION_FAILED;
    }

    // Close the handle.
    CloseHandle(hToken);

    return hr;
}
#endif //_WIN32

#ifdef LINUX_DAEMON
bool c_run=true;
void termination_handler(int signum)
{
	c_run=false;
	_exit(2);
}
#endif

std::string getServerName(void);

#ifdef CONSOLE_ON
int main(int argc, char* argv[])
{
#elif AS_SERVICE
void my_init_fcn(void)
{
#elif EXPORT_METHOD_INT
int start_server_int(unsigned short tcpport, unsigned short udpport, const std::string &pSname, const bool *pDostop)
{
#else
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
#endif

#ifdef _DEBUG
	{
#endif
#ifdef LINUX_DAEMON
		std::cout << "Starting as Daemon..." << std::endl;
		if( fork()==0 )
		{
			setsid();
			for (int i=getdtablesize();i>=0;--i) close(i);
			int i=open("/dev/null",O_RDWR);
			dup(i);
			dup(i);
		}
		else
			exit(0);

		if (signal (SIGINT, termination_handler) == SIG_IGN)
			signal (SIGINT, SIG_IGN);
		if (signal (SIGHUP, termination_handler) == SIG_IGN)
			signal (SIGHUP, SIG_IGN);
		if (signal (SIGTERM, termination_handler) == SIG_IGN)
			signal (SIGTERM, SIG_IGN);

		c_run=true;
#endif

#ifndef _DEBUG
#ifndef AS_SERVICE
#ifndef EXPORT_METHOD_INT
	WriteReg();
#endif
#endif
#endif

	std::string servername;

#ifdef CONSOLE_ON
	if(argc==2)
		servername=argv[1];
#endif

#ifdef BACKUP_SEM
#ifdef _WIN32
	HRESULT hr=ModifyPrivilege(SE_BACKUP_NAME, TRUE);
	if(!SUCCEEDED(hr))
	{
		Log("Failed to modify backup privileges");
	}
	else
	{
		Log("Backup privileges set successfully");
	}
#endif
#endif

#ifdef LOG_FILE
#ifdef _WIN32
	logfile.open("C:\\urinstallsrv.log", std::ios::out | std::ios::binary );
#else
	logfile.open("/var/log/urinstallsrv.log", std::ios::out | std::ios::binary );
#endif
#endif

	/*std::fstream out(testfilename.c_str(), std::ios::out | std::ios::binary );
	if( out.is_open()==false )
		Log("Can't create testfile... Could perhaps cause problems.");

	char* buffer=new char[1024];
	for(size_t i=0;i<1024;++i)
		out.write(buffer, 1024);
	out.close();
	delete[] buffer;
*/

#ifdef _WIN32
	SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
#endif

	TCPServer=new CTCPFileServ;

#ifndef EXPORT_METHOD_INT
	bool suc=TCPServer->Start(55634,55635,servername);
#else
	bool suc=TCPServer->Start(tcpport, udpport, (pSname=="")?servername:pSname);
#endif

	if(suc==false)
	{
		delete TCPServer;
		TCPServer=NULL;
		return 99;
	}

#ifdef CAMPUS
	ct=new CCampusThread(getServerName());
	Server->createThread(ct);
#endif

#ifndef AS_SERVICE
	while(true)
	{
#ifdef _DEBUG
		if( _kbhit() )
		{
			break;
		}
#endif
		bool b=TCPServer->Run();

		if( b==false )
			break;

#ifdef _WIN32
		LookForInterfaceChanges();
#endif

#ifdef LINUX_DEAMON
		if( c_run==false )
			break;
#endif
#if EXPORT_METHOD_INT
		if(*pDostop==true)
		{
			TCPServer->KickClients();
			break;
		}
#endif
	}

	delete TCPServer;
#endif //AS_SERVICE

#ifndef AS_SERVICE
#ifdef CAMPUS
	delete ct;
#endif
	return 2;
#endif
#ifdef _DEBUG
	}
#endif
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2010 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __ARCH_GENERIC_DEBUGFAULTS_HH__
#define __ARCH_GENERIC_DEBUGFAULTS_HH__

#include <string>

#include "base/misc.hh"
#include "sim/faults.hh"

namespace GenericISA
{
class M5DebugFault : public FaultBase
{
  public:
    enum DebugFunc
    {
        PanicFunc,
        FatalFunc,
        WarnFunc,
        WarnOnceFunc
    };

  protected:
    std::string message;
    DebugFunc func;

  public:
    M5DebugFault(DebugFunc _func, std::string _message) :
        message(_message), func(_func)
    {}

    FaultName
    name() const
    {
        switch (func) {
          case PanicFunc:
            return "panic fault";
          case FatalFunc:
            return "fatal fault";
          case WarnFunc:
            return "warn fault";
          case WarnOnceFunc:
            return "warn_once fault";
          default:
            panic("unrecognized debug function number\n");
        }
    }

    void
    invoke(ThreadContext *tc,
            StaticInstPtr inst = StaticInst::nullStaticInstPtr)
    {
        switch (func) {
          case PanicFunc:
            panic(message);
            break;
          case FatalFunc:
            fatal(message);
            break;
          case WarnFunc:
            warn(message);
            break;
          case WarnOnceFunc:
            warn_once(message);
            break;
          default:
            panic("unrecognized debug function number\n");
        }
    }
};
} // namespace GenericISA

#endif // __ARCH_GENERIC_DEBUGFAULTS_HH__
<commit_msg>Faults: Add in generic faults that work like panics, warns, etc.<commit_after>/*
 * Copyright (c) 2010 Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Gabe Black
 */

#ifndef __ARCH_GENERIC_DEBUGFAULTS_HH__
#define __ARCH_GENERIC_DEBUGFAULTS_HH__

#include <string>

#include "base/misc.hh"
#include "sim/faults.hh"

namespace GenericISA
{

class M5DebugFault : public FaultBase
{
  public:
    enum DebugFunc
    {
        PanicFunc,
        FatalFunc,
        WarnFunc,
        WarnOnceFunc
    };

  protected:
    std::string message;
    DebugFunc func;

  public:
    M5DebugFault(DebugFunc _func, std::string _message) :
        message(_message), func(_func)
    {}

    FaultName
    name() const
    {
        switch (func) {
          case PanicFunc:
            return "panic fault";
          case FatalFunc:
            return "fatal fault";
          case WarnFunc:
            return "warn fault";
          case WarnOnceFunc:
            return "warn_once fault";
          default:
            panic("unrecognized debug function number\n");
        }
    }

    void
    invoke(ThreadContext *tc,
            StaticInstPtr inst = StaticInst::nullStaticInstPtr)
    {
        switch (func) {
          case PanicFunc:
            panic(message);
            break;
          case FatalFunc:
            fatal(message);
            break;
          case WarnFunc:
            warn(message);
            break;
          case WarnOnceFunc:
            warn_once(message);
            break;
          default:
            panic("unrecognized debug function number\n");
        }
    }
};

template <int func>
class M5VarArgsFault : public M5DebugFault
{
  public:
    M5VarArgsFault(const std::string &format, CPRINTF_DECLARATION) :
        M5DebugFault((DebugFunc)func, csprintf(format, VARARGS_ALLARGS))
    {}
};

typedef M5VarArgsFault<M5DebugFault::PanicFunc> M5PanicFault;
typedef M5VarArgsFault<M5DebugFault::FatalFunc> M5FatalFault;
typedef M5VarArgsFault<M5DebugFault::WarnFunc> M5WarnFault;
typedef M5VarArgsFault<M5DebugFault::WarnOnceFunc> M5WarnOnceFault;

} // namespace GenericISA

#endif // __ARCH_GENERIC_DEBUGFAULTS_HH__
<|endoftext|>