1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
|
/*
* Copyright 2008-2009 Katholieke Universiteit Leuven
*
* Use of this software is governed by the MIT license
*
* Written by Sven Verdoolaege, K.U.Leuven, Departement
* Computerwetenschappen, Celestijnenlaan 200A, B-3001 Leuven, Belgium
*/
#include <isl_blk.h>
#include <isl_ctx_private.h>
/* The maximal number of cache misses before first element is evicted */
#define ISL_BLK_MAX_MISS 100
struct isl_blk isl_blk_empty()
{
struct isl_blk block;
block.size = 0;
block.data = NULL;
return block;
}
static int isl_blk_is_empty(struct isl_blk block)
{
return block.size == 0 && block.data == NULL;
}
static struct isl_blk isl_blk_error()
{
struct isl_blk block;
block.size = -1;
block.data = NULL;
return block;
}
int isl_blk_is_error(struct isl_blk block)
{
return block.size == -1 && block.data == NULL;
}
static void isl_blk_free_force(struct isl_ctx *ctx, struct isl_blk block)
{
int i;
for (i = 0; i < block.size; ++i)
isl_int_clear(block.data[i]);
free(block.data);
}
static struct isl_blk extend(struct isl_ctx *ctx, struct isl_blk block,
size_t new_n)
{
int i;
isl_int *p;
if (block.size >= new_n)
return block;
p = isl_realloc_array(ctx, block.data, isl_int, new_n);
if (!p) {
isl_blk_free_force(ctx, block);
return isl_blk_error();
}
block.data = p;
for (i = block.size; i < new_n; ++i)
isl_int_init(block.data[i]);
block.size = new_n;
return block;
}
struct isl_blk isl_blk_alloc(struct isl_ctx *ctx, size_t n)
{
int i;
struct isl_blk block;
block = isl_blk_empty();
if (n && ctx->n_cached) {
int best = 0;
for (i = 1; ctx->cache[best].size != n && i < ctx->n_cached; ++i) {
if (ctx->cache[best].size < n) {
if (ctx->cache[i].size > ctx->cache[best].size)
best = i;
} else if (ctx->cache[i].size >= n &&
ctx->cache[i].size < ctx->cache[best].size)
best = i;
}
if (ctx->cache[best].size < 2 * n + 100) {
block = ctx->cache[best];
if (--ctx->n_cached != best)
ctx->cache[best] = ctx->cache[ctx->n_cached];
if (best == 0)
ctx->n_miss = 0;
} else if (ctx->n_miss++ >= ISL_BLK_MAX_MISS) {
isl_blk_free_force(ctx, ctx->cache[0]);
if (--ctx->n_cached != 0)
ctx->cache[0] = ctx->cache[ctx->n_cached];
ctx->n_miss = 0;
}
}
return extend(ctx, block, n);
}
struct isl_blk isl_blk_extend(struct isl_ctx *ctx, struct isl_blk block,
size_t new_n)
{
if (isl_blk_is_empty(block))
return isl_blk_alloc(ctx, new_n);
return extend(ctx, block, new_n);
}
void isl_blk_free(struct isl_ctx *ctx, struct isl_blk block)
{
if (isl_blk_is_empty(block) || isl_blk_is_error(block))
return;
if (ctx->n_cached < ISL_BLK_CACHE_SIZE)
ctx->cache[ctx->n_cached++] = block;
else
isl_blk_free_force(ctx, block);
}
void isl_blk_clear_cache(struct isl_ctx *ctx)
{
int i;
for (i = 0; i < ctx->n_cached; ++i)
isl_blk_free_force(ctx, ctx->cache[i]);
ctx->n_cached = 0;
}
|