Exemplo n.º 1
0
/*
 * 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;
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
/*
 * 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;
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
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;
}
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
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);
}
Exemplo n.º 10
0
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));
}
Exemplo n.º 11
0
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);
}
Exemplo n.º 12
0
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;
	}