infix
A JIT-Powered FFI Library for C
Loading...
Searching...
No Matches
cache.c
Go to the documentation of this file.
1
20#include <stdlib.h>
21#include <string.h>
22
24#define CACHE_BUCKETS 1021
25
31#define CACHE_MAX_ENTRIES INFIX_CACHE_MAX_ENTRIES
32
40
48static size_t g_cache_count = 0;
51
56static void _cache_lru_unlink(_cache_entry_t * entry) {
57 if (entry->lru_prev)
58 entry->lru_prev->lru_next = entry->lru_next;
59 else
61 if (entry->lru_next)
62 entry->lru_next->lru_prev = entry->lru_prev;
63 else
65 entry->lru_prev = nullptr;
66 entry->lru_next = nullptr;
67}
68
74 entry->lru_prev = nullptr;
78 g_cache_lru_head = entry;
79 if (g_cache_lru_tail == nullptr)
80 g_cache_lru_tail = entry;
81}
82
87static uint64_t _cache_hash(const char * sig, void * target_fn, bool is_safe) {
88 uint64_t h = 5381;
89 int c;
90 while ((c = *sig++))
91 h = ((h << 5) + h) + c;
92 h ^= (uint64_t)(uintptr_t)target_fn;
93 if (is_safe)
94 h ^= 0x123456789ABCDEF0ULL;
95 return h;
96}
97
103infix_forward_t * _infix_cache_lookup(const char * signature, void * target_fn, bool is_safe) {
104 uint64_t h = _cache_hash(signature, target_fn, is_safe);
105 size_t index = h % CACHE_BUCKETS;
106
108 for (_cache_entry_t * entry = g_trampoline_cache[index]; entry; entry = entry->next) {
109 if (entry->trampoline->target_fn == target_fn && entry->trampoline->is_safe == is_safe &&
110 strcmp(entry->trampoline->signature, signature) == 0) {
111 // Cache hit: promote the entry to the MRU end of the LRU list.
112 _cache_lru_unlink(entry);
114 entry->trampoline->ref_count++;
116 return entry->trampoline;
117 }
118 }
120 return NULL;
121}
122
128
138 size_t index = h % CACHE_BUCKETS;
139
141 // Double check it's not already there
142 for (_cache_entry_t * entry = g_trampoline_cache[index]; entry; entry = entry->next) {
143 if (entry->trampoline->target_fn == trampoline->target_fn &&
144 entry->trampoline->is_safe == trampoline->is_safe &&
145 strcmp(entry->trampoline->signature, trampoline->signature) == 0) {
147 return;
148 }
149 }
150
151 _cache_entry_t * entry = infix_malloc(sizeof(_cache_entry_t));
152 if (!entry) {
154 return;
155 }
156
157 entry->trampoline = trampoline;
158 trampoline->ref_count++; // Cache reference
159 entry->next = g_trampoline_cache[index];
160 entry->lru_prev = nullptr;
161 entry->lru_next = nullptr;
162 g_trampoline_cache[index] = entry;
165
166 // Evict least-recently-used entries until the cache is back within its bound.
169 // The victim is guaranteed to be in the hash table; if not, bail out to
170 // avoid spinning on an inconsistent LRU list.
171 if (!_cache_remove_no_lock(victim))
172 break;
173 if (victim->ref_count == 0)
175 }
177}
178
185 for (size_t i = 0; i < CACHE_BUCKETS; ++i) {
187 while (entry) {
188 _cache_entry_t * next = entry->next;
189 if (--entry->trampoline->ref_count == 0)
191 infix_free(entry);
192 entry = next;
193 }
194 g_trampoline_cache[i] = nullptr;
195 }
196 g_cache_lru_head = nullptr;
197 g_cache_lru_tail = nullptr;
198 g_cache_count = 0;
200}
201
206size_t _infix_cache_count(void) {
208 size_t count = g_cache_count;
210 return count;
211}
212
221 if (!trampoline->signature)
222 return false;
224 size_t index = h % CACHE_BUCKETS;
225
227 while (*p) {
228 if ((*p)->trampoline == trampoline) {
229 _cache_entry_t * to_free = *p;
230 *p = to_free->next;
231 _cache_lru_unlink(to_free);
233 infix_free(to_free);
234 trampoline->ref_count--; // Decrement since cache no longer holds it
235 return true;
236 }
237 p = &((*p)->next);
238 }
239 return false;
240}
241
253
259 if (!trampoline)
260 return;
261
263 if (--trampoline->ref_count > 0) {
265 return;
266 }
267
268 // Reference count is 0. Remove from cache and destroy.
271
273}
char * p
Definition 904_registry_benchmark.c:25
#define CACHE_MAX_ENTRIES
Definition cache.c:31
void _infix_cache_release(infix_forward_t *trampoline)
Definition cache.c:258
static size_t g_cache_count
Definition cache.c:48
static bool _cache_remove_no_lock(infix_forward_t *trampoline)
Definition cache.c:220
static infix_mutex_t g_cache_mutex
Definition cache.c:50
static _cache_entry_t * g_cache_lru_tail
Definition cache.c:46
#define CACHE_BUCKETS
Definition cache.c:24
void _infix_cache_clear(void)
Definition cache.c:183
static void _cache_lru_push_front(_cache_entry_t *entry)
Definition cache.c:73
static _cache_entry_t * g_cache_lru_head
Definition cache.c:44
bool _infix_cache_remove(infix_forward_t *trampoline)
Definition cache.c:247
static void _cache_lru_unlink(_cache_entry_t *entry)
Definition cache.c:56
static _cache_entry_t * g_trampoline_cache[CACHE_BUCKETS]
Definition cache.c:42
static uint64_t _cache_hash(const char *sig, void *target_fn, bool is_safe)
Definition cache.c:87
infix_forward_t * _infix_cache_lookup(const char *signature, void *target_fn, bool is_safe)
Definition cache.c:103
size_t _infix_cache_count(void)
Definition cache.c:206
void _infix_cache_insert(infix_forward_t *trampoline)
Definition cache.c:136
#define infix_free(ptr)
A macro that can be defined to override infix's allocator at compile time.
Definition infix.h:435
#define infix_malloc(n)
A macro that can be defined to override infix's allocator at compile time.
Definition infix.h:423
Internal data structures, function prototypes, and constants.
pthread_mutex_t infix_mutex_t
Definition infix_internals.h:161
#define INFIX_MUTEX_INITIALIZER
Definition infix_internals.h:162
#define INFIX_MUTEX_UNLOCK(m)
Definition infix_internals.h:164
INFIX_INTERNAL void _infix_forward_destroy_internal(infix_forward_t *trampoline)
Definition trampoline.c:712
#define INFIX_MUTEX_LOCK(m)
Definition infix_internals.h:163
Definition cache.c:34
struct _cache_entry_t * lru_prev
Definition cache.c:37
infix_forward_t * trampoline
Definition cache.c:35
struct _cache_entry_t * next
Definition cache.c:36
struct _cache_entry_t * lru_next
Definition cache.c:38
Internal definition of a forward trampoline handle.
Definition infix_internals.h:90
void * target_fn
Definition infix_internals.h:99
size_t ref_count
Definition infix_internals.h:102
bool is_safe
Definition infix_internals.h:101
char * signature
Definition infix_internals.h:103