2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
22 #if defined(USE_AMALLOC)
23 extern uchar_efficient_t amalloc_enabled
;
25 #define amalloc_enabled 0
28 void * attr_fastcall
mem_alloc_position(size_t size
, ajla_error_t
*mayfail argument_position
);
29 void * attr_fastcall
mem_calloc_position(size_t size
, ajla_error_t
*mayfail argument_position
);
30 void * attr_fastcall
mem_align_position(size_t size
, size_t alignment
, ajla_error_t
*mayfail argument_position
);
31 void * attr_fastcall
mem_calign_position(size_t size
, size_t alignment
, ajla_error_t
*mayfail argument_position
);
32 void * attr_fastcall
mem_realloc_position(void *ptr
, size_t size
, ajla_error_t
*mayfail argument_position
);
33 void attr_fastcall
mem_free_position(const void *ptr argument_position
);
34 void attr_fastcall
mem_free_aligned_position(const void *ptr argument_position
);
36 #define mem_alloc_fn(x, y) mem_alloc_position(x, y pass_file_line)
37 #define mem_calloc_fn(x, y) mem_calloc_position(x, y pass_file_line)
38 #define mem_align_fn(x, y, z) mem_align_position(x, y, z pass_file_line)
39 #define mem_calign_fn(x, y, z) mem_calign_position(x, y, z pass_file_line)
40 #define mem_realloc_fn(x, y, z) mem_realloc_position(x, y, z pass_file_line)
41 #define mem_free(x) mem_free_position(x pass_file_line)
42 #define mem_free_aligned(x) mem_free_aligned_position(x pass_file_line)
44 #define mem_alloc_mayfail(t, x, y) cast_ptr(t, mem_alloc_fn(x, y))
45 #define mem_calloc_mayfail(t, x, y) cast_ptr(t, mem_calloc_fn(x, y))
46 #define mem_align_mayfail(t, x, y, z) cast_ptr(t, mem_align_fn(x, y, z))
47 #define mem_calign_mayfail(t, x, y, z) cast_ptr(t, mem_calign_fn(x, y, z))
48 #define mem_realloc_mayfail(t, x, y, z) cast_ptr(t, mem_realloc_fn(x, y, z))
50 #define mem_alloc(t, x) mem_alloc_mayfail(t, x, NULL)
51 #define mem_calloc(t, x) mem_calloc_mayfail(t, x, NULL)
52 #define mem_align(t, x, y) mem_align_mayfail(t, x, y, NULL)
53 #define mem_calign(t, x, y) mem_calign_mayfail(t, x, y, NULL)
54 #define mem_realloc(t, x, y) mem_realloc_mayfail(t, x, y, NULL)
56 #ifdef DEBUG_MEMORY_POSSIBLE
57 void attr_fastcall
mem_set_position(const void *ptr argument_position
);
58 const char * attr_fastcall
mem_get_position(const void *ptr argument_position
);
59 void attr_fastcall
mem_verify_position(const void attr_unused
*ptr argument_position
);
60 void attr_fastcall
mem_verify_aligned_position(const void attr_unused
*ptr argument_position
);
62 static inline void mem_set_position(const void attr_unused
*ptr argument_position
) { }
63 static inline const char *mem_get_position(const void attr_unused
*ptr argument_position
) { return "unknown position"; }
64 static inline void mem_verify_position(const void attr_unused
*ptr argument_position
) { }
65 static inline void mem_verify_aligned_position(const void attr_unused
*ptr argument_position
) { }
68 #define mem_get_pos(x) mem_get_position(x pass_file_line)
69 #define mem_verify(x) mem_verify_position(x pass_file_line)
70 #define mem_verify_aligned(x) mem_verify_aligned_position(x pass_file_line)
72 bool mem_trim_cache(void);
75 #define MR_MOST_ALLOCATED 1
76 #define MR_LARGEST_BLOCKS 2
77 #ifdef DEBUG_MEMORY_POSSIBLE
78 void mem_report_usage(int mode
, const char *string
);
80 static inline void mem_report_usage(int attr_unused mode
, const char attr_unused
*string
) { }
83 bool mem_enable_debugging_option(const char *option
, size_t l
);
84 bool mem_al_enable_profile(const char *option
, size_t l
);
85 void mem_al_set_ptrcomp(const char *str
);
86 void mem_al_set_system_malloc(const char attr_unused
*str
);
88 void mem_init_multithreaded(void);
89 void mem_done_multithreaded(void);
92 static inline bool mem_check_overflow(size_t prefix
, size_t n_elements
, size_t el_size
, ajla_error_t
*err
)
94 if (unlikely(n_elements
> (size_t_limit
- prefix
) / el_size
)) {
95 fatal_mayfail(error_ajla(EC_SYNC
, AJLA_ERROR_SIZE_OVERFLOW
), err
, "allocation size overflow: %" PRIuMAX
" + %" PRIuMAX
" * %" PRIuMAX
"", (uintmax_t)prefix
, (uintmax_t)n_elements
, (uintmax_t)el_size
);
101 #define struct_check_overflow(full, part, n_elements, err) mem_check_overflow(offsetof(full, part), n_elements, sizeof(((full *)NULL)->part[0]), err)
103 #define mem_alloc_array_mayfail(alloc, type, minimum, prefix, n_elements, el_size, err)\
104 (unlikely(!mem_check_overflow(prefix, n_elements, el_size, err)) ? cast_ptr(type, NULL) : alloc(type, maximum_maybe0((size_t)(prefix) + (size_t)(n_elements) * (size_t)(el_size), (size_t)(minimum)), err))
106 #define struct_alloc_array_mayfail(alloc, full, part, n_elements, err)\
107 mem_alloc_array_mayfail(alloc, full *, partial_sizeof_lower_bound(full), offsetof(full, part), n_elements, sizeof(((full *)NULL)->part[0]), err)