/* * pgstrom_program_cache_reclaim * * it tries to reclaim the shared memory if highly memory presure. */ static bool pgstrom_program_cache_reclaim(int shift_min) { program_cache_entry *entry; while (!dlist_is_empty(&pgcache_head->lru_list)) { dlist_node *dnode = dlist_tail_node(&pgcache_head->lru_list); int shift; entry = dlist_container(program_cache_entry, lru_chain, dnode); PGCACHE_CHECK_ACTIVE(entry); /* remove from the list not to be reclaimed again */ dlist_delete(&entry->hash_chain); dlist_delete(&entry->lru_chain); memset(&entry->hash_chain, 0, sizeof(dlist_node)); memset(&entry->lru_chain, 0, sizeof(dlist_node)); if (--entry->refcnt == 0) { pgstrom_program_cache_free(entry); /* check whether the required size is allocatable */ for (shift = shift_min; shift <= PGCACHE_MAX_BITS; shift++) { if (!dlist_is_empty(&pgcache_head->free_list[shift])) return true; } } } return false; }
static program_cache_entry * pgstrom_program_cache_alloc(Size required) { program_cache_entry *entry; dlist_node *dnode; Size total_size; int shift; total_size = offsetof(program_cache_entry, data[0]) + MAXALIGN(required) + PGCACHE_MIN_ERRORMSG_BUFSIZE + sizeof(cl_uint); /* required size too large? */ if (total_size > (1UL << PGCACHE_MAX_BITS)) return NULL; shift = get_next_log2(total_size); if (shift < PGCACHE_MIN_BITS) shift = PGCACHE_MIN_BITS; if (dlist_is_empty(&pgcache_head->free_list[shift])) { /* * If no entries are free in the suitable class, * we try to split larger blocks first, then try * to reclaim entries according to LRU. * If both of them make no sense, we give up! */ while (!pgstrom_program_cache_split(shift + 1)) { if (!pgstrom_program_cache_reclaim(shift)) return NULL; } } Assert(!dlist_is_empty(&pgcache_head->free_list[shift])); dnode = dlist_pop_head_node(&pgcache_head->free_list[shift]); entry = dlist_container(program_cache_entry, hash_chain, dnode); Assert(entry->shift == shift); memset(entry, 0, sizeof(program_cache_entry)); entry->shift = shift; entry->refcnt = 1; PGCACHE_MAGIC_CODE(entry) = PGCACHE_MAGIC; return entry; }
void test_dlist_prepend_to_empty(void) { unsigned long *val = NULL; assert_true(test_dlist == NULL); test_dlist = dlist_create(); assert_true(test_dlist != NULL); assert_true(dlist_is_empty(test_dlist)); val = make_ulong_ptr(9999); assert_true(val != NULL); assert_true(dlist_prepend(test_dlist, val) == 0); /* Verify */ val = NULL; val = dlist_index(test_dlist, 0); assert_true(val != NULL); assert_ulong_equal(9999, *val); assert_true(dlist_size(test_dlist) == 1); dlist_free_all(test_dlist, NULL); test_dlist = NULL; }
void test_dlist_create(void) { test_dlist = dlist_create(); assert_true(test_dlist != NULL); assert_true(dlist_size(test_dlist) == 0); assert_true(dlist_is_empty(test_dlist)); dlist_free(test_dlist); test_dlist = NULL; }
/* * pgstrom_program_cache_* * * a simple buddy memory allocation on the shared memory segment. */ static bool pgstrom_program_cache_split(int shift) { program_cache_entry *entry; dlist_node *dnode; Assert(shift > PGCACHE_MIN_BITS && shift <= PGCACHE_MAX_BITS); if (dlist_is_empty(&pgcache_head->free_list[shift])) { if (shift == PGCACHE_MAX_BITS || !pgstrom_program_cache_split(shift + 1)) return false; } Assert(!dlist_is_empty(&pgcache_head->free_list[shift])); dnode = dlist_pop_head_node(&pgcache_head->free_list[shift]); entry = dlist_container(program_cache_entry, hash_chain, dnode); Assert(entry->shift == shift); Assert((((uintptr_t)entry - (uintptr_t)pgcache_head->entry_begin) & ((1UL << shift) - 1)) == 0); shift--; /* earlier half */ memset(entry, 0, offsetof(program_cache_entry, data[0])); entry->shift = shift; entry->refcnt = 0; PGCACHE_MAGIC_CODE(entry) = PGCACHE_MAGIC; dlist_push_tail(&pgcache_head->free_list[shift], &entry->hash_chain); /* later half */ entry = (program_cache_entry *)((char *)entry + (1UL << shift)); memset(entry, 0, offsetof(program_cache_entry, data[0])); entry->shift = shift; entry->refcnt = 0; PGCACHE_MAGIC_CODE(entry) = PGCACHE_MAGIC; dlist_push_tail(&pgcache_head->free_list[shift], &entry->hash_chain); return true; }
void test_dlist_mergesort_empty(void) { assert_true(test_dlist == NULL); test_dlist = dlist_create(); assert_true(test_dlist != NULL); assert_true(dlist_is_empty(test_dlist)); assert_true(dlist_mergesort(test_dlist, (CompareFn)ulong_compare) == 0); dlist_free_all(test_dlist, NULL); test_dlist = NULL; }
void test_dlist_reverse_empty(void) { assert_true(test_dlist == NULL); test_dlist = dlist_create(); assert_true(test_dlist != NULL); assert_true(dlist_is_empty(test_dlist)); assert_true(dlist_reverse(test_dlist) == 0); dlist_free_all(test_dlist, NULL); test_dlist = NULL; }
void test_dlist_remove_data_from_empty(void) { assert_true(test_dlist == NULL); test_dlist = dlist_create(); assert_true(test_dlist != NULL); assert_true(dlist_is_empty(test_dlist)); assert_true(dlist_remove_data(test_dlist, NULL) == -1); dlist_free_all(test_dlist, NULL); test_dlist = NULL; }
void test_dlist_mergesort_existing(void) { unsigned long old_size; /* DListIterator *it; */ assert_true(test_dlist != NULL); assert_false(dlist_is_empty(test_dlist)); old_size = dlist_size(test_dlist); assert_true(dlist_mergesort(test_dlist, (CompareFn)ulong_compare) == 0); /* Verify */ assert_true(dlist_is_sorted(test_dlist, (CompareFn)ulong_compare)); assert_true(dlist_size(test_dlist) == old_size); }
void test_dlist_remove_data_from_existing_until_empty(void) { unsigned long *val; unsigned long i; val = NULL; i = dlist_size(test_dlist); while(i > 0) { val = dlist_index(test_dlist, --i); assert_true(val != NULL); assert_true(dlist_remove_data(test_dlist, val) == 0); assert_true(i == dlist_size(test_dlist)); } assert_true(dlist_is_empty(test_dlist)); }
void dlist_setup_ints_random(void) { unsigned long i, *val; test_dlist = dlist_create(); assert_true(test_dlist != NULL); assert_true(dlist_is_empty(test_dlist)); for(i = 0; i < 1000; i++) { val = make_ulong_ptr(rand() % 10000); if(val != NULL) { dlist_append(test_dlist, val); } } assert_true(dlist_size(test_dlist) == 1000); }
static int map_range_merge_( const struct map_t_ *const maps, struct dlist_entry_t *clusters, struct dlist_entry_t *ranges) { while (!dlist_is_empty(ranges)) { struct map_range_t_ *next_range = dlist_entry( ranges->next, struct map_range_t_, list); struct map_cluster_t_ *last_cluster = dlist_is_empty(clusters) ? NULL : dlist_entry(clusters->prev, struct map_cluster_t_, list); struct map_range_t_ *last_clustered = (last_cluster == NULL) ? NULL : dlist_entry( last_cluster->ranges.prev, struct map_range_t_, list); if ( dlist_is_empty(clusters) || map_range_is_large_equal_(next_range) || !map_range_can_be_merged_(maps, last_cluster, next_range)) { if ((last_cluster = malloc(sizeof(*last_cluster))) == NULL) { return -1; } last_cluster->illegal_code = ILLEGAL_NOT_SET; last_cluster->illegal_code_width = 0; dlist_init(&last_cluster->ranges); dlist_init(&last_cluster->list); dlist_insert_before(clusters, &last_cluster->list); } dlist_remove(&next_range->list); dlist_insert_before(&last_cluster->ranges, &next_range->list); if (last_clustered != NULL) { /* do not decrease code widths with merged range */ if (next_range->to_code_width < last_clustered->to_code_width) { next_range->to_code_width = last_clustered->to_code_width; } if (next_range->from_code_width < last_clustered->from_code_width) { next_range->from_code_width = last_clustered->from_code_width; } } } /* find the maximum code width for a whole cluster */ struct map_cluster_t_ *c; dlist_foreach_entry(c, struct map_cluster_t_, list, clusters) { int to_code_width = 0; struct map_range_t_ *r; dlist_foreach_entry(r, struct map_range_t_, list, &c->ranges) { if (to_code_width < r->to_code_width) { to_code_width = r->to_code_width; } } dlist_foreach_entry(r, struct map_range_t_, list, &c->ranges) { r->to_code_width = to_code_width; } c->illegal_code_width = to_code_width; }