Beispiel #1
0
static void
split_range (struct eh_range *range, int pc)
{
  struct eh_range *ptr;
  struct eh_range **first_child, **second_child;
  struct eh_range *h;

  /* First, split all the sub-ranges.  */
  for (ptr = range->first_child; ptr; ptr = ptr->next_sibling)
    {
      if (pc > ptr->start_pc
	  && pc < ptr->end_pc)
	{
	  split_range (ptr, pc);
	}
    }

  /* Create a new range.  */
  h = XNEW (struct eh_range);

  h->start_pc = pc;
  h->end_pc = range->end_pc;
  h->next_sibling = range->next_sibling;
  range->next_sibling = h;
  range->end_pc = pc;
  h->handlers = build_tree_list (TREE_PURPOSE (range->handlers),
				 TREE_VALUE (range->handlers));
  h->next_sibling = NULL;
  h->expanded = 0;
  h->stmt = NULL;
  h->outer = range->outer;
  h->first_child = NULL;

  ptr = range->first_child;
  first_child = &range->first_child;
  second_child = &h->first_child;

  /* Distribute the sub-ranges between the two new ranges.  */
  for (ptr = range->first_child; ptr; ptr = ptr->next_sibling)
    {
      if (ptr->start_pc < pc)
	{
	  *first_child = ptr;
	  ptr->outer = range;
	  first_child = &ptr->next_sibling;
	}
      else
	{
	  *second_child = ptr;
	  ptr->outer = h;
	  second_child = &ptr->next_sibling;
	}
    }
  *first_child = NULL;
  *second_child = NULL;
}  
Beispiel #2
0
void 
add_handler (int start_pc, int end_pc, tree handler, tree type)
{
  struct eh_range *ptr, *h;
  struct eh_range **first_child, **prev;

  /* First, split all the existing ranges that we need to enclose.  */
  for (ptr = whole_range.first_child; ptr; ptr = ptr->next_sibling)
    {
      if (start_pc > ptr->start_pc
	  && start_pc < ptr->end_pc)
	{
	  split_range (ptr, start_pc);
	}

      if (end_pc > ptr->start_pc
	  && end_pc < ptr->end_pc)
	{
	  split_range (ptr, end_pc);
	}

      if (ptr->start_pc >= end_pc)
	break;
    }

  /* Create the new range.  */
  h = XNEW (struct eh_range);
  first_child = &h->first_child;

  h->start_pc = start_pc;
  h->end_pc = end_pc;
  h->first_child = NULL;
  h->outer = NULL_EH_RANGE;
  h->handlers = build_tree_list (type, handler);
  h->next_sibling = NULL;
  h->expanded = 0;
  h->stmt = NULL;

  /* Find every range at the top level that will be a sub-range of the
     range we're inserting and make it so.  */
  {
    struct eh_range **prev = &whole_range.first_child;
    for (ptr = *prev; ptr;)
      {
	struct eh_range *next = ptr->next_sibling;

	if (ptr->start_pc >= end_pc)
	  break;

	if (ptr->start_pc < start_pc)
	  {
	    prev = &ptr->next_sibling;
	  }
	else if (ptr->start_pc >= start_pc
		 && ptr->start_pc < end_pc)
	  {
	    *prev = next;
	    *first_child = ptr;
	    first_child = &ptr->next_sibling;
	    ptr->outer = h;
	    ptr->next_sibling = NULL;	  
	  }

	ptr = next;
      }
  }

  /* Find the right place to insert the new range.  */
  prev = &whole_range.first_child;
  for (ptr = *prev; ptr; prev = &ptr->next_sibling, ptr = ptr->next_sibling)
    {
      gcc_assert (ptr->outer == NULL_EH_RANGE);
      if (ptr->start_pc >= start_pc)
	break;
    }

  /* And insert it there.  */
  *prev = h;
  if (ptr)
    {
      h->next_sibling = ptr;
      h->outer = ptr->outer;
    }
}
/**
 * gst_rtsp_address_pool_reserve_address:
 * @pool: a #GstRTSPAddressPool
 * @ip_address: The IP address to reserve
 * @port: The first port to reserve
 * @n_ports: The number of ports
 * @ttl: The requested ttl
 * @address: (out): storage for a #GstRTSPAddress
 *
 * Take a specific address and ports from @pool. @n_ports consecutive
 * ports will be allocated of which the first one can be found in
 * @port.
 *
 * If @ttl is 0, @address should be a unicast address. If @ttl > 0, @address
 * should be a valid multicast address.
 *
 * Returns: #GST_RTSP_ADDRESS_POOL_OK if an address was reserved. The address
 * is returned in @address and should be freed with gst_rtsp_address_free
 * after use.
 */
GstRTSPAddressPoolResult
gst_rtsp_address_pool_reserve_address (GstRTSPAddressPool * pool,
                                       const gchar * ip_address, guint port, guint n_ports, guint ttl,
                                       GstRTSPAddress ** address)
{
    GstRTSPAddressPoolPrivate *priv;
    Addr input_addr;
    GList *list;
    AddrRange *addr_range;
    GstRTSPAddress *addr;
    gboolean is_multicast;
    GstRTSPAddressPoolResult result;

    g_return_val_if_fail (GST_IS_RTSP_ADDRESS_POOL (pool),
                          GST_RTSP_ADDRESS_POOL_EINVAL);
    g_return_val_if_fail (ip_address != NULL, GST_RTSP_ADDRESS_POOL_EINVAL);
    g_return_val_if_fail (port > 0, GST_RTSP_ADDRESS_POOL_EINVAL);
    g_return_val_if_fail (n_ports > 0, GST_RTSP_ADDRESS_POOL_EINVAL);
    g_return_val_if_fail (address != NULL, GST_RTSP_ADDRESS_POOL_EINVAL);

    priv = pool->priv;
    addr_range = NULL;
    addr = NULL;
    is_multicast = ttl != 0;

    if (!fill_address (ip_address, port, &input_addr, is_multicast))
        goto invalid;

    g_mutex_lock (&priv->lock);
    list = find_address_in_ranges (priv->addresses, &input_addr, port, n_ports,
                                   ttl);
    if (list != NULL) {
        AddrRange *range = list->data;
        guint skip_port, skip_addr;

        skip_addr = diff_address (&input_addr, &range->min);
        skip_port = port - range->min.port;

        GST_DEBUG_OBJECT (pool, "diff 0x%08x/%u", skip_addr, skip_port);

        /* we found a range, remove from the list */
        priv->addresses = g_list_delete_link (priv->addresses, list);
        /* now split and exit our loop */
        addr_range = split_range (pool, range, skip_addr, skip_port, n_ports);
        priv->allocated = g_list_prepend (priv->allocated, addr_range);
    }

    if (addr_range) {
        addr = g_slice_new0 (GstRTSPAddress);
        addr->pool = g_object_ref (pool);
        addr->address = get_address_string (&addr_range->min);
        addr->n_ports = n_ports;
        addr->port = addr_range->min.port;
        addr->ttl = addr_range->ttl;
        addr->priv = addr_range;

        result = GST_RTSP_ADDRESS_POOL_OK;
        GST_DEBUG_OBJECT (pool, "reserved address %s:%u ttl %u", addr->address,
                          addr->port, addr->ttl);
    } else {
        /* We failed to reserve the address. Check if it was because the address
         * was already in use or if it wasn't in the pool to begin with */
        list = find_address_in_ranges (priv->allocated, &input_addr, port, n_ports,
                                       ttl);
        if (list != NULL) {
            result = GST_RTSP_ADDRESS_POOL_ERESERVED;
        } else {
            result = GST_RTSP_ADDRESS_POOL_ERANGE;
        }
    }
    g_mutex_unlock (&priv->lock);

    *address = addr;
    return result;

    /* ERRORS */
invalid:
    {
        GST_ERROR_OBJECT (pool, "invalid address %s:%u/%u/%u", ip_address,
                          port, n_ports, ttl);
        *address = NULL;
        return GST_RTSP_ADDRESS_POOL_EINVAL;
    }
}
/**
 * gst_rtsp_address_pool_acquire_address:
 * @pool: a #GstRTSPAddressPool
 * @flags: flags
 * @n_ports: the amount of ports
 *
 * Take an address and ports from @pool. @flags can be used to control the
 * allocation. @n_ports consecutive ports will be allocated of which the first
 * one can be found in @port.
 *
 * Returns: (nullable): a #GstRTSPAddress that should be freed with
 * gst_rtsp_address_free after use or %NULL when no address could be
 * acquired.
 */
GstRTSPAddress *
gst_rtsp_address_pool_acquire_address (GstRTSPAddressPool * pool,
                                       GstRTSPAddressFlags flags, gint n_ports)
{
    GstRTSPAddressPoolPrivate *priv;
    GList *walk, *next;
    AddrRange *result;
    GstRTSPAddress *addr;

    g_return_val_if_fail (GST_IS_RTSP_ADDRESS_POOL (pool), NULL);
    g_return_val_if_fail (n_ports > 0, NULL);

    priv = pool->priv;
    result = NULL;
    addr = NULL;

    g_mutex_lock (&priv->lock);
    /* go over available ranges */
    for (walk = priv->addresses; walk; walk = next) {
        AddrRange *range;
        gint ports, skip;

        range = walk->data;
        next = walk->next;

        /* check address type when given */
        if (flags & GST_RTSP_ADDRESS_FLAG_IPV4 && !ADDR_IS_IPV4 (&range->min))
            continue;
        if (flags & GST_RTSP_ADDRESS_FLAG_IPV6 && !ADDR_IS_IPV6 (&range->min))
            continue;
        if (flags & GST_RTSP_ADDRESS_FLAG_MULTICAST && range->ttl == 0)
            continue;
        if (flags & GST_RTSP_ADDRESS_FLAG_UNICAST && range->ttl != 0)
            continue;

        /* check for enough ports */
        ports = range->max.port - range->min.port + 1;
        if (flags & GST_RTSP_ADDRESS_FLAG_EVEN_PORT
                && !ADDR_IS_EVEN_PORT (&range->min))
            skip = 1;
        else
            skip = 0;
        if (ports - skip < n_ports)
            continue;

        /* we found a range, remove from the list */
        priv->addresses = g_list_delete_link (priv->addresses, walk);
        /* now split and exit our loop */
        result = split_range (pool, range, 0, skip, n_ports);
        priv->allocated = g_list_prepend (priv->allocated, result);
        break;
    }
    g_mutex_unlock (&priv->lock);

    if (result) {
        addr = g_slice_new0 (GstRTSPAddress);
        addr->pool = g_object_ref (pool);
        addr->address = get_address_string (&result->min);
        addr->n_ports = n_ports;
        addr->port = result->min.port;
        addr->ttl = result->ttl;
        addr->priv = result;

        GST_DEBUG_OBJECT (pool, "got address %s:%u ttl %u", addr->address,
                          addr->port, addr->ttl);
    }

    return addr;
}
void add_and_search_test(uint_t n, size_t num_insert_threads, size_t num_search_threads, size_t insert_step, size_t search_step) {
    hash_set_t hash_set(64);
    steady_timer timer;

    std::cout << "add nums..." << std::endl;

    std::vector<range> insert_ranges = split_range(range(1, n), num_insert_threads);

    timer.reset();

    std::vector<std::thread> inserters;
    barrier start_inserts(num_insert_threads);
    for (size_t i = 0; i < num_insert_threads; ++i) {
        std::cout << i << "-th thread insert range: [" << insert_ranges[i].start << ", " << insert_ranges[i].end << "]" << std::endl;

        auto insert_nums_to_hash_set = [&hash_set, &start_inserts, insert_step](range insert_range) {
            uint_t u = get_start_num(insert_range, insert_step);

            start_inserts.enter();

            while (u <= insert_range.end) {
                hash_set.add(u);
                u += insert_step;
            }
        };

        inserters.emplace_back(insert_nums_to_hash_set, insert_ranges[i]);
    }

    for (auto& t : inserters) {
        t.join();
    }

    std::cout << "add completed: " << timer.seconds_elapsed() << " seconds" << std::endl;

    std::cout << "search nums..." << std::endl;

    std::vector<range> search_ranges = split_range(range(1, n), num_search_threads);

    timer.reset();

    barrier start_searches(num_search_threads);
    std::vector<std::future<uint_t>> sums_of_found_nums;
    for (size_t i = 0; i < num_search_threads; ++i) {
        std::cout << i << "-th thread search range: [" << search_ranges[i].start << ", " << search_ranges[i].end << "]" << std::endl;

        auto search_nums = [&hash_set, &start_searches, search_step](range search_range) -> uint_t {
            uint_t sum_of_found = 0;
            uint_t u = get_start_num(search_range, search_step);

            start_searches.enter();

            while (u <= search_range.end) {
                if (hash_set.contains(u)) {
                    sum_of_found += u;
                }
                u += search_step;
            }
            return sum_of_found;
        };

        sums_of_found_nums.push_back(std::async(search_nums, search_ranges[i]));
    }

    uint_t total_sum_of_found_nums = 0;
    for (auto& search_result : sums_of_found_nums) {
        total_sum_of_found_nums += search_result.get();
    }

    std::cout << "search completed: " << timer.seconds_elapsed() << " seconds" << std::endl;

    uint_t expected_sum = 0;
    for (uint_t u = search_step; u <= n; u += search_step) {
        if (u % insert_step == 0) {
            expected_sum += u;
        }
    }

    std::cout << "sum of nums found in hash set: " << total_sum_of_found_nums << std::endl;
    std::cout << "expected sum: " << expected_sum << std::endl;
}
/* Return a sorted list of available memory ranges. */
int get_memory_ranges(struct memory_range **range, int *ranges,
				unsigned long kexec_flags)
{
	const char *iomem = proc_iomem();
	char line[MAX_LINE];
	FILE *fp;
	fp = fopen(iomem, "r");
	if (!fp) {
		fprintf(stderr, "Cannot open %s: %s\n",
			iomem, strerror(errno));
		return -1;
	}

	/* allocate memory_range dynamically */
	max_memory_ranges = 0;
	while(fgets(line, sizeof(line), fp) != 0) {
		max_memory_ranges++;
	}
	memory_range = xmalloc(sizeof(struct memory_range) *
			max_memory_ranges);
	rewind(fp);

	while(fgets(line, sizeof(line), fp) != 0) {
		unsigned long start, end;
		char *str;
		unsigned type;
		int consumed;
		int count;
		if (memory_ranges >= max_memory_ranges)
			break;
		count = sscanf(line, "%lx-%lx : %n",
				&start, &end, &consumed);
		if (count != 2)
			continue;
		str = line + consumed;
		end = end + 1;
		if (memcmp(str, "System RAM\n", 11) == 0) {
			type = RANGE_RAM;
		}
		else if (memcmp(str, "reserved\n", 9) == 0) {
			type = RANGE_RESERVED;
		}
		else if (memcmp(str, "Crash kernel\n", 13) == 0) {
			/* Redefine the memory region boundaries if kernel
			 * exports the limits and if it is panic kernel.
			 * Override user values only if kernel exported
			 * values are subset of user defined values.
			 */

			if (kexec_flags & KEXEC_ON_CRASH) {
				if (start > mem_min)
					mem_min = start;
				if (end < mem_max)
					mem_max = end;
			}
			continue;
		} else if (memcmp(str, "Boot parameter\n", 14) == 0) {
			memory_ranges = split_range(memory_ranges, start, end);
			continue;
		} else if (memcmp(str, "EFI Memory Map\n", 14) == 0) {
			memory_ranges = split_range(memory_ranges, start, end);
			saved_efi_memmap_size = end - start;
			continue;
		} else if (memcmp(str, "Uncached RAM\n", 13) == 0) {
			type = RANGE_UNCACHED;
		} else {
			continue;
		}
		/*
		 * Check if this memory range can be coalesced with
		 * the previous range
		 */
		if ((memory_ranges > 0) &&
			(start == memory_range[memory_ranges-1].end) &&
			(type == memory_range[memory_ranges-1].type)) {
			memory_range[memory_ranges-1].end = end;
		}
		else {
			memory_range[memory_ranges].start = start;
			memory_range[memory_ranges].end = end;
			memory_range[memory_ranges].type = type;
			memory_ranges++;
		}
	}
	fclose(fp);
 	*range = memory_range;
 	*ranges = memory_ranges;

 	return 0;
}