<commit_before>/*********************************************************************
 *
 * Copyright (C) 2008,  Simon Kagstrom
 *
 * Filename:      basicblock.cc
 * Author:        Simon Kagstrom <simon.kagstrom@gmail.com>
 * Description:   Basic block implementation
 *
 * $Id:$
 *
 ********************************************************************/
#include <controller.hh>
#include <basicblock.hh>
#include <emit.hh>
#include <config.hh>

BasicBlock::BasicBlock(Instruction **insns,
		       bb_type_t type,
		       int first, int last) : CodeBlock()
{
  this->instructions = &(insns[first]);
  this->n_insns = last - first;
  this->type = type;

  this->address = this->instructions[0]->getAddress();
  this->size = this->n_insns * 4;
}

bool BasicBlock::pass1()
{
  bool out = true;

  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];

      controller->setCurrentInstruction(insn);

      if (insn->getOpcode() == OP_J)
        {
          uint32_t dstAddress = insn->getExtra() << 2;
          JavaMethod *src = controller->getMethodByAddress(insn->getAddress());
          JavaMethod *dst = controller->getMethodByAddress(dstAddress);

          if (src != dst)
            {
              /* Typically tail call optimizations, just "unoptimize" */
              emit->warning("Jump from 0x%x to 0x%x not within the same method, replacing with jal\n",
                            this->address, dstAddress);
              this->instructions[i] = InstructionFactory::getInstance()->createTailCallJump(insn->getAddress(),
                                                                                insn->getExtra());
              if (insn->isBranchTarget())
                this->instructions[i]->setBranchTarget();
              this->instructions[i]->setDelayed(insn->getDelayed());
              delete insn;
              insn = this->instructions[i];
            }
        }

      if ( (this->type == PROLOGUE && insn->getOpcode() == OP_SW && insn->getRs() == R_SP) ||
	   (this->type == EPILOGUE && insn->getOpcode() == OP_LW && insn->getRs() == R_SP) )
	{
	  int p_s[N_REGS];
	  int p_d[N_REGS];

	  memset(p_s, 0, sizeof(p_s));
	  memset(p_d, 0, sizeof(p_d));
	  insn->fillSources(p_s);
	  insn->fillDestinations(p_d);

	  /* Loop through all caller saved registers and for writes, simply skip them */
	  for (int j = 0;
	       mips_caller_saved[j] != R_ZERO;
	       j++)
	    {
	      MIPS_register_t reg = mips_caller_saved[j];

	      if ( (this->type == PROLOGUE && p_s[reg] != 0) ||
                   (this->type == EPILOGUE && p_d[reg] != 0) )
		{
		  this->instructions[i] = InstructionFactory::getInstance()->createNop(insn->getAddress());
                  if (insn->isBranchTarget())
                    this->instructions[i]->setBranchTarget();
		  delete insn;
                  insn = this->instructions[i];
		  break;
		}
	    }
	}

      /* Prepare the instruction */
      if (!insn->pass1())
	out = false;
    }

  return out;
}

static void pushRegister(MIPS_register_t reg)
{
  if (reg != R_RA)
    emit->bc_pushregister(reg);
  else
    emit->bc_pushconst(0);
}

void BasicBlock::traceRegisterValues(Instruction *insn)
{
  MIPS_register_t rs,rt,rd;

  rs = insn->getRs();
  rt = insn->getRt();
  rd = insn->getRd();

  /* Push all registers, then invoke the tracer */
  pushRegister(rs);
  pushRegister(rt);
  pushRegister(rd);

  emit->bc_invokestatic("CRunTime/emitRegisterTrace(III)V");
  if (insn->getDelayed())
    this->traceRegisterValues(insn->getDelayed());
}

void BasicBlock::commentInstruction(Instruction *insn)
{
  char buf[255];
  char out[255];

  memset(buf, 0, 255);
  memset(out, 0, 255);

  /* Output a comment */
  int l = snprintf(buf, 255, "0x%x: ", insn->getAddress());
  l += instruction_to_string(insn, buf+l, 255);
  if (insn->hasDelaySlot())
    {
      buf[l] = ' ';
      instruction_to_string(insn->getDelayed(), buf+l+1, 255-l-1);
    }

  snprintf(out, 255, "0x%08x: %s", insn->getAddress(), buf);
  emit->bc_comment(out);

  if ( insn->getAddress() >= config->traceRange[0] && insn->getAddress() < config->traceRange[1])
    {
      emit->bc_ldc(buf);
      emit->bc_invokestatic("CRunTime/emitTrace(Ljava/lang/String;)V");
      this->traceRegisterValues(insn);
    }
}

bool BasicBlock::pass2()
{
  bool out = true;

  emit->bc_comment("--- basic block ---");
  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];

      controller->setCurrentInstruction(insn);

      /* FIXME: Emit .line info if debug is on */
      if ( (insn->isBranchTarget() || controller->hasJumptabLabel(insn->getAddress())) &&
           !insn->isDelaySlotNop() )
	emit->bc_label( "L_%x", insn->getAddress() );

      if (!insn->isNop())
	this->commentInstruction(insn);

      /* Compile the instruction */
      if (!insn->pass2())
	out = false;

      if ( insn->hasDelaySlot() && controller->hasJumptabLabel(insn->getDelayed()->getAddress()) )
        {
          uint32_t addr = insn->getDelayed()->getAddress();

          emit->warning("Instruction on address 0x%x is in delay slot but has a label\n",
                        addr);
          /* Jump past the instruction and emit it again */
          emit->bc_goto("L_%x_out", addr);

          /* Emit the instruction again */
          emit->bc_label("L_%x", addr);
          insn->getDelayed()->pass2();
          emit->bc_label("L_%x_out", addr);
        }
    }

  return out;
}

int BasicBlock::fillDestinations(int *p)
{
  int out = 0;

  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];
      Instruction *delayed = insn->getDelayed();
      Instruction *prefix = insn->getPrefix();

      out += insn->fillDestinations(p);
      if (delayed)
        out += delayed->fillDestinations(p);
      if (prefix)
        out += prefix->fillDestinations(p);
    }

  return out;
}

int BasicBlock::fillSources(int *p)
{
  int out = 0;

  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];
      Instruction *delayed = insn->getDelayed();
      Instruction *prefix = insn->getPrefix();

      out += insn->fillSources(p);
      if (delayed)
        out += delayed->fillSources(p);
      if (prefix)
        out += prefix->fillSources(p);
    }

  return out;
}
<commit_msg>Use xsnprintf - checks return values<commit_after>/*********************************************************************
 *
 * Copyright (C) 2008,  Simon Kagstrom
 *
 * Filename:      basicblock.cc
 * Author:        Simon Kagstrom <simon.kagstrom@gmail.com>
 * Description:   Basic block implementation
 *
 * $Id:$
 *
 ********************************************************************/
#include <controller.hh>
#include <basicblock.hh>
#include <emit.hh>
#include <config.hh>

BasicBlock::BasicBlock(Instruction **insns,
		       bb_type_t type,
		       int first, int last) : CodeBlock()
{
  this->instructions = &(insns[first]);
  this->n_insns = last - first;
  this->type = type;

  this->address = this->instructions[0]->getAddress();
  this->size = this->n_insns * 4;
}

bool BasicBlock::pass1()
{
  bool out = true;

  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];

      controller->setCurrentInstruction(insn);

      if (insn->getOpcode() == OP_J)
        {
          uint32_t dstAddress = insn->getExtra() << 2;
          JavaMethod *src = controller->getMethodByAddress(insn->getAddress());
          JavaMethod *dst = controller->getMethodByAddress(dstAddress);

          if (src != dst)
            {
              /* Typically tail call optimizations, just "unoptimize" */
              emit->warning("Jump from 0x%x to 0x%x not within the same method, replacing with jal\n",
                            this->address, dstAddress);
              this->instructions[i] = InstructionFactory::getInstance()->createTailCallJump(insn->getAddress(),
                                                                                insn->getExtra());
              if (insn->isBranchTarget())
                this->instructions[i]->setBranchTarget();
              this->instructions[i]->setDelayed(insn->getDelayed());
              delete insn;
              insn = this->instructions[i];
            }
        }

      if ( (this->type == PROLOGUE && insn->getOpcode() == OP_SW && insn->getRs() == R_SP) ||
	   (this->type == EPILOGUE && insn->getOpcode() == OP_LW && insn->getRs() == R_SP) )
	{
	  int p_s[N_REGS];
	  int p_d[N_REGS];

	  memset(p_s, 0, sizeof(p_s));
	  memset(p_d, 0, sizeof(p_d));
	  insn->fillSources(p_s);
	  insn->fillDestinations(p_d);

	  /* Loop through all caller saved registers and for writes, simply skip them */
	  for (int j = 0;
	       mips_caller_saved[j] != R_ZERO;
	       j++)
	    {
	      MIPS_register_t reg = mips_caller_saved[j];

	      if ( (this->type == PROLOGUE && p_s[reg] != 0) ||
                   (this->type == EPILOGUE && p_d[reg] != 0) )
		{
		  this->instructions[i] = InstructionFactory::getInstance()->createNop(insn->getAddress());
                  if (insn->isBranchTarget())
                    this->instructions[i]->setBranchTarget();
		  delete insn;
                  insn = this->instructions[i];
		  break;
		}
	    }
	}

      /* Prepare the instruction */
      if (!insn->pass1())
	out = false;
    }

  return out;
}

static void pushRegister(MIPS_register_t reg)
{
  if (reg != R_RA)
    emit->bc_pushregister(reg);
  else
    emit->bc_pushconst(0);
}

void BasicBlock::traceRegisterValues(Instruction *insn)
{
  MIPS_register_t rs,rt,rd;

  rs = insn->getRs();
  rt = insn->getRt();
  rd = insn->getRd();

  /* Push all registers, then invoke the tracer */
  pushRegister(rs);
  pushRegister(rt);
  pushRegister(rd);

  emit->bc_invokestatic("CRunTime/emitRegisterTrace(III)V");
  if (insn->getDelayed())
    this->traceRegisterValues(insn->getDelayed());
}

void BasicBlock::commentInstruction(Instruction *insn)
{
  char buf[255];
  char out[255];

  memset(buf, 0, 255);
  memset(out, 0, 255);

  /* Output a comment */
  int l = snprintf(buf, 255, "0x%x: ", insn->getAddress());
  l += instruction_to_string(insn, buf+l, 255);
  if (insn->hasDelaySlot())
    {
      buf[l] = ' ';
      instruction_to_string(insn->getDelayed(), buf+l+1, 255-l-1);
    }

  xsnprintf(out, 255, "0x%08x: %s", insn->getAddress(), buf);
  emit->bc_comment(out);

  if ( insn->getAddress() >= config->traceRange[0] && insn->getAddress() < config->traceRange[1])
    {
      emit->bc_ldc(buf);
      emit->bc_invokestatic("CRunTime/emitTrace(Ljava/lang/String;)V");
      this->traceRegisterValues(insn);
    }
}

bool BasicBlock::pass2()
{
  bool out = true;

  emit->bc_comment("--- basic block ---");
  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];

      controller->setCurrentInstruction(insn);

      /* FIXME: Emit .line info if debug is on */
      if ( (insn->isBranchTarget() || controller->hasJumptabLabel(insn->getAddress())) &&
           !insn->isDelaySlotNop() )
	emit->bc_label( "L_%x", insn->getAddress() );

      if (!insn->isNop())
	this->commentInstruction(insn);

      /* Compile the instruction */
      if (!insn->pass2())
	out = false;

      if ( insn->hasDelaySlot() && controller->hasJumptabLabel(insn->getDelayed()->getAddress()) )
        {
          uint32_t addr = insn->getDelayed()->getAddress();

          emit->warning("Instruction on address 0x%x is in delay slot but has a label\n",
                        addr);
          /* Jump past the instruction and emit it again */
          emit->bc_goto("L_%x_out", addr);

          /* Emit the instruction again */
          emit->bc_label("L_%x", addr);
          insn->getDelayed()->pass2();
          emit->bc_label("L_%x_out", addr);
        }
    }

  return out;
}

int BasicBlock::fillDestinations(int *p)
{
  int out = 0;

  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];
      Instruction *delayed = insn->getDelayed();
      Instruction *prefix = insn->getPrefix();

      out += insn->fillDestinations(p);
      if (delayed)
        out += delayed->fillDestinations(p);
      if (prefix)
        out += prefix->fillDestinations(p);
    }

  return out;
}

int BasicBlock::fillSources(int *p)
{
  int out = 0;

  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];
      Instruction *delayed = insn->getDelayed();
      Instruction *prefix = insn->getPrefix();

      out += insn->fillSources(p);
      if (delayed)
        out += delayed->fillSources(p);
      if (prefix)
        out += prefix->fillSources(p);
    }

  return out;
}
<|endoftext|>


<commit_before>/*********************************************************************
 *
 * Copyright (C) 2008,  Simon Kagstrom
 *
 * Filename:      basicblock.cc
 * Author:        Simon Kagstrom <simon.kagstrom@gmail.com>
 * Description:   Basic block implementation
 *
 * $Id:$
 *
 ********************************************************************/
#include <controller.hh>
#include <basicblock.hh>
#include <emit.hh>
#include <config.hh>

BasicBlock::BasicBlock(Instruction **insns,
		       bb_type_t type,
		       int first, int last) : CodeBlock()
{
  panic_if(first < 0 || last < 0 || first > last,
           "Basic block constructed with wrong instructions %d to %d\n", first, last);

  this->instructions = &(insns[first]);
  this->n_insns = last - first;
  this->type = type;

  this->address = this->instructions[0]->getAddress();
  this->size = this->n_insns * 4;

  /* Fixup the bytecode size and fill in last register writes and
   * last register reads for the instruction */
  this->bc_size = 0;
  this->maxStackHeight = 0; /* Fixed in pass 1 */
  for (int i = 0; i < n_insns; i++)
    {
      Instruction *insn = this->instructions[i];

      /* Order is important. The parameters for the instruction with a delay
       * slot is pushed before the delay slot */
      if (insn->hasPrefix())
        this->bc_size += insn->getPrefix()->getBytecodeSize();
      this->bc_size += insn->getBytecodeSize();
      if (insn->hasDelayed())
        this->bc_size += insn->getDelayed()->getBytecodeSize();
    }
}

void BasicBlock::handleTables(Instruction **rtab, Instruction **wtab,
    Instruction *insn)
{
  /* First update the instruction and then the tables */
  this->fillInstructionReadsAndWrites(rtab, wtab, insn);
  this->fillReadTable(rtab, insn);
  this->fillWriteTable(wtab, insn);
}

void BasicBlock::fillInstructionReadsAndWrites(Instruction **rtab,
    Instruction **wtab, Instruction *insn)
{
  int uses[N_REGS];

  memset(uses, 0, sizeof(uses));
  insn->fillDestinations(uses);
  insn->fillSources(uses);

  if (uses[insn->getRs()])
      insn->setPrevRegisterReadAndWrite(rtab[insn->getRs()],
          wtab[insn->getRs()], I_RS);
  if (uses[insn->getRt()])
    insn->setPrevRegisterReadAndWrite(rtab[insn->getRt()],
        wtab[insn->getRt()], I_RT);
  if (uses[insn->getRd()])
    insn->setPrevRegisterReadAndWrite(rtab[insn->getRd()],
        wtab[insn->getRd()], I_RD);
}

void BasicBlock::fillWriteTable(Instruction **table, Instruction *insn)
{
  int dsts[N_REGS];

  memset(dsts, 0, sizeof(dsts));
  insn->fillDestinations(dsts);

  /* rs is rarely used as a destination, but we want to be sure! */
  if (dsts[insn->getRs()])
    table[insn->getRs()] = insn;
  if (dsts[insn->getRt()])
    table[insn->getRt()] = insn;
  if (dsts[insn->getRd()])
    table[insn->getRd()] = insn;
}

void BasicBlock::fillReadTable(Instruction **table, Instruction *insn)
{
  int srcs[N_REGS];

  memset(srcs, 0, sizeof(srcs));
  insn->fillDestinations(srcs);

  if (srcs[insn->getRs()])
    table[insn->getRs()] = insn;
  if (srcs[insn->getRt()])
    table[insn->getRt()] = insn;
  if (srcs[insn->getRd()])
    table[insn->getRd()] = insn;
}

bool BasicBlock::pass1()
{
  bool out = true;
  Instruction **write_table = (Instruction**)xcalloc(N_REGS,
      sizeof(Instruction*));
  Instruction **read_table = (Instruction**)xcalloc(N_REGS,
      sizeof(Instruction*));

  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];

      controller->setCurrentInstruction(insn);

      if (insn->getOpcode() == OP_J)
        {
          uint32_t dstAddress = insn->getExtra() << 2;
          JavaMethod *src = controller->getMethodByAddress(insn->getAddress());
          JavaMethod *dst = controller->getMethodByAddress(dstAddress);

          if (src != dst)
            {
              /* Typically tail call optimizations, just "unoptimize" */
              emit->warning("Jump from 0x%x to 0x%x not within the same method, replacing with jal\n",
                            this->address, dstAddress);
              this->instructions[i] = InstructionFactory::getInstance()->createTailCallJump(insn->getAddress(),
                                                                                insn->getExtra());
              if (insn->isBranchTarget())
                this->instructions[i]->setBranchTarget();
              this->instructions[i]->setDelayed(insn->getDelayed());
              delete insn;
              insn = this->instructions[i];
            }
        }

      /* Prepare the instruction */
      if (!insn->pass1())
	out = false;

      /* Order is important. The parameters for the instruction with a delay
       * slot is pushed before the delay slot */
      if (insn->hasPrefix())
        this->handleTables(read_table, write_table, insn->getPrefix());
      this->handleTables(read_table, write_table, insn);
      if (insn->hasDelayed())
        this->handleTables(read_table, write_table, insn->getDelayed());
    }

  free(write_table);
  free(read_table);

  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];

      if (config->optimizePruneStackStores &&
          ((this->type == PROLOGUE && insn->getOpcode() == OP_SW && insn->getRs() == R_SP) ||
              (this->type == EPILOGUE && insn->getOpcode() == OP_LW && insn->getRs() == R_SP)) )
        {
          int p_s[N_REGS];
          int p_d[N_REGS];

          memset(p_s, 0, sizeof(p_s));
          memset(p_d, 0, sizeof(p_d));
          insn->fillSources(p_s);
          insn->fillDestinations(p_d);

          /* Loop through all caller saved registers and for writes, simply skip them */
          for (int j = 0; mips_caller_saved[j] != R_ZERO; j++)
            {
              MIPS_register_t reg = mips_caller_saved[j];

              if ( (this->type == PROLOGUE && p_s[reg] != 0 && !insn->getPrevRegisterWrite(I_RT)) ||
                  (this->type == EPILOGUE && p_d[reg] != 0 && !insn->getPrevRegisterWrite(I_RT)))
                {
                  this->instructions[i] = InstructionFactory::getInstance()->createNop(insn->getAddress());
                  if (insn->isBranchTarget())
                    this->instructions[i]->setBranchTarget();
                  delete insn;
                  insn = this->instructions[i];
                  break;
                }
            }
        }
      this->maxStackHeight = max(this->maxStackHeight, insn->getMaxStackHeight());
      if (insn->getDelayed())
        this->maxStackHeight = max(this->maxStackHeight,
            insn->getDelayed()->getMaxStackHeight());
    }

  return out;
}

static void pushRegister(MIPS_register_t reg)
{
  if (reg != R_RA)
    emit->bc_pushregister(reg);
  else
    emit->bc_pushconst(0);
}

void BasicBlock::traceRegisterValues(Instruction *insn)
{
  MIPS_register_t rs,rt,rd;

  rs = insn->getRs();
  rt = insn->getRt();
  rd = insn->getRd();

  /* Push all registers, then invoke the tracer */
  pushRegister(rs);
  pushRegister(rt);
  pushRegister(rd);

  emit->bc_invokestatic("%sCRunTime/emitRegisterTrace(III)V",
      controller->getJasminPackagePath());
  if (insn->getDelayed())
    this->traceRegisterValues(insn->getDelayed());
}

Instruction *BasicBlock::lookupPrevRegister(Instruction *insn, MIPS_register_t reg,
    bool is_write)
{
  mips_register_type_t which;

  if (reg == insn->getRs())
    which = I_RS;
  else if (reg == insn->getRt())
    which = I_RT;
  else if (reg == insn->getRd())
    which = I_RD;
  else /* Does not access the register! */
    return NULL;

  if (is_write)
    return insn->getPrevRegisterWrite(which);
  return insn->getPrevRegisterRead(which);
}

void BasicBlock::commentInstruction(Instruction *insn)
{
  char buf[255];
  char out[255];

  memset(buf, 0, 255);
  memset(out, 0, 255);

  /* Output a comment */
  int l = snprintf(buf, 255, "0x%x: ", insn->getAddress());
  l += instruction_to_string(insn, buf+l, 255);
  if (insn->hasDelaySlot())
    {
      buf[l] = ' ';
      instruction_to_string(insn->getDelayed(), buf+l+1, 255-l-1);
    }

  xsnprintf(out, 255, "0x%08x: %s", insn->getAddress(), buf);
  emit->bc_comment(out);

  if ( insn->getAddress() >= config->traceRange[0] && insn->getAddress() < config->traceRange[1])
    {
      emit->bc_ldc(buf);
      emit->bc_invokestatic("%sCRunTime/emitTrace(Ljava/lang/String;)V",
          controller->getJasminPackagePath());
      this->traceRegisterValues(insn);
    }
}

bool BasicBlock::pass2()
{
  bool out = true;

  emit->bc_comment("--- basic block ---");
  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];

      controller->setCurrentInstruction(insn);

      /* FIXME: Emit .line info if debug is on */
      if ( (insn->isBranchTarget() || controller->hasJumptabLabel(insn->getAddress())) &&
           !insn->isDelaySlotNop() )
	emit->bc_label( insn->getAddress() );

      if (!insn->isNop())
	this->commentInstruction(insn);

      /* Compile the instruction */
      if (!insn->pass2())
	out = false;

      if ( insn->hasDelaySlot() && controller->hasJumptabLabel(insn->getDelayed()->getAddress()) )
        {
          uint32_t addr = insn->getDelayed()->getAddress();

          emit->warning("Instruction on address 0x%x is in delay slot but has a label\n",
                        addr);
          /* Jump past the instruction and emit it again */
          emit->bc_goto("L_%x_out", addr);

          /* Emit the instruction again */
          emit->bc_label("L_%x", addr);
          insn->getDelayed()->pass2();
          emit->bc_label("L_%x_out", addr);
        }
    }

  return out;
}

int BasicBlock::fillDestinations(int *p)
{
  int out = 0;

  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];
      Instruction *delayed = insn->getDelayed();
      Instruction *prefix = insn->getPrefix();

      out += insn->fillDestinations(p);
      if (delayed)
        out += delayed->fillDestinations(p);
      if (prefix)
        out += prefix->fillDestinations(p);
    }

  return out;
}

int BasicBlock::fillSources(int *p)
{
  int out = 0;

  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];
      Instruction *delayed = insn->getDelayed();
      Instruction *prefix = insn->getPrefix();

      out += insn->fillSources(p);
      if (delayed)
        out += delayed->fillSources(p);
      if (prefix)
        out += prefix->fillSources(p);
    }

  return out;
}
<commit_msg>Correct filling of read tables and the instruction read and writes.<commit_after>/*********************************************************************
 *
 * Copyright (C) 2008,  Simon Kagstrom
 *
 * Filename:      basicblock.cc
 * Author:        Simon Kagstrom <simon.kagstrom@gmail.com>
 * Description:   Basic block implementation
 *
 * $Id:$
 *
 ********************************************************************/
#include <controller.hh>
#include <basicblock.hh>
#include <emit.hh>
#include <config.hh>

BasicBlock::BasicBlock(Instruction **insns,
		       bb_type_t type,
		       int first, int last) : CodeBlock()
{
  panic_if(first < 0 || last < 0 || first > last,
           "Basic block constructed with wrong instructions %d to %d\n", first, last);

  this->instructions = &(insns[first]);
  this->n_insns = last - first;
  this->type = type;

  this->address = this->instructions[0]->getAddress();
  this->size = this->n_insns * 4;

  /* Fixup the bytecode size and fill in last register writes and
   * last register reads for the instruction */
  this->bc_size = 0;
  this->maxStackHeight = 0; /* Fixed in pass 1 */
  for (int i = 0; i < n_insns; i++)
    {
      Instruction *insn = this->instructions[i];

      /* Order is important. The parameters for the instruction with a delay
       * slot is pushed before the delay slot */
      if (insn->hasPrefix())
        this->bc_size += insn->getPrefix()->getBytecodeSize();
      this->bc_size += insn->getBytecodeSize();
      if (insn->hasDelayed())
        this->bc_size += insn->getDelayed()->getBytecodeSize();
    }
}

void BasicBlock::handleTables(Instruction **rtab, Instruction **wtab,
    Instruction *insn)
{
  /* First update the instruction and then the tables */
  this->fillReadTable(rtab, insn);
  this->fillWriteTable(wtab, insn);
  this->fillInstructionReadsAndWrites(rtab, wtab, insn);
}

void BasicBlock::fillInstructionReadsAndWrites(Instruction **rtab,
    Instruction **wtab, Instruction *insn)
{
  int uses[N_REGS];

  memset(uses, 0, sizeof(uses));
  insn->fillDestinations(uses);
  insn->fillSources(uses);

  if (uses[insn->getRs()])
      insn->setPrevRegisterReadAndWrite(rtab[insn->getRs()],
          wtab[insn->getRs()], I_RS);
  if (uses[insn->getRt()])
    insn->setPrevRegisterReadAndWrite(rtab[insn->getRt()],
        wtab[insn->getRt()], I_RT);
  if (uses[insn->getRd()])
    insn->setPrevRegisterReadAndWrite(rtab[insn->getRd()],
        wtab[insn->getRd()], I_RD);
}

void BasicBlock::fillWriteTable(Instruction **table, Instruction *insn)
{
  int dsts[N_REGS];

  memset(dsts, 0, sizeof(dsts));
  insn->fillDestinations(dsts);

  /* rs is rarely used as a destination, but we want to be sure! */
  if (dsts[insn->getRs()])
    table[insn->getRs()] = insn;
  if (dsts[insn->getRt()])
    table[insn->getRt()] = insn;
  if (dsts[insn->getRd()])
    table[insn->getRd()] = insn;
}

void BasicBlock::fillReadTable(Instruction **table, Instruction *insn)
{
  int srcs[N_REGS];

  memset(srcs, 0, sizeof(srcs));
  insn->fillSources(srcs);

  if (srcs[insn->getRs()])
    table[insn->getRs()] = insn;
  if (srcs[insn->getRt()])
    table[insn->getRt()] = insn;
  if (srcs[insn->getRd()])
    table[insn->getRd()] = insn;
}

bool BasicBlock::pass1()
{
  bool out = true;
  Instruction **write_table = (Instruction**)xcalloc(N_REGS,
      sizeof(Instruction*));
  Instruction **read_table = (Instruction**)xcalloc(N_REGS,
      sizeof(Instruction*));

  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];

      controller->setCurrentInstruction(insn);

      if (insn->getOpcode() == OP_J)
        {
          uint32_t dstAddress = insn->getExtra() << 2;
          JavaMethod *src = controller->getMethodByAddress(insn->getAddress());
          JavaMethod *dst = controller->getMethodByAddress(dstAddress);

          if (src != dst)
            {
              /* Typically tail call optimizations, just "unoptimize" */
              emit->warning("Jump from 0x%x to 0x%x not within the same method, replacing with jal\n",
                            this->address, dstAddress);
              this->instructions[i] = InstructionFactory::getInstance()->createTailCallJump(insn->getAddress(),
                                                                                insn->getExtra());
              if (insn->isBranchTarget())
                this->instructions[i]->setBranchTarget();
              this->instructions[i]->setDelayed(insn->getDelayed());
              delete insn;
              insn = this->instructions[i];
            }
        }

      /* Prepare the instruction */
      if (!insn->pass1())
	out = false;

      /* Order is important. The parameters for the instruction with a delay
       * slot is pushed before the delay slot */
      if (insn->hasPrefix())
        this->handleTables(read_table, write_table, insn->getPrefix());
      this->handleTables(read_table, write_table, insn);
      if (insn->hasDelayed())
        this->handleTables(read_table, write_table, insn->getDelayed());
    }

  free(write_table);
  free(read_table);

  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];

      if (config->optimizePruneStackStores &&
          ((this->type == PROLOGUE && insn->getOpcode() == OP_SW && insn->getRs() == R_SP) ||
              (this->type == EPILOGUE && insn->getOpcode() == OP_LW && insn->getRs() == R_SP)) )
        {
          int p_s[N_REGS];
          int p_d[N_REGS];

          memset(p_s, 0, sizeof(p_s));
          memset(p_d, 0, sizeof(p_d));
          insn->fillSources(p_s);
          insn->fillDestinations(p_d);

          /* Loop through all caller saved registers and for writes, simply skip them */
          for (int j = 0; mips_caller_saved[j] != R_ZERO; j++)
            {
              MIPS_register_t reg = mips_caller_saved[j];

              if ( (this->type == PROLOGUE && p_s[reg] != 0 && !insn->getPrevRegisterWrite(I_RT)) ||
                  (this->type == EPILOGUE && p_d[reg] != 0 && !insn->getPrevRegisterWrite(I_RT)))
                {
                  this->instructions[i] = InstructionFactory::getInstance()->createNop(insn->getAddress());
                  if (insn->isBranchTarget())
                    this->instructions[i]->setBranchTarget();
                  delete insn;
                  insn = this->instructions[i];
                  break;
                }
            }
        }
      this->maxStackHeight = max(this->maxStackHeight, insn->getMaxStackHeight());
      if (insn->getDelayed())
        this->maxStackHeight = max(this->maxStackHeight,
            insn->getDelayed()->getMaxStackHeight());
    }

  return out;
}

static void pushRegister(MIPS_register_t reg)
{
  if (reg != R_RA)
    emit->bc_pushregister(reg);
  else
    emit->bc_pushconst(0);
}

void BasicBlock::traceRegisterValues(Instruction *insn)
{
  MIPS_register_t rs,rt,rd;

  rs = insn->getRs();
  rt = insn->getRt();
  rd = insn->getRd();

  /* Push all registers, then invoke the tracer */
  pushRegister(rs);
  pushRegister(rt);
  pushRegister(rd);

  emit->bc_invokestatic("%sCRunTime/emitRegisterTrace(III)V",
      controller->getJasminPackagePath());
  if (insn->getDelayed())
    this->traceRegisterValues(insn->getDelayed());
}

Instruction *BasicBlock::lookupPrevRegister(Instruction *insn, MIPS_register_t reg,
    bool is_write)
{
  mips_register_type_t which;

  if (reg == insn->getRs())
    which = I_RS;
  else if (reg == insn->getRt())
    which = I_RT;
  else if (reg == insn->getRd())
    which = I_RD;
  else /* Does not access the register! */
    return NULL;

  if (is_write)
    return insn->getPrevRegisterWrite(which);
  return insn->getPrevRegisterRead(which);
}

void BasicBlock::commentInstruction(Instruction *insn)
{
  char buf[255];
  char out[255];

  memset(buf, 0, 255);
  memset(out, 0, 255);

  /* Output a comment */
  int l = snprintf(buf, 255, "0x%x: ", insn->getAddress());
  l += instruction_to_string(insn, buf+l, 255);
  if (insn->hasDelaySlot())
    {
      buf[l] = ' ';
      instruction_to_string(insn->getDelayed(), buf+l+1, 255-l-1);
    }

  xsnprintf(out, 255, "0x%08x: %s", insn->getAddress(), buf);
  emit->bc_comment(out);

  if ( insn->getAddress() >= config->traceRange[0] && insn->getAddress() < config->traceRange[1])
    {
      emit->bc_ldc(buf);
      emit->bc_invokestatic("%sCRunTime/emitTrace(Ljava/lang/String;)V",
          controller->getJasminPackagePath());
      this->traceRegisterValues(insn);
    }
}

bool BasicBlock::pass2()
{
  bool out = true;

  emit->bc_comment("--- basic block ---");
  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];

      controller->setCurrentInstruction(insn);

      /* FIXME: Emit .line info if debug is on */
      if ( (insn->isBranchTarget() || controller->hasJumptabLabel(insn->getAddress())) &&
           !insn->isDelaySlotNop() )
	emit->bc_label( insn->getAddress() );

      if (!insn->isNop())
	this->commentInstruction(insn);

      /* Compile the instruction */
      if (!insn->pass2())
	out = false;

      if ( insn->hasDelaySlot() && controller->hasJumptabLabel(insn->getDelayed()->getAddress()) )
        {
          uint32_t addr = insn->getDelayed()->getAddress();

          emit->warning("Instruction on address 0x%x is in delay slot but has a label\n",
                        addr);
          /* Jump past the instruction and emit it again */
          emit->bc_goto("L_%x_out", addr);

          /* Emit the instruction again */
          emit->bc_label("L_%x", addr);
          insn->getDelayed()->pass2();
          emit->bc_label("L_%x_out", addr);
        }
    }

  return out;
}

int BasicBlock::fillDestinations(int *p)
{
  int out = 0;

  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];
      Instruction *delayed = insn->getDelayed();
      Instruction *prefix = insn->getPrefix();

      out += insn->fillDestinations(p);
      if (delayed)
        out += delayed->fillDestinations(p);
      if (prefix)
        out += prefix->fillDestinations(p);
    }

  return out;
}

int BasicBlock::fillSources(int *p)
{
  int out = 0;

  for (int i = 0; i < this->n_insns; i++)
    {
      Instruction *insn = this->instructions[i];
      Instruction *delayed = insn->getDelayed();
      Instruction *prefix = insn->getPrefix();

      out += insn->fillSources(p);
      if (delayed)
        out += delayed->fillSources(p);
      if (prefix)
        out += prefix->fillSources(p);
    }

  return out;
}
<|endoftext|>


<commit_before>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXDE-Qt - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2012 Razor team
 * Authors:
 *   Christian Surlykke <christian@surlykke.dk>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */
#include <QComboBox>
#include <QDebug>

#include "idlenesswatchersettings.h"
#include "ui_idlenesswatchersettings.h"
#include "helpers.h"

IdlenessWatcherSettings::IdlenessWatcherSettings(QWidget *parent) :
    QWidget(parent),
    mSettings(),
    mUi(new Ui::IdlenessWatcherSettings)
{
    mUi->setupUi(this);
    fillComboBox(mUi->idleActionComboBox);
    connect(mUi->idlenessWatcherGroupBox, SIGNAL(clicked()), SLOT(saveSettings()));
    connect(mUi->idleActionComboBox, SIGNAL(activated(int)), SLOT(saveSettings()));
    connect(mUi->idleTimeMinutesSpinBox, SIGNAL(editingFinished()), SLOT(saveSettings()));
    connect(mUi->idleTimeMinutesSpinBox, SIGNAL(valueChanged(int)), SLOT(minutesChanged(int)));
    connect(mUi->idleTimeSecondsSpinBox, SIGNAL(valueChanged(int)), SLOT(secondsChanged(int)));

    connect(mUi->idleTimeSecondsSpinBox, SIGNAL(editingFinished()), SLOT(saveSettings()));
}

IdlenessWatcherSettings::~IdlenessWatcherSettings()
{
    delete mUi;
}

void IdlenessWatcherSettings::loadSettings()
{
    qDebug() << "IdlenessWatcherSettings:loadSettings";

    mUi->idlenessWatcherGroupBox->setChecked(mSettings.isIdlenessWatcherEnabled());
    setComboBoxToValue(mUi->idleActionComboBox, mSettings.getIdlenessAction());

    int idlenessTimeSeconds = mSettings.getIdlenessTimeSecs();
    if (idlenessTimeSeconds < 5) idlenessTimeSeconds = 5;
    int idlenessTimeMinutes = idlenessTimeSeconds/60;
    idlenessTimeSeconds = idlenessTimeSeconds % 60;
    mUi->idleTimeMinutesSpinBox->setValue(idlenessTimeMinutes);
    mUi->idleTimeSecondsSpinBox->setValue(idlenessTimeSeconds);
}

void IdlenessWatcherSettings::minutesChanged(int newVal)
{
    if (newVal <= 1 && mUi->idleTimeSecondsSpinBox->value() < 5)
    {
        mUi->idleTimeSecondsSpinBox->setValue(5);
    }
}

void IdlenessWatcherSettings::secondsChanged(int newVal)
{
    if (newVal > 59)
    {
        mUi->idleTimeSecondsSpinBox->setValue(0);
        mUi->idleTimeMinutesSpinBox->setValue(mUi->idleTimeMinutesSpinBox->value() + 1);
    }
    else if (newVal < 5 && mUi->idleTimeMinutesSpinBox->value() <= 0)
    {
        mUi->idleTimeSecondsSpinBox->setValue(5);
    }
    else if (newVal < 0)
    {
        mUi->idleTimeMinutesSpinBox->setValue(mUi->idleTimeMinutesSpinBox->value() - 1);
        mUi->idleTimeSecondsSpinBox->setValue(59);
    }
}

void IdlenessWatcherSettings::saveSettings()
{
    qDebug() << "IdlenessWatcherSettings:saveSettings";

    mSettings.setIdlenessWatcherEnabled(mUi->idlenessWatcherGroupBox->isChecked());
    mSettings.setIdlenessAction(currentValue(mUi->idleActionComboBox));

    mSettings.setIdlenessTimeSecs(60*mUi->idleTimeMinutesSpinBox->value() + mUi->idleTimeSecondsSpinBox->value());
}
<commit_msg>Fix small bugs in idleness-settings, update of seconds<commit_after>/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * LXDE-Qt - a lightweight, Qt based, desktop toolset
 * http://razor-qt.org
 *
 * Copyright: 2012 Razor team
 * Authors:
 *   Christian Surlykke <christian@surlykke.dk>
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */
#include <QComboBox>
#include <QDebug>

#include "idlenesswatchersettings.h"
#include "ui_idlenesswatchersettings.h"
#include "helpers.h"

IdlenessWatcherSettings::IdlenessWatcherSettings(QWidget *parent) :
    QWidget(parent),
    mSettings(),
    mUi(new Ui::IdlenessWatcherSettings)
{
    mUi->setupUi(this);
    fillComboBox(mUi->idleActionComboBox);
    connect(mUi->idlenessWatcherGroupBox, SIGNAL(clicked()), SLOT(saveSettings()));
    connect(mUi->idleActionComboBox, SIGNAL(activated(int)), SLOT(saveSettings()));
    connect(mUi->idleTimeMinutesSpinBox, SIGNAL(editingFinished()), SLOT(saveSettings()));
    connect(mUi->idleTimeMinutesSpinBox, SIGNAL(valueChanged(int)), SLOT(minutesChanged(int)));
    connect(mUi->idleTimeSecondsSpinBox, SIGNAL(valueChanged(int)), SLOT(secondsChanged(int)));

    connect(mUi->idleTimeSecondsSpinBox, SIGNAL(editingFinished()), SLOT(saveSettings()));
}

IdlenessWatcherSettings::~IdlenessWatcherSettings()
{
    delete mUi;
}

void IdlenessWatcherSettings::loadSettings()
{
    qDebug() << "IdlenessWatcherSettings:loadSettings";

    mUi->idlenessWatcherGroupBox->setChecked(mSettings.isIdlenessWatcherEnabled());
    setComboBoxToValue(mUi->idleActionComboBox, mSettings.getIdlenessAction());

    int idlenessTimeSeconds = mSettings.getIdlenessTimeSecs();
    if (idlenessTimeSeconds < 5) idlenessTimeSeconds = 5;
    int idlenessTimeMinutes = idlenessTimeSeconds/60;
    idlenessTimeSeconds = idlenessTimeSeconds % 60;
    mUi->idleTimeMinutesSpinBox->setValue(idlenessTimeMinutes);
    mUi->idleTimeSecondsSpinBox->setValue(idlenessTimeSeconds);
}

void IdlenessWatcherSettings::minutesChanged(int newVal)
{
    if (newVal < 1 && mUi->idleTimeSecondsSpinBox->value() < 5)
    {
        mUi->idleTimeSecondsSpinBox->setValue(5);
    }
}

void IdlenessWatcherSettings::secondsChanged(int newVal)
{
    if (newVal > 59)
    {
        mUi->idleTimeSecondsSpinBox->setValue(0);
        mUi->idleTimeMinutesSpinBox->setValue(mUi->idleTimeMinutesSpinBox->value() + 1);
    }
    else if (newVal < 5 && mUi->idleTimeMinutesSpinBox->value() <= 0)
    {
        mUi->idleTimeSecondsSpinBox->setValue(5);
    }
    else if (newVal < 0)
    {
        mUi->idleTimeMinutesSpinBox->setValue(mUi->idleTimeMinutesSpinBox->value() - 1);
        mUi->idleTimeSecondsSpinBox->setValue(59);
    }
}

void IdlenessWatcherSettings::saveSettings()
{
    qDebug() << "IdlenessWatcherSettings:saveSettings";

    mSettings.setIdlenessWatcherEnabled(mUi->idlenessWatcherGroupBox->isChecked());
    mSettings.setIdlenessAction(currentValue(mUi->idleActionComboBox));

    mSettings.setIdlenessTimeSecs(60*mUi->idleTimeMinutesSpinBox->value() + mUi->idleTimeSecondsSpinBox->value());
}
<|endoftext|>


<commit_before>#include <omp.h>
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <fstream>
#include <iostream>
#include <armadillo>
#include <iomanip>
#include <vector>

using namespace std;
using namespace arma;

#include "grass-def.hpp"
#include "grass-impl.hpp"

//Home
//const std::string path = "/media/johanna/HD1T/codes/datasets_codes/KTH/";

//WANDA
const std::string path = "/home/johanna/codes/codes-git/study-paper/trunk/features/";

const std::string peopleList = "people_list.txt";
const std::string  actionNames = "actionNames.txt";

///kth
// int ori_col = 160;
// int ori_row = 120;

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

  //    if(argc < 3 )
  //   {
  //     cout << "usage: " << argv[0] << " scale_factor " << " shift_factor " << endl;
  //     return -1;
  //   }
  //
  //
  //   int scale_factor = atoi( argv[1] );
  //   int shift = atoi( argv[2] );

  //vec vec_shift;
  //vec_shift << -25 << -20 << -15 << -10 << -5 << 5 << 10 << 15 << 20 << 25 << endr;
  int scale_factor =1;

  int total_scenes = 1; //Try only with scenario 1
  int segment_length = 20; // Not Used
  //int p   = 12; //To obtain the optimise sub-space of order p
  int dim = 12;

  //for (int i=0; i< vec_shift.n_elem; ++i)
  {
    int shift = 0;
    for (int p=1; p<= dim; ++p)
    {

      cout << "Gp for shift " << shift << " &  p= " << p << endl;

      field<string> all_people;
      all_people.load(peopleList);

      grass_points get_gp(path, actionNames, scale_factor, shift, total_scenes, segment_length, p);
      //get_gp.calculate( all_people, dim );
      get_gp.calculate_onepervideo( all_people, dim );
    }
  }

  return 0;

}
<commit_msg>Get Gp dim_12_no_xy<commit_after>#include <omp.h>
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <fstream>
#include <iostream>
#include <armadillo>
#include <iomanip>
#include <vector>

using namespace std;
using namespace arma;

#include "grass-def.hpp"
#include "grass-impl.hpp"

//Home
//const std::string path = "/media/johanna/HD1T/codes/datasets_codes/KTH/";

//WANDA
const std::string path = "/home/johanna/codes/codes-git/study-paper/trunk/dim_12_no_xy/features/";

const std::string peopleList = "people_list.txt";
const std::string  actionNames = "actionNames.txt";

///kth
// int ori_col = 160;
// int ori_row = 120;

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

  //    if(argc < 3 )
  //   {
  //     cout << "usage: " << argv[0] << " scale_factor " << " shift_factor " << endl;
  //     return -1;
  //   }
  //
  //
  //   int scale_factor = atoi( argv[1] );
  //   int shift = atoi( argv[2] );

  //vec vec_shift;
  //vec_shift << -25 << -20 << -15 << -10 << -5 << 5 << 10 << 15 << 20 << 25 << endr;
  int scale_factor =1;

  int total_scenes = 1; //Try only with scenario 1
  int segment_length = 20; // Not Used
  //int p   = 12; //To obtain the optimise sub-space of order p
  int dim = 12;

  //for (int i=0; i< vec_shift.n_elem; ++i)
  {
    int shift = 0;
    for (int p=1; p<= dim; ++p)
    {

      cout << "Gp for shift " << shift << " &  p= " << p << endl;

      field<string> all_people;
      all_people.load(peopleList);

      grass_points get_gp(path, actionNames, scale_factor, shift, total_scenes, segment_length, p);
      //get_gp.calculate( all_people, dim );
      get_gp.calculate_onepervideo( all_people, dim );
    }
  }

  return 0;

}
<|endoftext|>


<commit_before>// Copyright (c) 2014, Facebook, Inc.  All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.

#include "rocksdb/utilities/flashcache.h"

#include "utilities/flashcache/flashcache.h"

#ifdef OS_LINUX
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <unistd.h>

#include "third-party/flashcache/flashcache_ioctl.h"
#endif

namespace rocksdb {

#if !defined(ROCKSDB_LITE) && defined(OS_LINUX)
// Most of the code that handles flashcache is copied from websql's branch of
// mysql-5.6
class FlashcacheAwareEnv : public EnvWrapper {
 public:
  FlashcacheAwareEnv(Env* base, int cachedev_fd)
      : EnvWrapper(base), cachedev_fd_(cachedev_fd) {
    pid_t pid = getpid();
    /* cleanup previous whitelistings */
    if (ioctl(cachedev_fd_, FLASHCACHEDELALLWHITELIST, &pid) < 0) {
      cachedev_fd_ = -1;
      fprintf(stderr, "ioctl del-all-whitelist for flashcache failed\n");
      return;
    }
    if (ioctl(cachedev_fd_, FLASHCACHEADDWHITELIST, &pid) < 0) {
      fprintf(stderr, "ioctl add-whitelist for flashcache failed\n");
    }
  }

  ~FlashcacheAwareEnv() {
    // cachedev_fd_ is -1 if it's unitialized
    if (cachedev_fd_ != -1) {
      pid_t pid = getpid();
      if (ioctl(cachedev_fd_, FLASHCACHEDELWHITELIST, &pid) < 0) {
        fprintf(stderr, "ioctl del-whitelist for flashcache failed\n");
      }
    }
  }

  static int BlacklistCurrentThread(int cachedev_fd) {
    pid_t pid = static_cast<pid_t>(syscall(SYS_gettid));
    return ioctl(cachedev_fd, FLASHCACHEADDNCPID, &pid);
  }

  static int WhitelistCurrentThread(int cachedev_fd) {
    pid_t pid = static_cast<pid_t>(syscall(SYS_gettid));
    return ioctl(cachedev_fd, FLASHCACHEDELNCPID, &pid);
  }

  int GetFlashCacheFileDescriptor() { return cachedev_fd_; }

  struct Arg {
    Arg(void (*f)(void* arg), void* a, int _cachedev_fd)
        : original_function_(f), original_arg_(a), cachedev_fd(_cachedev_fd) {}

    void (*original_function_)(void* arg);
    void* original_arg_;
    int cachedev_fd;
  };

  static void BgThreadWrapper(void* a) {
    Arg* arg = reinterpret_cast<Arg*>(a);
    if (arg->cachedev_fd != -1) {
      if (BlacklistCurrentThread(arg->cachedev_fd) < 0) {
        fprintf(stderr, "ioctl add-nc-pid for flashcache failed\n");
      }
    }
    arg->original_function_(arg->original_arg_);
    if (arg->cachedev_fd != -1) {
      if (WhitelistCurrentThread(arg->cachedev_fd) < 0) {
        fprintf(stderr, "ioctl del-nc-pid for flashcache failed\n");
      }
    }
    delete arg;
  }

  int UnSchedule(void* arg, Priority pri) override {
    // no unschedule for you
    return 0;
  }

  void Schedule(void (*f)(void* arg), void* a, Priority pri,
                void* tag = nullptr) override {
    EnvWrapper::Schedule(&BgThreadWrapper, new Arg(f, a, cachedev_fd_), pri,
                         tag);
  }

 private:
  int cachedev_fd_;
};

std::unique_ptr<Env> NewFlashcacheAwareEnv(Env* base,
                                           const int cachedev_fd) {
  std::unique_ptr<Env> ret(new FlashcacheAwareEnv(base, cachedev_fd));
  return std::move(ret);
}

int FlashcacheBlacklistCurrentThread(Env* flashcache_aware_env) {
  int fd = dynamic_cast<FlashcacheAwareEnv*>(flashcache_aware_env)
               ->GetFlashCacheFileDescriptor();
  if (fd == -1) {
    return -1;
  }
  return FlashcacheAwareEnv::BlacklistCurrentThread(fd);
}
int FlashcacheWhitelistCurrentThread(Env* flashcache_aware_env) {
  int fd = dynamic_cast<FlashcacheAwareEnv*>(flashcache_aware_env)
               ->GetFlashCacheFileDescriptor();
  if (fd == -1) {
    return -1;
  }
  return FlashcacheAwareEnv::WhitelistCurrentThread(fd);
}

#else   // !defined(ROCKSDB_LITE) && defined(OS_LINUX)
std::unique_ptr<Env> NewFlashcacheAwareEnv(Env* base,
                                           const std::string& flashcache_dev) {
  return nullptr;
}
int FlashcacheBlacklistCurrentThread(Env* flashcache_aware_env) { return -1; }
int FlashcacheWhitelistCurrentThread(Env* flashcache_aware_env) { return -1; }

#endif  // !defined(ROCKSDB_LITE) && defined(OS_LINUX)

}  // namespace rocksdb
<commit_msg>Fix the compilation error in flashcache.cc on Mac<commit_after>// Copyright (c) 2014, Facebook, Inc.  All rights reserved.
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree. An additional grant
// of patent rights can be found in the PATENTS file in the same directory.

#include "rocksdb/utilities/flashcache.h"

#include "utilities/flashcache/flashcache.h"

#ifdef OS_LINUX
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <unistd.h>

#include "third-party/flashcache/flashcache_ioctl.h"
#endif

namespace rocksdb {

#if !defined(ROCKSDB_LITE) && defined(OS_LINUX)
// Most of the code that handles flashcache is copied from websql's branch of
// mysql-5.6
class FlashcacheAwareEnv : public EnvWrapper {
 public:
  FlashcacheAwareEnv(Env* base, int cachedev_fd)
      : EnvWrapper(base), cachedev_fd_(cachedev_fd) {
    pid_t pid = getpid();
    /* cleanup previous whitelistings */
    if (ioctl(cachedev_fd_, FLASHCACHEDELALLWHITELIST, &pid) < 0) {
      cachedev_fd_ = -1;
      fprintf(stderr, "ioctl del-all-whitelist for flashcache failed\n");
      return;
    }
    if (ioctl(cachedev_fd_, FLASHCACHEADDWHITELIST, &pid) < 0) {
      fprintf(stderr, "ioctl add-whitelist for flashcache failed\n");
    }
  }

  ~FlashcacheAwareEnv() {
    // cachedev_fd_ is -1 if it's unitialized
    if (cachedev_fd_ != -1) {
      pid_t pid = getpid();
      if (ioctl(cachedev_fd_, FLASHCACHEDELWHITELIST, &pid) < 0) {
        fprintf(stderr, "ioctl del-whitelist for flashcache failed\n");
      }
    }
  }

  static int BlacklistCurrentThread(int cachedev_fd) {
    pid_t pid = static_cast<pid_t>(syscall(SYS_gettid));
    return ioctl(cachedev_fd, FLASHCACHEADDNCPID, &pid);
  }

  static int WhitelistCurrentThread(int cachedev_fd) {
    pid_t pid = static_cast<pid_t>(syscall(SYS_gettid));
    return ioctl(cachedev_fd, FLASHCACHEDELNCPID, &pid);
  }

  int GetFlashCacheFileDescriptor() { return cachedev_fd_; }

  struct Arg {
    Arg(void (*f)(void* arg), void* a, int _cachedev_fd)
        : original_function_(f), original_arg_(a), cachedev_fd(_cachedev_fd) {}

    void (*original_function_)(void* arg);
    void* original_arg_;
    int cachedev_fd;
  };

  static void BgThreadWrapper(void* a) {
    Arg* arg = reinterpret_cast<Arg*>(a);
    if (arg->cachedev_fd != -1) {
      if (BlacklistCurrentThread(arg->cachedev_fd) < 0) {
        fprintf(stderr, "ioctl add-nc-pid for flashcache failed\n");
      }
    }
    arg->original_function_(arg->original_arg_);
    if (arg->cachedev_fd != -1) {
      if (WhitelistCurrentThread(arg->cachedev_fd) < 0) {
        fprintf(stderr, "ioctl del-nc-pid for flashcache failed\n");
      }
    }
    delete arg;
  }

  int UnSchedule(void* arg, Priority pri) override {
    // no unschedule for you
    return 0;
  }

  void Schedule(void (*f)(void* arg), void* a, Priority pri,
                void* tag = nullptr) override {
    EnvWrapper::Schedule(&BgThreadWrapper, new Arg(f, a, cachedev_fd_), pri,
                         tag);
  }

 private:
  int cachedev_fd_;
};

std::unique_ptr<Env> NewFlashcacheAwareEnv(Env* base,
                                           const int cachedev_fd) {
  std::unique_ptr<Env> ret(new FlashcacheAwareEnv(base, cachedev_fd));
  return std::move(ret);
}

int FlashcacheBlacklistCurrentThread(Env* flashcache_aware_env) {
  int fd = dynamic_cast<FlashcacheAwareEnv*>(flashcache_aware_env)
               ->GetFlashCacheFileDescriptor();
  if (fd == -1) {
    return -1;
  }
  return FlashcacheAwareEnv::BlacklistCurrentThread(fd);
}
int FlashcacheWhitelistCurrentThread(Env* flashcache_aware_env) {
  int fd = dynamic_cast<FlashcacheAwareEnv*>(flashcache_aware_env)
               ->GetFlashCacheFileDescriptor();
  if (fd == -1) {
    return -1;
  }
  return FlashcacheAwareEnv::WhitelistCurrentThread(fd);
}

#else   // !defined(ROCKSDB_LITE) && defined(OS_LINUX)
std::unique_ptr<Env> NewFlashcacheAwareEnv(Env* base,
                                           const int cachedev_fd) {
  return nullptr;
}
int FlashcacheBlacklistCurrentThread(Env* flashcache_aware_env) { return -1; }
int FlashcacheWhitelistCurrentThread(Env* flashcache_aware_env) { return -1; }

#endif  // !defined(ROCKSDB_LITE) && defined(OS_LINUX)

}  // namespace rocksdb
<|endoftext|>


<commit_before>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2018-2019 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include "vk_test.h"

TEST(VK_Misaligned_Dirty, VulkanGraphicsTest)
{
  static constexpr const char *Description =
      "Generate a case where the initial states for a buffer end up being misaligned with what can "
      "be cleared.";

  std::string common = R"EOSHADER(

#version 420 core

struct v2f
{
	vec4 pos;
	vec4 col;
	vec4 uv;
};

)EOSHADER";

  const std::string vertex = R"EOSHADER(

layout(location = 0) in vec3 Position;
layout(location = 1) in vec4 Color;
layout(location = 2) in vec2 UV;

layout(location = 0) out v2f vertOut;

void main()
{
	vertOut.pos = vec4(Position.xyz*vec3(1,-1,1), 1);
	gl_Position = vertOut.pos;
	vertOut.col = Color;
	vertOut.uv = vec4(UV.xy, 0, 1);
}

)EOSHADER";

  const std::string pixel = R"EOSHADER(

layout(location = 0) in v2f vertIn;

layout(location = 0, index = 0) out vec4 Color;

void main()
{
	Color = vertIn.col;
}

)EOSHADER";

  int main()
  {
    // initialise, create window, create context, etc
    if(!Init())
      return 3;

    VkPipelineLayout layout = createPipelineLayout(vkh::PipelineLayoutCreateInfo());

    vkh::GraphicsPipelineCreateInfo pipeCreateInfo;

    pipeCreateInfo.layout = layout;
    pipeCreateInfo.renderPass = mainWindow->rp;

    pipeCreateInfo.vertexInputState.vertexBindingDescriptions = {vkh::vertexBind(0, DefaultA2V)};
    pipeCreateInfo.vertexInputState.vertexAttributeDescriptions = {
        vkh::vertexAttr(0, 0, DefaultA2V, pos), vkh::vertexAttr(1, 0, DefaultA2V, col),
        vkh::vertexAttr(2, 0, DefaultA2V, uv),
    };

    pipeCreateInfo.stages = {
        CompileShaderModule(common + vertex, ShaderLang::glsl, ShaderStage::vert, "main"),
        CompileShaderModule(common + pixel, ShaderLang::glsl, ShaderStage::frag, "main"),
    };

    VkPipeline pipe = createGraphicsPipeline(pipeCreateInfo);

    AllocatedBuffer vb(
        allocator, vkh::BufferCreateInfo(sizeof(DefaultTri), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
                                                                 VK_BUFFER_USAGE_TRANSFER_DST_BIT),
        VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));

    vb.upload(DefaultTri);

    AllocatedBuffer copy_src(
        allocator, vkh::BufferCreateInfo(sizeof(DefaultTri), VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
                                                                 VK_BUFFER_USAGE_TRANSFER_DST_BIT),
        VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));

    copy_src.upload(DefaultTri);

    while(Running())
    {
      VkCommandBuffer cmd = GetCommandBuffer();

      vkBeginCommandBuffer(cmd, vkh::CommandBufferBeginInfo());

      VkImage swapimg =
          StartUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);

      vkCmdClearColorImage(cmd, swapimg, VK_IMAGE_LAYOUT_GENERAL,
                           vkh::ClearColorValue(0.4f, 0.5f, 0.6f, 1.0f), 1,
                           vkh::ImageSubresourceRange());

      VkBufferCopy region = {};
      region.srcOffset = 3;
      region.dstOffset = 3;
      region.size = 7;
      vkCmdCopyBuffer(cmd, copy_src.buffer, vb.buffer, 1, &region);

      vkCmdBeginRenderPass(
          cmd, vkh::RenderPassBeginInfo(mainWindow->rp, mainWindow->GetFB(), mainWindow->scissor),
          VK_SUBPASS_CONTENTS_INLINE);

      vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
      vkCmdSetViewport(cmd, 0, 1, &mainWindow->viewport);
      vkCmdSetScissor(cmd, 0, 1, &mainWindow->scissor);
      vkh::cmdBindVertexBuffers(cmd, 0, {vb.buffer}, {0});
      vkCmdDraw(cmd, 3, 1, 0, 0);

      vkCmdEndRenderPass(cmd);

      FinishUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);

      vkEndCommandBuffer(cmd);

      Submit(0, 1, {cmd});

      Present();
    }

    return 0;
  }
};

REGISTER_TEST();
<commit_msg>Update misaligned dirty demo to have interesting data in all bytes<commit_after>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2018-2019 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include "vk_test.h"

TEST(VK_Misaligned_Dirty, VulkanGraphicsTest)
{
  static constexpr const char *Description =
      "Generate a case where the initial states for a buffer end up being misaligned with what can "
      "be cleared.";

  std::string common = R"EOSHADER(

#version 420 core

struct v2f
{
	vec4 pos;
	vec4 col;
	vec4 uv;
};

)EOSHADER";

  const std::string vertex = R"EOSHADER(

layout(location = 0) in vec3 Position;
layout(location = 1) in vec4 Color;
layout(location = 2) in vec2 UV;

layout(location = 0) out v2f vertOut;

void main()
{
	vertOut.pos = vec4(Position.xyz*vec3(1,-1,1), 1);
	gl_Position = vertOut.pos;
	vertOut.col = Color;
	vertOut.uv = vec4(UV.xy, 0, 1);
}

)EOSHADER";

  const std::string pixel = R"EOSHADER(

layout(location = 0) in v2f vertIn;

layout(location = 0, index = 0) out vec4 Color;

void main()
{
	Color = vertIn.col;
}

)EOSHADER";

  int main()
  {
    // initialise, create window, create context, etc
    if(!Init())
      return 3;

    VkPipelineLayout layout = createPipelineLayout(vkh::PipelineLayoutCreateInfo());

    vkh::GraphicsPipelineCreateInfo pipeCreateInfo;

    pipeCreateInfo.layout = layout;
    pipeCreateInfo.renderPass = mainWindow->rp;

    pipeCreateInfo.vertexInputState.vertexBindingDescriptions = {vkh::vertexBind(0, DefaultA2V)};
    pipeCreateInfo.vertexInputState.vertexAttributeDescriptions = {
        vkh::vertexAttr(0, 0, DefaultA2V, pos), vkh::vertexAttr(1, 0, DefaultA2V, col),
        vkh::vertexAttr(2, 0, DefaultA2V, uv),
    };

    pipeCreateInfo.stages = {
        CompileShaderModule(common + vertex, ShaderLang::glsl, ShaderStage::vert, "main"),
        CompileShaderModule(common + pixel, ShaderLang::glsl, ShaderStage::frag, "main"),
    };

    VkPipeline pipe = createGraphicsPipeline(pipeCreateInfo);

    const float val = 2.0f / 3.0f;

    const DefaultA2V tri[3] = {
        {Vec3f(-val, -val, val), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 0.0f)},
        {Vec3f(0.0f, val, val), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(0.0f, 1.0f)},
        {Vec3f(val, -val, val), Vec4f(0.0f, 1.0f, 0.0f, 1.0f), Vec2f(1.0f, 0.0f)},
    };

    AllocatedBuffer vb(allocator,
                       vkh::BufferCreateInfo(sizeof(tri), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
                                                              VK_BUFFER_USAGE_TRANSFER_DST_BIT),
                       VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));

    vb.upload(tri);

    AllocatedBuffer copy_src(
        allocator, vkh::BufferCreateInfo(sizeof(tri), VK_BUFFER_USAGE_TRANSFER_SRC_BIT |
                                                          VK_BUFFER_USAGE_TRANSFER_DST_BIT),
        VmaAllocationCreateInfo({0, VMA_MEMORY_USAGE_CPU_TO_GPU}));

    copy_src.upload(tri);

    while(Running())
    {
      VkCommandBuffer cmd = GetCommandBuffer();

      vkBeginCommandBuffer(cmd, vkh::CommandBufferBeginInfo());

      VkImage swapimg =
          StartUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);

      vkCmdClearColorImage(cmd, swapimg, VK_IMAGE_LAYOUT_GENERAL,
                           vkh::ClearColorValue(0.4f, 0.5f, 0.6f, 1.0f), 1,
                           vkh::ImageSubresourceRange());

      VkBufferCopy region = {};
      region.srcOffset = 3;
      region.dstOffset = 3;
      region.size = 7;
      vkCmdCopyBuffer(cmd, copy_src.buffer, vb.buffer, 1, &region);

      vkCmdBeginRenderPass(
          cmd, vkh::RenderPassBeginInfo(mainWindow->rp, mainWindow->GetFB(), mainWindow->scissor),
          VK_SUBPASS_CONTENTS_INLINE);

      vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipe);
      vkCmdSetViewport(cmd, 0, 1, &mainWindow->viewport);
      vkCmdSetScissor(cmd, 0, 1, &mainWindow->scissor);
      vkh::cmdBindVertexBuffers(cmd, 0, {vb.buffer}, {0});
      vkCmdDraw(cmd, 3, 1, 0, 0);

      vkCmdEndRenderPass(cmd);

      FinishUsingBackbuffer(cmd, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);

      vkEndCommandBuffer(cmd);

      Submit(0, 1, {cmd});

      Present();
    }

    return 0;
  }
};

REGISTER_TEST();
<|endoftext|>


<commit_before>//
// Created by permal on 6/25/17.
//

#include <cstring>
#include <smooth/network/Socket.h>

#include <esp_log.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <errno.h>
#include <smooth/network/SocketDispatcher.h>

namespace smooth
{
    namespace network
    {
        Socket::Socket(util::ICircularBuffer<char>& tx_buffer, util::ICircularBuffer<char>& rx_buffer,
                       smooth::ipc::TaskEventQueue<smooth::network::TransmitBufferEmpty>& tx_empty,
                       smooth::ipc::TaskEventQueue<smooth::network::DataAvailable>& data_available)
                :
                tx_buffer(tx_buffer), rx_buffer(rx_buffer), tx_empty(tx_empty), data_available(data_available)
        {
        }

        bool Socket::start(std::shared_ptr<InetAddress> ip)
        {
            this->ip = ip;
            bool res = ip->is_valid() && create_socket();
            if (res)
            {
                SocketDispatcher::instance().add_socket(this);
            }

            return res;
        }

        bool Socket::create_socket()
        {
            bool res = false;

            if (socket_id < 0)
            {
                socket_id = socket(ip->get_protocol_family(), SOCK_STREAM, 0);

                if (socket_id == -1)
                {
                    ESP_LOGV("Socket", "Creation failed, id: %s", strerror(errno));
                }
                else
                {
                    res = set_non_blocking();
                    int no_delay = 1;
                    res &= setsockopt(socket_id, IPPROTO_TCP, TCP_NODELAY, &no_delay, sizeof(no_delay)) == 0;
                    if (res)
                    {
                        ESP_LOGV("Socket", "Created: id: %d", socket_id);
                    }
                }
            }
            else
            {
                res = true;
            }

            return res;
        }

        bool Socket::set_non_blocking()
        {
            bool res = true;

            auto opts = fcntl(socket_id, F_GETFL, 0);
            if (opts < 0)
            {
                ESP_LOGE("Socket", "Could not get socket flags: %s", strerror(errno));
                res = false;
            }
            else if (fcntl(socket_id, F_SETFL, opts | O_NONBLOCK) < 0)
            {
                ESP_LOGE("Socket", "Could not set socket flags: %s", strerror(errno));
                res = false;
            }

            return res;
        }

        void Socket::readable()
        {
            // Detect disconnection
            char b[1];
            int res = recv(socket_id, b, 1, MSG_PEEK);
            if (res <= 0)
            {
                if (res == -1)
                {
                    const char* error = strerror(errno);
                    ESP_LOGV("Socket", "Error: %d: %s", socket_id, error);
                }

                stop();
            }
            else
            {
                ESP_LOGV("readable", "readable");
                // attempt to read available data
                // Any room left in buffer?
                if (rx_buffer.available_slots() > 0)
                {
                    char data;
                    int read_count = 0;

                    do
                    {
                        read_count = recv(socket_id, &data, sizeof(data), 0);
                        ESP_LOGV("read", "%d", read_count);
                        if (read_count > 0)
                        {
                            rx_buffer.put(data);
                        }
                    }
                    while (rx_buffer.available_slots() > 0 && read_count > 0);

                    if (read_count == -1)
                    {
                        if (errno != EWOULDBLOCK)
                        {
                            const char* error = strerror(errno);
                            ESP_LOGV("Socket", "readable(): %d: %s", socket_id, error);
                            stop();
                        }
                    }

                    if( connected )
                    {
                        DataAvailable d(&rx_buffer);
                        data_available.push(d);
                    }
                }

            }
        }

        void Socket::writable()
        {
            if (!connected)
            {
                int result;
                socklen_t size = sizeof(result);
                if (getsockopt(socket_id, SOL_SOCKET, SO_ERROR, &result, &size) < 0)
                {
                    ESP_LOGV("Socket", "getsockopt failed");
                    stop();
                }
                else if (result != 0)
                {
                    ESP_LOGV("Socket", "getsockopt: %d", result);
                    stop();
                }
            }
            else
            {
                char data;
                if (has_data_to_transmit())
                {
                    while (tx_buffer.get(data))
                    {
                        int res = ::send(socket_id, &data, sizeof(data), 0);
                        if (res == -1)
                        {
                            if (errno != EWOULDBLOCK)
                            {
                                const char* error = strerror(errno);
                                ESP_LOGE("Socket", "Failed during send: %d, %s", errno, error);
                                stop();
                            }
                        }
                    }

                    if (connected)
                    {
                        // Notify data is sent
                        smooth::network::TransmitBufferEmpty msg(&tx_buffer);
                        tx_empty.push(msg);
                    }
                }
            }
        }

        bool Socket::is_started()
        {
            return started;
        }

        void Socket::internal_start()
        {
            if (!is_started())
            {
                bool could_create = create_socket();

                if (could_create)
                {
                    // The socket is non-blocking so we expect return value of either 0, or -1 with errno == EINPROGRESS
                    int res = connect(socket_id, ip->get_socket_address(), ip->get_socket_address_length());
                    if (res == 0 || (res == -1 && errno == EINPROGRESS))
                    {
                        ESP_LOGV("Socket", "started: %d", socket_id);
                        started = true;
                    }
                    else
                    {
                        const char* error = strerror(errno);
                        ESP_LOGV("Socket", "connect: %d, errno: %s", res, error);
                    }
                }

                if (!started)
                {
                    stop();
                }
            }
        }

        void Socket::check_if_connection_is_completed()
        {
            int res = connect(socket_id, ip->get_socket_address(), ip->get_socket_address_length());
            if (res == -1 && errno == EISCONN)
            {
                connected = true;
                ESP_LOGV("Socket", "Connected %d", socket_id);
                // QQQ Notify receiver connection is completed
            }
        }

        void Socket::stop()
        {
            shutdown(socket_id, SHUT_RDWR);
            close(socket_id);
            started = false;
            connected = false;
            tx_buffer.clear();
            rx_buffer.clear();
            SocketDispatcher::instance().socket_closed(this);

            // Reset socket_id last as it is used as an identifier up to this point.
            socket_id = -1;
        }

    }
}
<commit_msg>Pretty ineffective, but stable communication.<commit_after>//
// Created by permal on 6/25/17.
//

#include <cstring>
#include <smooth/network/Socket.h>

#include <esp_log.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <errno.h>
#include <smooth/network/SocketDispatcher.h>

namespace smooth
{
    namespace network
    {
        Socket::Socket(util::ICircularBuffer<char>& tx_buffer, util::ICircularBuffer<char>& rx_buffer,
                       smooth::ipc::TaskEventQueue<smooth::network::TransmitBufferEmpty>& tx_empty,
                       smooth::ipc::TaskEventQueue<smooth::network::DataAvailable>& data_available)
                :
                tx_buffer(tx_buffer), rx_buffer(rx_buffer), tx_empty(tx_empty), data_available(data_available)
        {
        }

        bool Socket::start(std::shared_ptr<InetAddress> ip)
        {
            this->ip = ip;
            bool res = ip->is_valid() && create_socket();
            if (res)
            {
                SocketDispatcher::instance().add_socket(this);
            }

            return res;
        }

        bool Socket::create_socket()
        {
            bool res = false;

            if (socket_id < 0)
            {
                socket_id = socket(ip->get_protocol_family(), SOCK_STREAM, 0);

                if (socket_id == -1)
                {
                    ESP_LOGV("Socket", "Creation failed, id: %s", strerror(errno));
                }
                else
                {
                    res = set_non_blocking();
                    int no_delay = 1;
                    res &= setsockopt(socket_id, IPPROTO_TCP, TCP_NODELAY, &no_delay, sizeof(no_delay)) == 0;
                    if (res)
                    {
                        ESP_LOGV("Socket", "Created: id: %d", socket_id);
                    }
                }
            }
            else
            {
                res = true;
            }

            return res;
        }

        bool Socket::set_non_blocking()
        {
            bool res = true;

            auto opts = fcntl(socket_id, F_GETFL, 0);
            if (opts < 0)
            {
                ESP_LOGE("Socket", "Could not get socket flags: %s", strerror(errno));
                res = false;
            }
            else if (fcntl(socket_id, F_SETFL, opts | O_NONBLOCK) < 0)
            {
                ESP_LOGE("Socket", "Could not set socket flags: %s", strerror(errno));
                res = false;
            }

            return res;
        }

        void Socket::readable()
        {
            // Detect disconnection
            char b[1];
            int res = recv(socket_id, b, 1, MSG_PEEK);
            if (res <= 0)
            {
                if (res == -1)
                {
                    const char* error = strerror(errno);
                    ESP_LOGV("Socket", "Error: %d: %s", socket_id, error);
                }

                stop();
            }
            else
            {
                ESP_LOGV("readable", "readable");
                // attempt to read available data
                // Any room left in buffer?
                if (rx_buffer.available_slots() > 0)
                {
                    char data;
                    int read_count = 0;

                    do
                    {
                        read_count = recv(socket_id, &data, sizeof(data), 0);
                        ESP_LOGV("read", "%d", read_count);
                        if (read_count > 0)
                        {
                            rx_buffer.put(data);
                        }
                    }
                    while (rx_buffer.available_slots() > 0 && read_count > 0);

                    if (read_count == -1)
                    {
                        if (errno != EWOULDBLOCK)
                        {
                            const char* error = strerror(errno);
                            ESP_LOGV("Socket", "readable(): %d: %s", socket_id, error);
                            stop();
                        }
                    }

                    if( connected )
                    {
                        DataAvailable d(&rx_buffer);
                        data_available.push(d);
                    }
                }

            }
        }

        void Socket::writable()
        {
            if (!connected)
            {
                int result;
                socklen_t size = sizeof(result);
                if (getsockopt(socket_id, SOL_SOCKET, SO_ERROR, &result, &size) < 0)
                {
                    ESP_LOGV("Socket", "getsockopt failed");
                    stop();
                }
                else if (result != 0)
                {
                    ESP_LOGV("Socket", "getsockopt: %d", result);
                    stop();
                }
            }
            else
            {
                char data;
                if (has_data_to_transmit())
                {
                    if (tx_buffer.get(data))
                    {
                        int res = ::send(socket_id, &data, sizeof(data), 0);
                        if (res == -1)
                        {
                            if (errno != EWOULDBLOCK)
                            {
                                const char* error = strerror(errno);
                                ESP_LOGE("Socket", "Failed during send: %d, %s", errno, error);
                                stop();
                            }
                        }
                    }

                    // Done transmitting?
                    if (connected && !has_data_to_transmit())
                    {
                        // Notify data is sent
                        smooth::network::TransmitBufferEmpty msg(&tx_buffer);
                        tx_empty.push(msg);
                    }
                }
            }
        }

        bool Socket::is_started()
        {
            return started;
        }

        void Socket::internal_start()
        {
            if (!is_started())
            {
                bool could_create = create_socket();

                if (could_create)
                {
                    // The socket is non-blocking so we expect return value of either 0, or -1 with errno == EINPROGRESS
                    int res = connect(socket_id, ip->get_socket_address(), ip->get_socket_address_length());
                    if (res == 0 || (res == -1 && errno == EINPROGRESS))
                    {
                        ESP_LOGV("Socket", "started: %d", socket_id);
                        started = true;
                    }
                    else
                    {
                        const char* error = strerror(errno);
                        ESP_LOGV("Socket", "connect: %d, errno: %s", res, error);
                    }
                }

                if (!started)
                {
                    stop();
                }
            }
        }

        void Socket::check_if_connection_is_completed()
        {
            int res = connect(socket_id, ip->get_socket_address(), ip->get_socket_address_length());
            if (res == -1 && errno == EISCONN)
            {
                connected = true;
                ESP_LOGV("Socket", "Connected %d", socket_id);
                // QQQ Notify receiver connection is completed
            }
        }

        void Socket::stop()
        {
            shutdown(socket_id, SHUT_RDWR);
            close(socket_id);
            started = false;
            connected = false;
            tx_buffer.clear();
            rx_buffer.clear();
            SocketDispatcher::instance().socket_closed(this);

            // Reset socket_id last as it is used as an identifier up to this point.
            socket_id = -1;
        }

    }
}
<|endoftext|>


<commit_before><commit_msg>`VectorFont`: do not create `Glyph`s if `parent` is `nullptr`.<commit_after><|endoftext|>


<commit_before>#pragma once
#include <boost/spirit/include/support_utree.hpp>
#include <boost/spirit/include/qi.hpp>
#include <istream>

namespace metaSMT {
  namespace smt2 {
    namespace spirit   = boost::spirit;
    namespace qi       = boost::spirit::qi;
    namespace phoenix  = boost::phoenix;
    namespace standard = boost::spirit::standard;
    namespace ascii    = boost::spirit::ascii;

    namespace detail {
      template<typename Iterator>
      struct whitespace : qi::grammar< Iterator >  {
        whitespace()
          : whitespace::base_type(start) {
          using standard::space;
          using standard::char_;
          using qi::eol;

          start = space | ( ';' >> *(char_ - eol) >> eol );
        }

        qi::rule<Iterator> start;
      }; // whitespace

      template < typename Iterator, typename Evaluator >
      struct parser : qi::grammar< Iterator, spirit::utree::list_type(), whitespace<Iterator> > {
        parser( Evaluator &eval )
          : parser::base_type(start)
          , evaluate(eval)
          , evaluator(eval) {

          start %= *( command );

          command %= '(' >> command_name >> *sexpr >> ')';

          sexpr %= qi::string("(") >> *sexpr >> qi::string(")") | symbol | numeral;

          symbol %= qi::lexeme [ +(qi::char_ - end_of_word ) ];

          numeral %= qi::uint_;

          command_name %= qi::lexeme [ +(qi::char_ - end_of_word ) ];

          end_of_word %= qi::space | qi::char_(")");

          start.name( "start" );
          command.name( "command" ) ;
          sexpr.name( "s-expr" );
          symbol.name( "symbol" );
          numeral.name( "numeral" );
          command_name.name( "command_name" );

#if 0
          qi::debug ( start);
          qi::debug ( command );
          qi::debug ( sexpr );
          qi::debug ( symbol );
          qi::debug ( numeral );
          qi::debug ( command_name );
#endif
        }

        qi::rule<Iterator, spirit::utree::list_type(), whitespace< Iterator > > start;
        qi::rule<Iterator, spirit::utree(), whitespace< Iterator > > numeral, sexpr;
        qi::rule<Iterator, spirit::utf8_symbol_type(), whitespace< Iterator > > command_name;
        qi::rule<Iterator, spirit::utf8_string_type(), whitespace< Iterator > > symbol;
        qi::rule<Iterator, spirit::utree(), whitespace< Iterator> > command, declaration;
        qi::rule<Iterator > end_of_word;

        phoenix::function<Evaluator> const evaluate;
        Evaluator& evaluator;
      }; // parser
    } // detail

    template < typename Evaluator >
    class SMT2Parser {
    public:
      SMT2Parser( Evaluator &evaluator )
        : evaluator(evaluator)
      {}

      bool parse( std::istream &instream, spirit::utree::list_type &ast ) {
        if ( !instream.good() ) {
          return false;
        }

        instream.unsetf ( std::ios::skipws );

        spirit::istream_iterator begin(instream);
        spirit::istream_iterator end;

        detail::parser<spirit::istream_iterator, Evaluator> p( evaluator );
        detail::whitespace<spirit::istream_iterator> ws;
        bool r = phrase_parse( begin, end, p, ws, ast );
        if ( r && begin == end ) {
          return true;
        }
        else {
          std::cerr << "ERROR: Parsing failed!" << std::endl;
          std::cerr << "Stop at:" << std::string(begin, end) << std::endl;
          return false;
        }
      }

    private:
      Evaluator &evaluator;
    }; // SMT2Parser

  } // smt2
} // metaSMT
<commit_msg>Server ignores comments in smt input<commit_after>#pragma once
#include <boost/spirit/include/support_utree.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <istream>

namespace metaSMT {
  namespace smt2 {
    namespace spirit   = boost::spirit;
    namespace qi       = boost::spirit::qi;
    namespace phoenix  = boost::phoenix;
    namespace standard = boost::spirit::standard;
    namespace ascii    = boost::spirit::ascii;

    namespace detail {
      template<typename Iterator>
      struct whitespace : qi::grammar< Iterator >  {
        whitespace()
          : whitespace::base_type(start) {
          using standard::space;
          using standard::char_;
          using qi::eol;

          start = space | ( ';' >> *(char_ - eol) >> eol );
        }

        qi::rule<Iterator> start;
      }; // whitespace

      template < typename Iterator, typename Evaluator >
      struct parser : qi::grammar< Iterator, spirit::utree::list_type(), whitespace<Iterator> > {
        parser( Evaluator &eval )
          : parser::base_type(start)
          , evaluate(eval)
          , evaluator(eval) {

          start %= *( command );

          command %= '(' >> command_name >> *sexpr >> ')';

          sexpr %= qi::string("(") >> *sexpr >> qi::string(")") | symbol | numeral;

          symbol %= qi::lexeme [ +(qi::char_ - end_of_word ) ];

          numeral %= qi::uint_;

          command_name %= qi::lexeme [ +(qi::char_ - end_of_word ) ];

          end_of_word %= qi::space | qi::char_(")");

          start.name( "start" );
          command.name( "command" ) ;
          sexpr.name( "s-expr" );
          symbol.name( "symbol" );
          numeral.name( "numeral" );
          command_name.name( "command_name" );

#if 0
          qi::debug ( start);
          qi::debug ( command );
          qi::debug ( sexpr );
          qi::debug ( symbol );
          qi::debug ( numeral );
          qi::debug ( command_name );
#endif
        }

        qi::rule<Iterator, spirit::utree::list_type(), whitespace< Iterator > > start;
        qi::rule<Iterator, spirit::utree(), whitespace< Iterator > > numeral, sexpr;
        qi::rule<Iterator, spirit::utf8_symbol_type(), whitespace< Iterator > > command_name;
        qi::rule<Iterator, spirit::utf8_string_type(), whitespace< Iterator > > symbol;
        qi::rule<Iterator, spirit::utree(), whitespace< Iterator> > command, declaration;
        qi::rule<Iterator > end_of_word;

        phoenix::function<Evaluator> const evaluate;
        Evaluator& evaluator;
      }; // parser
    } // detail

    template < typename Evaluator >
    class SMT2Parser {
    public:
      SMT2Parser( Evaluator &evaluator )
        : evaluator(evaluator)
      {}

      bool parse( std::istream &instream, spirit::utree::list_type &ast ) {
        if ( !instream.good() ) {
          return false;
        }

        instream.unsetf ( std::ios::skipws );

        spirit::istream_iterator begin(instream);
        spirit::istream_iterator end;

        detail::parser<spirit::istream_iterator, Evaluator> p( evaluator );
        detail::whitespace<spirit::istream_iterator> ws;
        bool r = phrase_parse( begin, end, p, ws, ast );
        if ( r && begin == end ) {
          return true;
        }
        else {
          const std::string unparsable = std::string(begin,end);
          if (!boost::algorithm::starts_with(unparsable,";")) {
            std::cerr << "ERROR: Parsing failed!" << std::endl;
            std::cerr << "Stop at \"" << unparsable << "\"" << std::endl;
            return false;
          }
          return true;
        }
      }

    private:
      Evaluator &evaluator;
    }; // SMT2Parser

  } // smt2
} // metaSMT
<|endoftext|>