57 *out_pages = (uint32_t)pages;
73 uint32_t pages_needed = 0;
74 size_t rounded_size = 0;
79 guint best_index = G_MAXUINT;
80 uint32_t best_length = UINT32_MAX;
85 if(
r->length >= pages_needed &&
r->length < best_length)
88 best_length =
r->length;
89 if(best_length == pages_needed)
break;
93 if(best_index == G_MAXUINT)
100 const uint32_t first =
r->start;
103 r->start += pages_needed;
104 r->length -= pages_needed;
108 g_array_remove_index(a->
free_runs, best_index);
118 if(
IS_NULL_PTR(VirtualAlloc(ptr, rounded_size, MEM_COMMIT, PAGE_READWRITE)))
120 const DWORD err = GetLastError();
121 fprintf(stderr,
"couldn't commit cache page range (VirtualAlloc error %lu)\n", (
unsigned long)err);
128 *out_size = rounded_size;
146 const uintptr_t base = (uintptr_t)a->
base;
147 const uintptr_t addr = (uintptr_t)ptr;
148 if(addr < base || addr >= base + a->
size)
150 fprintf(stderr,
"[pixelpipe] arena free: pointer out of range\n");
155 fprintf(stderr,
"[pixelpipe] arena free: pointer not page-aligned\n");
162 fprintf(stderr,
"[pixelpipe] arena free: invalid size\n");
166 const size_t first_sz = (addr - base) / a->
page_size;
169 fprintf(stderr,
"[pixelpipe] arena free: range out of bounds\n");
173 const uint32_t first = (uint32_t)first_sz;
179 while(i < a->free_runs->len &&
189 fprintf(stderr,
"[pixelpipe] arena free: overlap with previous run\n");
193 if(i < a->free_runs->len)
196 if(first + pages > next->
start)
199 fprintf(stderr,
"[pixelpipe] arena free: overlap with next run\n");
235 uint32_t *out_total_free_pages,
236 uint32_t *out_largest_free_run_pages)
238 if(out_total_free_pages) *out_total_free_pages = 0;
239 if(out_largest_free_run_pages) *out_largest_free_run_pages = 0;
244 uint32_t largest = 0;
249 if(
r->length > largest) largest =
r->length;
253 if(out_total_free_pages) *out_total_free_pages = total;
254 if(out_largest_free_run_pages) *out_largest_free_run_pages = largest;
271 VirtualFree(a->
base, 0, MEM_RELEASE);
287 const size_t page_size = 64 * 1024;
288 const size_t pages = total_size / page_size;
300 a->
base = (uint8_t *)VirtualAlloc(NULL, total_size,
305 const DWORD err = GetLastError();
306 fprintf(stderr,
"couldn't alloc map (VirtualAlloc error %lu)\n", (
unsigned long)err);
310 a->
base = mmap(NULL, total_size,
311 PROT_READ | PROT_WRITE,
312 MAP_PRIVATE | MAP_ANONYMOUS,
315 if(a->
base == MAP_FAILED)
318 fprintf(stderr,
"couldn't alloc map (mmap error %d: %s)\n", errno, strerror(errno));
323 a->
size = total_size;
331 VirtualFree(a->
base, 0, MEM_RELEASE);
339 fprintf(stderr,
"couldn't alloc free run list\n");
358 const uintptr_t base = (uintptr_t)a->
base;
359 const uintptr_t addr = (uintptr_t)ptr;
360 return addr >= base && addr < base + a->
size;
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
static int dt_pthread_mutex_unlock(dt_pthread_mutex_t *mutex) RELEASE(mutex) NO_THREAD_SAFETY_ANALYSIS
static int dt_pthread_mutex_init(dt_pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
static int dt_pthread_mutex_destroy(dt_pthread_mutex_t *mutex)
static int dt_pthread_mutex_lock(dt_pthread_mutex_t *mutex) ACQUIRE(mutex) NO_THREAD_SAFETY_ANALYSIS
void dt_cache_arena_stats(dt_cache_arena_t *a, uint32_t *out_total_free_pages, uint32_t *out_largest_free_run_pages)
void dt_cache_arena_cleanup(dt_cache_arena_t *a)
gboolean dt_cache_arena_ptr_in(const dt_cache_arena_t *a, const void *ptr)
gboolean dt_cache_arena_calc(const dt_cache_arena_t *a, size_t size, uint32_t *out_pages, size_t *out_size)
int dt_cache_arena_init(dt_cache_arena_t *a, size_t total_size)
void dt_cache_arena_free(dt_cache_arena_t *a, void *ptr, size_t size)
void * dt_cache_arena_alloc(dt_cache_arena_t *a, size_t size, size_t *out_size)