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);
112 *out_size = rounded_size;
130 const uintptr_t base = (uintptr_t)a->
base;
131 const uintptr_t addr = (uintptr_t)ptr;
132 if(addr < base || addr >= base + a->
size)
134 fprintf(stderr,
"[pixelpipe] arena free: pointer out of range\n");
139 fprintf(stderr,
"[pixelpipe] arena free: pointer not page-aligned\n");
146 fprintf(stderr,
"[pixelpipe] arena free: invalid size\n");
150 const size_t first_sz = (addr - base) / a->
page_size;
153 fprintf(stderr,
"[pixelpipe] arena free: range out of bounds\n");
157 const uint32_t first = (uint32_t)first_sz;
163 while(i < a->free_runs->len &&
173 fprintf(stderr,
"[pixelpipe] arena free: overlap with previous run\n");
177 if(i < a->free_runs->len)
180 if(first + pages > next->
start)
183 fprintf(stderr,
"[pixelpipe] arena free: overlap with next run\n");
219 uint32_t *out_total_free_pages,
220 uint32_t *out_largest_free_run_pages)
222 if(out_total_free_pages) *out_total_free_pages = 0;
223 if(out_largest_free_run_pages) *out_largest_free_run_pages = 0;
228 uint32_t largest = 0;
233 if(
r->length > largest) largest =
r->length;
237 if(out_total_free_pages) *out_total_free_pages = total;
238 if(out_largest_free_run_pages) *out_largest_free_run_pages = largest;
255 VirtualFree(a->
base, 0, MEM_RELEASE);
271 const size_t page_size = 64 * 1024;
272 const size_t pages = total_size / page_size;
275 a->
base = (uint8_t *)VirtualAlloc(NULL, total_size,
276 MEM_RESERVE | MEM_COMMIT,
280 const DWORD err = GetLastError();
281 fprintf(stderr,
"couldn't alloc map (VirtualAlloc error %lu)\n", (
unsigned long)err);
285 a->
base = mmap(NULL, total_size,
286 PROT_READ | PROT_WRITE,
287 MAP_PRIVATE | MAP_ANONYMOUS,
290 if(a->
base == MAP_FAILED)
293 fprintf(stderr,
"couldn't alloc map (mmap error %d: %s)\n", errno, strerror(errno));
298 a->
size = total_size;
306 VirtualFree(a->
base, 0, MEM_RELEASE);
314 fprintf(stderr,
"couldn't alloc free run list\n");
333 const uintptr_t base = (uintptr_t)a->
base;
334 const uintptr_t addr = (uintptr_t)ptr;
335 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)