parent
93f93a594e
commit
56a4357b20
@ -1,117 +0,0 @@ |
|||||||
#define _POSIX_C_SOURCE 200809l |
|
||||||
#define _GNU_SOURCE |
|
||||||
|
|
||||||
#include <stdlib.h> |
|
||||||
#include <stdio.h> |
|
||||||
#include <stdint.h> |
|
||||||
#include <string.h> |
|
||||||
|
|
||||||
#include "cache.h" |
|
||||||
#include "hash.h" |
|
||||||
#include "font.h" |
|
||||||
#include "util.h" |
|
||||||
|
|
||||||
|
|
||||||
static struct hm_ref *hash_table; |
|
||||||
static struct font_glyph cache_array[CACHE_SIZE] = {0}; |
|
||||||
|
|
||||||
// bitmap size is aligned to word
|
|
||||||
// 2^6 == 64 bits, number of bits in a uint64_t
|
|
||||||
#define _BSIZE (((CACHE_SIZE+0x3f)&(~0x3f))>>6) |
|
||||||
static uint64_t bitmap[_BSIZE] = {0}; |
|
||||||
|
|
||||||
// bitmap operations
|
|
||||||
#define B_RESET() for (int i = 0; i < _BSIZE; bitmap[i++] = 0); |
|
||||||
#define B_SET(x) bitmap[(x)>>6] |= (uint64_t)1<<((x)%64) |
|
||||||
#define B_TEST(x) (bitmap[(x)>>6]&((uint64_t)1<<((x)%64))) |
|
||||||
|
|
||||||
// reset the bitmap every n cycles
|
|
||||||
#define NCYCLES (CACHE_SIZE/2) |
|
||||||
static int cycles = 0; |
|
||||||
|
|
||||||
|
|
||||||
static inline void set_bit(unsigned int x) |
|
||||||
{ |
|
||||||
// printf("cycles: %d, set: %d\n", cycles, x);
|
|
||||||
cycles = (cycles+1)%NCYCLES; |
|
||||||
if (!cycles) B_RESET(); |
|
||||||
B_SET(x); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void cache_init(void) |
|
||||||
{ |
|
||||||
hash_table = hm_create(CACHE_SIZE); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
void cache_destroy(void) |
|
||||||
{ |
|
||||||
hm_destroy(hash_table); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
const struct font_glyph * cache_search(unsigned int code) |
|
||||||
{ |
|
||||||
struct hm_entry *r = hm_search(hash_table, code); |
|
||||||
|
|
||||||
// miss
|
|
||||||
if (!r) |
|
||||||
return NULL; |
|
||||||
|
|
||||||
// hit
|
|
||||||
set_bit((struct font_glyph *)(r->data)-cache_array); |
|
||||||
return (struct font_glyph *)(r->data); |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// return the first free spot into the cache
|
|
||||||
unsigned int cache_get(void) |
|
||||||
{ |
|
||||||
uint32_t x = 0; |
|
||||||
// find an open spot in the cache
|
|
||||||
for (int b = 0; b < _BSIZE; b++) { |
|
||||||
if (bitmap[b] == 0) x = 64; |
|
||||||
else x = __builtin_clzll(bitmap[b]); |
|
||||||
x = 64-x; |
|
||||||
if (!B_TEST(x+64*b)) |
|
||||||
return x+64*b; |
|
||||||
} |
|
||||||
return 0; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
// inserts the font glyph into the cache
|
|
||||||
const struct font_glyph * cache_insert(const struct font_glyph *g, unsigned int x) |
|
||||||
{ |
|
||||||
struct font_glyph *spot = NULL; |
|
||||||
|
|
||||||
// allocation in cache failed
|
|
||||||
if (B_TEST(x)) |
|
||||||
return NULL; |
|
||||||
|
|
||||||
set_bit(x); |
|
||||||
spot = &cache_array[x]; |
|
||||||
*spot = *g; |
|
||||||
|
|
||||||
/*
|
|
||||||
for (int i = 0; i < _BSIZE; i++) { |
|
||||||
//print_byte(bitmap[i]);
|
|
||||||
//print_byte(bitmap[i]>>8);
|
|
||||||
//print_byte(bitmap[i]>>16);
|
|
||||||
//print_byte(bitmap[i]>>24);
|
|
||||||
//print_byte(bitmap[i]>>32);
|
|
||||||
//print_byte(bitmap[i]>>40);
|
|
||||||
//print_byte(bitmap[i]>>48);
|
|
||||||
//print_byte(bitmap[i]>>56);
|
|
||||||
printf("%lx", bitmap[i]); |
|
||||||
} |
|
||||||
printf("\n"); |
|
||||||
*/ |
|
||||||
|
|
||||||
struct hm_entry e = { .code = g->codepoint, .data = spot}; |
|
||||||
if (!hm_insert(hash_table, &e)) |
|
||||||
return NULL; |
|
||||||
|
|
||||||
return spot; |
|
||||||
} |
|
@ -1,13 +0,0 @@ |
|||||||
#ifndef _CACHE_H |
|
||||||
#define _CACHE_H |
|
||||||
|
|
||||||
#define CACHE_SIZE 512 |
|
||||||
|
|
||||||
void cache_init(void); |
|
||||||
void cache_destroy(void); |
|
||||||
const struct font_glyph * cache_search(unsigned int code); |
|
||||||
unsigned int cache_get(void); |
|
||||||
const struct font_glyph * cache_insert(const struct font_glyph *g, unsigned int idx); |
|
||||||
|
|
||||||
|
|
||||||
#endif |
|
@ -0,0 +1,100 @@ |
|||||||
|
#ifndef CACHE_GENERIC_H |
||||||
|
#define CACHE_GENERIC_H |
||||||
|
|
||||||
|
|
||||||
|
#include "hash.h" |
||||||
|
|
||||||
|
#define CACHE_SIZE 512 |
||||||
|
#define CACHE_NCYCLES (CACHE_SIZE/2) |
||||||
|
#define CACHE_BSIZE (((CACHE_SIZE+0x3f)&(~0x3f))>>6) |
||||||
|
#define CACHE_BRESET(b) for (int i = 0; i < CACHE_BSIZE; b[i++] = 0); |
||||||
|
#define CACHE_BSET(b, x) b[(x)>>6] |= (uint64_t)1<<((x)%64) |
||||||
|
#define CACHE_BTEST(b, x) (b[(x)>>6]&((uint64_t)1<<((x)%64))) |
||||||
|
|
||||||
|
#define CACHE_SET(c, x) \ |
||||||
|
{ \
|
||||||
|
c->cycles = (c->cycles+1)%CACHE_NCYCLES; \
|
||||||
|
if (!c->cycles) CACHE_BRESET(c->bitmap); \
|
||||||
|
CACHE_BSET(c->bitmap, x); \
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
#define CACHE_DECL(cachename, type) \ |
||||||
|
struct cachename { \
|
||||||
|
struct hm_ref *table; \
|
||||||
|
type *array; \
|
||||||
|
uint64_t *bitmap; \
|
||||||
|
int cycles; \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
\
|
||||||
|
struct cachename cachename##_init(void) \
|
||||||
|
{ \
|
||||||
|
struct hm_ref *t = hm_create(CACHE_SIZE); \
|
||||||
|
type *a = malloc(sizeof(type)*CACHE_SIZE); \
|
||||||
|
uint64_t *b = malloc(sizeof(uint64_t)*CACHE_BSIZE); \
|
||||||
|
CACHE_BRESET(b); \
|
||||||
|
return (struct cachename){ .table = t, .array = a, .bitmap = b, 0}; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
\
|
||||||
|
void cachename##_free(struct cachename *cache) \
|
||||||
|
{ \
|
||||||
|
if (cache) { \
|
||||||
|
hm_destroy(cache->table); \
|
||||||
|
free(cache->array); \
|
||||||
|
free(cache->bitmap); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
\
|
||||||
|
const type * cachename##_search(struct cachename *cache, unsigned int code) \
|
||||||
|
{ \
|
||||||
|
if (!cache) \
|
||||||
|
return NULL; \
|
||||||
|
struct hm_entry *r = hm_search(cache->table, code); \
|
||||||
|
/* MISS */ \
|
||||||
|
if (!r) \
|
||||||
|
return NULL; \
|
||||||
|
/* HIT */ \
|
||||||
|
CACHE_SET(cache, (type *)(r->data)-cache->array); \
|
||||||
|
return (const type *)(r->data); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
\
|
||||||
|
int cachename##_get(struct cachename *cache) \
|
||||||
|
{ \
|
||||||
|
if (!cache) \
|
||||||
|
return -1; \
|
||||||
|
int x = 0; \
|
||||||
|
for (int b = 0; b < CACHE_BSIZE; b++) { \
|
||||||
|
if (cache->bitmap[b] == 0) x = 64; \
|
||||||
|
else x = __builtin_clzll(cache->bitmap[b]); \
|
||||||
|
x = 64-x; \
|
||||||
|
if (!CACHE_BTEST(cache->bitmap, x+64*b)) \
|
||||||
|
return x+64*b; \
|
||||||
|
} \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
\
|
||||||
|
const type * cachename##_insert(struct cachename *cache, const type *g, unsigned int code, int x) \
|
||||||
|
{ \
|
||||||
|
if (!cache) \
|
||||||
|
return NULL; \
|
||||||
|
type *spot = NULL; \
|
||||||
|
/* x is the index to the cache array, it has to come from the user */ \
|
||||||
|
/* check if the spot is free */ \
|
||||||
|
if (x < 0 || CACHE_BTEST(cache->bitmap, x)) \
|
||||||
|
return NULL; \
|
||||||
|
CACHE_SET(cache, x) \
|
||||||
|
spot = &(cache->array[x]); \
|
||||||
|
*spot = *g; \
|
||||||
|
struct hm_entry e = { .code = code, .data = spot}; \
|
||||||
|
if (!hm_insert(cache->table, &e)) \
|
||||||
|
return NULL; \
|
||||||
|
return spot; \
|
||||||
|
} \
|
||||||
|
|
||||||
|
|
||||||
|
#endif |
Loading…
Reference in new issue