Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
test_pipe_cache_alloc_refusals.c
Go to the documentation of this file.
1/*
2 This file is part of Ansel,
3 Copyright (C) 2026 Guillaume Stutin.
4
5 Ansel is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Ansel is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17*/
18
30#include "system/macros.h"
31
32#include <glib.h>
33#include <stdarg.h>
34#include <stddef.h>
35// cmocka.h declares `extern jmp_buf global_expect_assert_env' at file scope without including
36// <setjmp.h> itself. Same suppression as test_metadata_notify.c, and for the same reason.
37#include <setjmp.h> // NOLINT(misc-include-cleaner)
38#include <stdint.h>
39#include <cmocka.h>
40
41#ifdef _WIN32
42#include "win/main_wrapper.h"
43#endif
44
45#define MIB ((size_t)1024 * 1024)
46#define CACHE_BYTES (64 * MIB)
47#define HASH_HELD 0x0A0A0A0A0A0A0A0Aull
48
49static int _setup(void **state __attribute__((unused)))
50{
52}
53
54static int _teardown(void **state __attribute__((unused)))
55{
57 return 0;
58}
59
62{
63 const uint32_t before = dt_pixelpipe_cache_get_alloc_refusals();
64
65 void *buffer = dt_pixelpipe_cache_alloc_align_cache_impl(MIB, 0, "granted");
66 assert_non_null(buffer);
67 assert_int_equal(dt_pixelpipe_cache_get_alloc_refusals(), before);
68
69 dt_pixelpipe_cache_free_align_cache(&buffer, "granted");
70}
71
74{
75 const uint32_t before = dt_pixelpipe_cache_get_alloc_refusals();
76
77 assert_null(dt_pixelpipe_cache_alloc_align_cache_impl(2 * CACHE_BYTES, 0, "too large"));
78 assert_int_equal(dt_pixelpipe_cache_get_alloc_refusals(), before + 1);
79}
80
83{
84 void *data = NULL;
85 dt_pixel_cache_entry_t *held = NULL;
86 // Created referenced and write-locked, the way a module holds its output while it writes it.
87 assert_int_equal(dt_dev_pixelpipe_cache_get_writable(HASH_HELD, 48 * MIB, "held line", 0, TRUE, FALSE, NULL,
88 NULL, &data, &held),
90 assert_non_null(data);
91
92 const uint32_t before = dt_pixelpipe_cache_get_alloc_refusals();
93 assert_null(dt_pixelpipe_cache_alloc_align_cache_impl(32 * MIB, 0, "no room"));
94 assert_int_equal(dt_pixelpipe_cache_get_alloc_refusals(), before + 1);
95
98}
99
100static gpointer _refuse_on_this_thread(gpointer unused __attribute__((unused)))
101{
102 const uint32_t before = dt_pixelpipe_cache_get_alloc_refusals();
103 void *buffer = dt_pixelpipe_cache_alloc_align_cache_impl(2 * CACHE_BYTES, 0, "too large");
104 const uint32_t counted = dt_pixelpipe_cache_get_alloc_refusals() - before;
105 return GUINT_TO_POINTER(IS_NULL_PTR(buffer) ? counted : G_MAXUINT);
106}
107
111{
112 const uint32_t before = dt_pixelpipe_cache_get_alloc_refusals();
113
114 GThread *other = g_thread_new("refused elsewhere", _refuse_on_this_thread, NULL);
115 const guint counted_there = GPOINTER_TO_UINT(g_thread_join(other));
116
117 assert_int_equal(counted_there, 1);
118 assert_int_equal(dt_pixelpipe_cache_get_alloc_refusals(), before);
119}
120
121int main(int argc, char *argv[])
122{
123 const struct CMUnitTest tests[] = {
124 cmocka_unit_test_setup_teardown(_granted_allocation_is_not_counted, _setup, _teardown),
125 cmocka_unit_test_setup_teardown(_request_larger_than_the_cache_is_counted_once, _setup, _teardown),
126 cmocka_unit_test_setup_teardown(_budget_spent_by_a_line_in_use_is_counted_once, _setup, _teardown),
127 cmocka_unit_test_setup_teardown(_refusal_on_another_thread_is_not_counted_here, _setup, _teardown),
128 };
129 return cmocka_run_group_tests(tests, NULL, NULL);
130}
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition macros.h:96
void dt_dev_pixelpipe_cache_wrlock_entry(gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Lock or release the write lock on the entry.
void dt_dev_pixelpipe_cache_cleanup(void)
Release everything dt_dev_pixelpipe_cache_init() created, the instance included. Only after a success...
void * dt_pixelpipe_cache_alloc_align_cache_impl(size_t size, int id, const char *name)
Allocate aligned memory tracked by the pixelpipe cache. This allows LRU cache entries to be evicted i...
void dt_dev_pixelpipe_cache_ref_count_entry(gboolean lock, dt_pixel_cache_entry_t *cache_entry)
Take or release one reference on a cache line. A referenced line is never evicted,...
gboolean dt_dev_pixelpipe_cache_init(size_t max_memory, const gboolean verbose, const gboolean verbose_detail)
Reserve the cache's arena and start it.
void dt_pixelpipe_cache_free_align_cache(void **mem, const char *message)
Free aligned memory allocated with dt_pixelpipe_cache_alloc_align_cache.
dt_dev_pixelpipe_cache_writable_status_t dt_dev_pixelpipe_cache_get_writable(const uint64_t hash, const size_t size, const char *name, const int id, const gboolean alloc, const gboolean allow_rekey_reuse, const dt_pixel_cache_entry_t *reuse_hint, const dt_pixel_cache_entry_t *reuse_hint_prev, void **data, dt_pixel_cache_entry_t **entry)
uint32_t dt_pixelpipe_cache_get_alloc_refusals(void)
Count the allocations the cache refused to the calling thread for lack of memory (thread-local).
Pixelpipe cache for storing intermediate results in the pixelpipe.
@ DT_DEV_PIXELPIPE_CACHE_WRITABLE_CREATED
int main()
Definition prova.c:47
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
Definition simd.h:55
const float uint32_t state[4]
static void _refusal_on_another_thread_is_not_counted_here(void **state __attribute__((unused)))
static int _teardown(void **state __attribute__((unused)))
static int _setup(void **state __attribute__((unused)))
static void _request_larger_than_the_cache_is_counted_once(void **state __attribute__((unused)))
static void _budget_spent_by_a_line_in_use_is_counted_once(void **state __attribute__((unused)))
static gpointer _refuse_on_this_thread(gpointer unused __attribute__((unused)))
static void _granted_allocation_is_not_counted(void **state __attribute__((unused)))