/* Add a chunk to the free list */ staticvoid
free_blocks (cairo_mempool_t *pool,
size_t first,
size_t last,
cairo_bool_t clear)
{
size_t i, len; int bits = 0;
for (i = first, len = 1; i < last; i += len) { /* To avoid cost quadratic in the number of different *blocksproducedfromthischunkofstore,wehaveto *usethesizeofthepreviousblockproducedfromthis *chunkasthestartingpointtoworkoutthesizeofthe *nextblockwecanproduce.Ifyoulookatthebinary *representationofthestartingpointsoftheblocks *produced,youcanseethatyoufirstofallincreasethe *sizeoftheblocksproduceduptosomemaximumasthe *addressdealtwithgetsoffsetsaddedonwhichzapout *loworderbits,thendecreaseastheloworderbitsofthe *finalblockproducedgetaddedin.E.g.asyougofrom *001to0111yougenerateblocks *ofsize001at001takingyouto010 *ofsize010at010takingyouto100 *ofsize010at100takingyouto110 *ofsize001at110takingyouto111 *Sothemaximumtotalcostoftheloopsbelowthiscomment *isonetripfromthelowestblocksizetothehighestand *backagain.
*/ while (bits < pool->num_sizes - 1) {
size_t next_bits = bits + 1;
size_t next_len = len << 1;
if (i + next_bits > last) { /* off end of chunk to be freed */ break;
}
if (i & (next_len - 1)) /* block would not be on boundary */ break;
bits = next_bits;
len = next_len;
}
do { if (i + len <= last && /* off end of chunk to be freed */
(i & (len - 1)) == 0) /* block would not be on boundary */ break;
if (BITTEST (pool, offset + (((size_t) 1) << bits) - 1)) return NULL; /* buddy is allocated */
block = pool->blocks + offset; if (block->bits != bits) return NULL; /* buddy is partially allocated */
return block;
}
staticvoid
merge_buddies (cairo_mempool_t *pool, struct _cairo_memblock *block, int max_bits)
{
size_t block_offset = block - pool->blocks; int bits = block->bits;
while (bits < max_bits - 1) { /* while you can, merge two blocks and get a legal block size */
size_t buddy_offset = block_offset ^ (((size_t) 1) << bits);
if (bits > pool->max_free_bits)
pool->max_free_bits = bits;
}
/* attempt to merge all available buddies up to a particular size */ staticint
merge_bits (cairo_mempool_t *pool, int max_bits)
{ struct _cairo_memblock *block, *buddy, *next; int bits;
/* Find a list with blocks big enough on it */
block = NULL; for (b = bits; b <= pool->max_free_bits; b++) { if (! cairo_list_is_empty (&pool->free[b])) {
block = cairo_list_first_entry (&pool->free[b], struct _cairo_memblock,
link); break;
}
}
assert (block != NULL);
cairo_list_del (&block->link);
while (cairo_list_is_empty (&pool->free[pool->max_free_bits])) { if (--pool->max_free_bits == -1) break;
}
/* Mark end of allocated area */
offset = block - pool->blocks;
past = offset + (((size_t) 1) << bits);
BITSET (pool, past - 1);
block->bits = bits;
/* If we used a larger free block than we needed, free the rest */
pool->free_bytes -= ((size_t) 1) << (b + pool->min_bits);
free_blocks (pool, past, offset + (((size_t) 1) << b), 0);
cairo_status_t
_cairo_mempool_init (cairo_mempool_t *pool, void *base, size_t bytes, int min_bits, int num_sizes)
{
uintptr_t tmp; int num_blocks; int i;
/* Align the start to an integral chunk */
tmp = ((uintptr_t) base) & ((((size_t) 1) << min_bits) - 1); if (tmp) {
tmp = (((size_t) 1) << min_bits) - tmp;
base = (char *)base + tmp;
bytes -= tmp;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.