Пример #1
0
    void
    range_run<Char>::set(range_type const& range)
    {
        BOOST_ASSERT(is_valid(range));
        if (run.empty())
        {
            // the vector is empty, insert 'range'
            run.push_back(range);
            return;
        }

        // search the ranges for one that potentially includes 'range'
        typename storage_type::iterator iter =
            std::upper_bound(
                run.begin(), run.end(), range,
                range_compare<range_type>()
            );

        if (iter != run.begin())
        {
            // if *(iter-1) includes 'range', return early
            if (includes(*(iter-1), range))
            {
                return;
            }

            // if *(iter-1) can merge with 'range', merge them and return
            if (try_merge(run, iter-1, range))
            {
                return;
            }
        }

        // if *iter can merge with with 'range', merge them
        if (iter == run.end() || !try_merge(run, iter, range))
        {
            // no overlap, insert 'range'
            run.insert(iter, range);
        }
    }
Пример #2
0
void shm_free(void *ptr) {
  block *p1, *p2, *p3, *pp;
  int index;

  if(ptr == NULL) {
    return;
  }

  pp = (block*) ptr - 1;

  x_semop(semid, &lock, 1);
  
  for(p1 = buf + 1; (p1->next_index != out_of_memory_index) &&
	((p2 = buf + p1->next_index) != pp); p1 = p2);

  if(p1->next_index == out_of_memory_index) {
    x_semop(semid, &unlock, 1);
    return;
  }

  index = p1->next_index;
  p1->next_index = p2->next_index;

  for(p1 = buf; p1->next_index < index; p1 = buf + p1->next_index);
  
  p3 = NULL;
  if(p1->next_index != out_of_memory_index) {
    p3 = buf + p1->next_index;
  }
  p2->next_index = p1->next_index;
  p1->next_index = index;

  try_merge(p2, p3);
  try_merge(p1, p2);
  
  x_semop(semid, &unlock, 1);
}
Пример #3
0
/*
 * Find the conflict identified by "id"; the change between its
 * "preimage" (i.e. a previous contents with conflict markers) and its
 * "postimage" (i.e. the corresponding contents with conflicts
 * resolved) may apply cleanly to the contents stored in "path", i.e.
 * the conflict this time around.
 *
 * Returns 0 for successful replay of recorded resolution, or non-zero
 * for failure.
 */
static int merge(const struct rerere_id *id, const char *path)
{
	FILE *f;
	int ret;
	mmfile_t cur = {NULL, 0};
	mmbuffer_t result = {NULL, 0};

	/*
	 * Normalize the conflicts in path and write it out to
	 * "thisimage" temporary file.
	 */
	if ((handle_file(path, NULL, rerere_path(id, "thisimage")) < 0) ||
	    read_mmfile(&cur, rerere_path(id, "thisimage"))) {
		ret = 1;
		goto out;
	}

	ret = try_merge(id, path, &cur, &result);
	if (ret)
		goto out;

	/*
	 * A successful replay of recorded resolution.
	 * Mark that "postimage" was used to help gc.
	 */
	if (utime(rerere_path(id, "postimage"), NULL) < 0)
		warning_errno(_("failed utime() on '%s'"),
			      rerere_path(id, "postimage"));

	/* Update "path" with the resolution */
	f = fopen(path, "w");
	if (!f)
		return error_errno(_("could not open '%s'"), path);
	if (fwrite(result.ptr, result.size, 1, f) != 1)
		error_errno(_("could not write '%s'"), path);
	if (fclose(f))
		return error_errno(_("writing '%s' failed"), path);

out:
	free(cur.ptr);
	free(result.ptr);

	return ret;
}
Пример #4
0
static bool
find_inc (bool first_try)
{
  rtx insn;
  basic_block bb = BLOCK_FOR_INSN (mem_insn.insn);
  rtx other_insn;
  df_ref *def_rec;

  /* Make sure this reg appears only once in this insn.  */
  if (count_occurrences (PATTERN (mem_insn.insn), mem_insn.reg0, 1) != 1)
    {
      if (dump_file)
	fprintf (dump_file, "mem count failure\n");
      return false;
    }

  if (dump_file)
    dump_mem_insn (dump_file);

  /* Find the next use that is an inc.  */
  insn = get_next_ref (REGNO (mem_insn.reg0),
		       BLOCK_FOR_INSN (mem_insn.insn),
		       reg_next_inc_use);
  if (!insn)
    return false;

  /* Even though we know the next use is an add or inc because it came
     from the reg_next_inc_use, we must still reparse.  */
  if (!parse_add_or_inc (insn, false))
    {
      /* Next use was not an add.  Look for one extra case. It could be
	 that we have:

	 *(a + b)
	 ...= a;
	 ...= b + a

	 if we reverse the operands in the mem ref we would
	 find this.  Only try it once though.  */
      if (first_try && !mem_insn.reg1_is_const)
	{
	  reverse_mem ();
	  return find_inc (false);
	}
      else
	return false;
    }

  /* Need to assure that none of the operands of the inc instruction are
     assigned to by the mem insn.  */
  for (def_rec = DF_INSN_DEFS (mem_insn.insn); *def_rec; def_rec++)
    {
      df_ref def = *def_rec;
      unsigned int regno = DF_REF_REGNO (def);
      if ((regno == REGNO (inc_insn.reg0))
	  || (regno == REGNO (inc_insn.reg_res)))
	{
	  if (dump_file)
	    fprintf (dump_file, "inc conflicts with store failure.\n");
	  return false;
	}
      if (!inc_insn.reg1_is_const && (regno == REGNO (inc_insn.reg1)))
	{
	  if (dump_file)
	    fprintf (dump_file, "inc conflicts with store failure.\n");
	  return false;
	}
    }

  if (dump_file)
    dump_inc_insn (dump_file);

  if (inc_insn.form == FORM_POST_ADD)
    {
      /* Make sure that there is no insn that assigns to inc_insn.res
	 between the mem_insn and the inc_insn.  */
      rtx other_insn = get_next_ref (REGNO (inc_insn.reg_res),
				     BLOCK_FOR_INSN (mem_insn.insn),
				     reg_next_def);
      if (other_insn != inc_insn.insn)
	{
	  if (dump_file)
	    fprintf (dump_file,
		     "result of add is assigned to between mem and inc insns.\n");
	  return false;
	}

      other_insn = get_next_ref (REGNO (inc_insn.reg_res),
				 BLOCK_FOR_INSN (mem_insn.insn),
				 reg_next_use);
      if (other_insn
	  && (other_insn != inc_insn.insn)
	  && (DF_INSN_LUID (inc_insn.insn) > DF_INSN_LUID (other_insn)))
	{
	  if (dump_file)
	    fprintf (dump_file,
		     "result of add is used between mem and inc insns.\n");
	  return false;
	}

      /* For the post_add to work, the result_reg of the inc must not be
	 used in the mem insn since this will become the new index
	 register.  */
      if (reg_overlap_mentioned_p (inc_insn.reg_res, PATTERN (mem_insn.insn)))
	{
	  if (dump_file)
	    fprintf (dump_file, "base reg replacement failure.\n");
	  return false;
	}
    }

  if (mem_insn.reg1_is_const)
    {
      if (mem_insn.reg1_val == 0)
	{
	  if (!inc_insn.reg1_is_const)
	    {
	      /* The mem looks like *r0 and the rhs of the add has two
		 registers.  */
	      int luid = DF_INSN_LUID (inc_insn.insn);
	      if (inc_insn.form == FORM_POST_ADD)
		{
		  /* The trick is that we are not going to increment r0,
		     we are going to increment the result of the add insn.
		     For this trick to be correct, the result reg of
		     the inc must be a valid addressing reg.  */
		  addr_space_t as = MEM_ADDR_SPACE (*mem_insn.mem_loc);
		  if (GET_MODE (inc_insn.reg_res)
		      != targetm.addr_space.address_mode (as))
		    {
		      if (dump_file)
			fprintf (dump_file, "base reg mode failure.\n");
		      return false;
		    }

		  /* We also need to make sure that the next use of
		     inc result is after the inc.  */
		  other_insn
		    = get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_use);
		  if (other_insn && luid > DF_INSN_LUID (other_insn))
		    return false;

		  if (!rtx_equal_p (mem_insn.reg0, inc_insn.reg0))
		    reverse_inc ();
		}

	      other_insn
		= get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_def);
	      if (other_insn && luid > DF_INSN_LUID (other_insn))
		return false;
	    }
	}
      /* Both the inc/add and the mem have a constant.  Need to check
	 that the constants are ok. */
      else if ((mem_insn.reg1_val != inc_insn.reg1_val)
	       && (mem_insn.reg1_val != -inc_insn.reg1_val))
	return false;
    }
  else
    {
      /* The mem insn is of the form *(a + b) where a and b are both
	 regs.  It may be that in order to match the add or inc we
	 need to treat it as if it was *(b + a).  It may also be that
	 the add is of the form a + c where c does not match b and
	 then we just abandon this.  */

      int luid = DF_INSN_LUID (inc_insn.insn);
      rtx other_insn;

      /* Make sure this reg appears only once in this insn.  */
      if (count_occurrences (PATTERN (mem_insn.insn), mem_insn.reg1, 1) != 1)
	return false;

      if (inc_insn.form == FORM_POST_ADD)
	{
	  /* For this trick to be correct, the result reg of the inc
	     must be a valid addressing reg.  */
	  addr_space_t as = MEM_ADDR_SPACE (*mem_insn.mem_loc);
	  if (GET_MODE (inc_insn.reg_res)
	      != targetm.addr_space.address_mode (as))
	    {
	      if (dump_file)
		fprintf (dump_file, "base reg mode failure.\n");
	      return false;
	    }

	  if (rtx_equal_p (mem_insn.reg0, inc_insn.reg0))
	    {
	      if (!rtx_equal_p (mem_insn.reg1, inc_insn.reg1))
		{
		  /* See comment above on find_inc (false) call.  */
		  if (first_try)
		    {
		      reverse_mem ();
		      return find_inc (false);
		    }
		  else
		    return false;
		}

	      /* Need to check that there are no assignments to b
		 before the add insn.  */
	      other_insn
		= get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_def);
	      if (other_insn && luid > DF_INSN_LUID (other_insn))
		return false;
	      /* All ok for the next step.  */
	    }
	  else
	    {
	      /* We know that mem_insn.reg0 must equal inc_insn.reg1
		 or else we would not have found the inc insn.  */
	      reverse_mem ();
	      if (!rtx_equal_p (mem_insn.reg0, inc_insn.reg0))
		{
		  /* See comment above on find_inc (false) call.  */
		  if (first_try)
		    return find_inc (false);
		  else
		    return false;
		}
	      /* To have gotten here know that.
	       *(b + a)

	       ... = (b + a)

	       We also know that the lhs of the inc is not b or a.  We
	       need to make sure that there are no assignments to b
	       between the mem ref and the inc.  */

	      other_insn
		= get_next_ref (REGNO (inc_insn.reg0), bb, reg_next_def);
	      if (other_insn && luid > DF_INSN_LUID (other_insn))
		return false;
	    }

	  /* Need to check that the next use of the add result is later than
	     add insn since this will be the reg incremented.  */
	  other_insn
	    = get_next_ref (REGNO (inc_insn.reg_res), bb, reg_next_use);
	  if (other_insn && luid > DF_INSN_LUID (other_insn))
	    return false;
	}
      else /* FORM_POST_INC.  There is less to check here because we
	      know that operands must line up.  */
	{
	  if (!rtx_equal_p (mem_insn.reg1, inc_insn.reg1))
	    /* See comment above on find_inc (false) call.  */
	    {
	      if (first_try)
		{
		  reverse_mem ();
		  return find_inc (false);
		}
	      else
		return false;
	    }

	  /* To have gotten here know that.
	   *(a + b)

	   ... = (a + b)

	   We also know that the lhs of the inc is not b.  We need to make
	   sure that there are no assignments to b between the mem ref and
	   the inc.  */
	  other_insn
	    = get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_def);
	  if (other_insn && luid > DF_INSN_LUID (other_insn))
	    return false;
	}
    }

  if (inc_insn.form == FORM_POST_INC)
    {
      other_insn
	= get_next_ref (REGNO (inc_insn.reg0), bb, reg_next_use);
      /* When we found inc_insn, we were looking for the
	 next add or inc, not the next insn that used the
	 reg.  Because we are going to increment the reg
	 in this form, we need to make sure that there
	 were no intervening uses of reg.  */
      if (inc_insn.insn != other_insn)
	return false;
    }

  return try_merge ();
}
Пример #5
0
static void
merge_in_block (int max_reg, basic_block bb)
{
  rtx insn;
  rtx curr;
  int success_in_block = 0;

  if (dump_file)
    fprintf (dump_file, "\n\nstarting bb %d\n", bb->index);

  FOR_BB_INSNS_REVERSE_SAFE (bb, insn, curr)
    {
      unsigned int uid = INSN_UID (insn);
      bool insn_is_add_or_inc = true;

      if (!NONDEBUG_INSN_P (insn))
	continue;

      /* This continue is deliberate.  We do not want the uses of the
	 jump put into reg_next_use because it is not considered safe to
	 combine a preincrement with a jump.  */
      if (JUMP_P (insn))
	continue;

      if (dump_file)
	dump_insn_slim (dump_file, insn);

      /* Does this instruction increment or decrement a register?  */
      if (parse_add_or_inc (insn, true))
	{
	  int regno = REGNO (inc_insn.reg_res);
	  /* Cannot handle case where there are three separate regs
	     before a mem ref.  Too many moves would be needed to be
	     profitable.  */
	  if ((inc_insn.form == FORM_PRE_INC) || inc_insn.reg1_is_const)
	    {
	      mem_insn.insn = get_next_ref (regno, bb, reg_next_use);
	      if (mem_insn.insn)
		{
		  bool ok = true;
		  if (!inc_insn.reg1_is_const)
		    {
		      /* We are only here if we are going to try a
			 HAVE_*_MODIFY_REG type transformation.  c is a
			 reg and we must sure that the path from the
			 inc_insn to the mem_insn.insn is both def and use
			 clear of c because the inc insn is going to move
			 into the mem_insn.insn.  */
		      int luid = DF_INSN_LUID (mem_insn.insn);
		      rtx other_insn
			= get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_use);

		      if (other_insn && luid > DF_INSN_LUID (other_insn))
			ok = false;

		      other_insn
			= get_next_ref (REGNO (inc_insn.reg1), bb, reg_next_def);

		      if (other_insn && luid > DF_INSN_LUID (other_insn))
			ok = false;
		    }

		  if (dump_file)
		    dump_inc_insn (dump_file);

		  if (ok && find_address (&PATTERN (mem_insn.insn)) == -1)
		    {
		      if (dump_file)
			dump_mem_insn (dump_file);
		      if (try_merge ())
			{
			  success_in_block++;
			  insn_is_add_or_inc = false;
			}
		    }
		}
	    }
	}
      else
	{
	  insn_is_add_or_inc = false;
	  mem_insn.insn = insn;
	  if (find_mem (&PATTERN (insn)))
	    success_in_block++;
	}

      /* If the inc insn was merged with a mem, the inc insn is gone
	 and there is noting to update.  */
      if (DF_INSN_UID_GET (uid))
	{
	  df_ref *def_rec;
	  df_ref *use_rec;
	  /* Need to update next use.  */
	  for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
	    {
	      df_ref def = *def_rec;
	      reg_next_use[DF_REF_REGNO (def)] = NULL;
	      reg_next_inc_use[DF_REF_REGNO (def)] = NULL;
	      reg_next_def[DF_REF_REGNO (def)] = insn;
	    }

	  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
	    {
	      df_ref use = *use_rec;
	      reg_next_use[DF_REF_REGNO (use)] = insn;
	      if (insn_is_add_or_inc)
		reg_next_inc_use[DF_REF_REGNO (use)] = insn;
	      else
		reg_next_inc_use[DF_REF_REGNO (use)] = NULL;
	    }
	}
      else if (dump_file)
	fprintf (dump_file, "skipping update of deleted insn %d\n", uid);
    }
Пример #6
0
static int rerere_forget_one_path(const char *path, struct string_list *rr)
{
	const char *filename;
	struct rerere_id *id;
	unsigned char sha1[20];
	int ret;
	struct string_list_item *item;

	/*
	 * Recreate the original conflict from the stages in the
	 * index and compute the conflict ID
	 */
	ret = handle_cache(path, sha1, NULL);
	if (ret < 1)
		return error(_("could not parse conflict hunks in '%s'"), path);

	/* Nuke the recorded resolution for the conflict */
	id = new_rerere_id(sha1);

	for (id->variant = 0;
	     id->variant < id->collection->status_nr;
	     id->variant++) {
		mmfile_t cur = { NULL, 0 };
		mmbuffer_t result = {NULL, 0};
		int cleanly_resolved;

		if (!has_rerere_resolution(id))
			continue;

		handle_cache(path, sha1, rerere_path(id, "thisimage"));
		if (read_mmfile(&cur, rerere_path(id, "thisimage"))) {
			free(cur.ptr);
			error(_("failed to update conflicted state in '%s'"), path);
			goto fail_exit;
		}
		cleanly_resolved = !try_merge(id, path, &cur, &result);
		free(result.ptr);
		free(cur.ptr);
		if (cleanly_resolved)
			break;
	}

	if (id->collection->status_nr <= id->variant) {
		error(_("no remembered resolution for '%s'"), path);
		goto fail_exit;
	}

	filename = rerere_path(id, "postimage");
	if (unlink(filename)) {
		if (errno == ENOENT)
			error(_("no remembered resolution for '%s'"), path);
		else
			error_errno(_("cannot unlink '%s'"), filename);
		goto fail_exit;
	}

	/*
	 * Update the preimage so that the user can resolve the
	 * conflict in the working tree, run us again to record
	 * the postimage.
	 */
	handle_cache(path, sha1, rerere_path(id, "preimage"));
	fprintf_ln(stderr, _("Updated preimage for '%s'"), path);

	/*
	 * And remember that we can record resolution for this
	 * conflict when the user is done.
	 */
	item = string_list_insert(rr, path);
	free_rerere_id(item);
	item->util = id;
	fprintf(stderr, _("Forgot resolution for '%s'\n"), path);
	return 0;

fail_exit:
	free(id);
	return -1;
}
Пример #7
0
static int
thisudp (struct dns_transmit *d)
{
    const char *ip = NULL;

    socketfree (d);
    mergefree (d);

    while (d->udploop < 4)
    {
        for (; d->curserver < 16; ++d->curserver)
        {
            ip = d->servers + 4 * d->curserver;
            if (byte_diff (ip, 4, "\0\0\0\0"))
            {
                if (merge_enable && try_merge (d))
                {
                    if (merge_logger)
                        merge_logger (ip, d->qtype, d->query + 14);
                    return 0;
                }

                d->query[2] = dns_random (256);
                d->query[3] = dns_random (256);

                d->s1 = 1 + socket_udp ();
                if (!d->s1)
                {
                    dns_transmit_free (d);
                    return -1;
                }
                if (randombind (d) == -1)
                {
                    dns_transmit_free (d);
                    return -1;
                }

                if (socket_connect4 (d->s1 - 1, ip, 53) == 0)
                {
                    if (send (d->s1 - 1, d->query + 2, d->querylen - 2, 0)
                            == d->querylen - 2)
                    {
                        struct taia now;

                        taia_now (&now);
                        taia_uint (&d->deadline, timeouts[d->udploop]);
                        taia_add (&d->deadline, &d->deadline, &now);
                        d->tcpstate = 0;
                        if (merge_enable)
                            register_inprogress (d);
                        return 0;
                    }
                }
                socketfree (d);
            }
        }

        ++d->udploop;
        d->curserver = 0;
    }

    dns_transmit_free (d);
    return -1;
}