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; }
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; }