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