1 /*@ Memory: tools like copy, move etc., and a heap allocation interface.
3 * Copyright (c) 2001 - 2020 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
4 * SPDX-License-Identifier: ISC
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 #include <su/code-in.h>
24 /* A memset that is not optimized away */
25 EXPORT_DATA
void * (* volatile su_mem_set_volatile
)(void*, int, uz
);
26 EXPORT sz
su_mem_cmp(void const *vpa
, void const *vpb
, uz len
);
27 EXPORT
void *su_mem_copy(void *vp
, void const *src
, uz len
);
28 EXPORT
void *su_mem_find(void const *vp
, s32 what
, uz len
);
29 EXPORT
void *su_mem_rfind(void const *vp
, s32 what
, uz len
);
30 EXPORT
void *su_mem_move(void *vp
, void const *src
, uz len
);
31 EXPORT
void *su_mem_set(void *vp
, s32 what
, uz len
);
32 #if (defined su_HAVE_DEBUG && !defined su_HAVE_MEM_CANARIES_DISABLE) ||\
34 # define su_MEM_ALLOC_DEBUG
36 enum su_mem_alloc_flags
{
38 su_MEM_ALLOC_CLEAR
= 1u<<1,
39 su_MEM_ALLOC_32BIT_OVERFLOW
= 1u<<2,
40 su_MEM_ALLOC_31BIT_OVERFLOW
= 1u<<3,
41 su_MEM_ALLOC_OVERFLOW_OK
= su_STATE_ERR_OVERFLOW
,
42 su_MEM_ALLOC_NOMEM_OK
= su_STATE_ERR_NOMEM
,
43 su_MEM_ALLOC_MAYFAIL
= su_STATE_ERR_PASS
,
44 su_MEM_ALLOC_MUSTFAIL
= su_STATE_ERR_NOPASS
,
45 su__MEM_ALLOC_MARK_SHIFT
= 16u,
46 su_MEM_ALLOC_MARK_0
= 0u<<su__MEM_ALLOC_MARK_SHIFT
,
47 su_MEM_ALLOC_MARK_1
= 1u<<su__MEM_ALLOC_MARK_SHIFT
,
48 su_MEM_ALLOC_MARK_2
= 2u<<su__MEM_ALLOC_MARK_SHIFT
,
49 su_MEM_ALLOC_MARK_3
= 3u<<su__MEM_ALLOC_MARK_SHIFT
,
50 su_MEM_ALLOC_MARK_AUTO
= su_MEM_ALLOC_MARK_1
,
51 su_MEM_ALLOC_MARK_AUTO_HUGE
= su_MEM_ALLOC_MARK_2
,
52 su_MEM_ALLOC_MARK_LOFI
= su_MEM_ALLOC_MARK_3
,
53 su__MEM_ALLOC_MARK_MAX
= 3u,
54 su__MEM_ALLOC_MARK_MASK
= 3u,
55 su__MEM_ALLOC_USER_MASK
= 0xFF | su_STATE_ERR_MASK
|
56 (su__MEM_ALLOC_MARK_MASK
<< su__MEM_ALLOC_MARK_SHIFT
)
58 #ifdef su_SOURCE_MEM_ALLOC
59 CTA((su_STATE_ERR_MASK
& ~0xFF00u
) == 0,
60 "Reuse of low order bits impossible, or mask excesses storage");
63 su_MEM_ALLOC_MIN
= Z_ALIGN(1)
65 enum su_mem_conf_option
{
67 /* su_MEM_ALLOC_DEBUG only: booleans */
68 su_MEM_CONF_DEBUG
= 1u<<0,
69 su_MEM_CONF_ON_ERROR_EMERG
= 1u<<1,
70 su_MEM_CONF_LINGER_FREE
= 1u<<2,
71 su_MEM_CONF_LINGER_FREE_RELEASE
= 1u<<3,
72 /*madvise,free area count*/
73 /*say_if_empty_on_exit,statistics*/
74 su__MEM_CONF_MAX
= su_MEM_CONF_LINGER_FREE_RELEASE
76 #ifdef su_MEM_ALLOC_DEBUG
77 EXPORT boole
su__mem_get_can_book(uz size
, uz no
);
78 EXPORT boole
su__mem_check(su_DBG_LOC_ARGS_DECL_SOLE
);
79 EXPORT boole
su__mem_trace(su_DBG_LOC_ARGS_DECL_SOLE
);
81 EXPORT
void *su_mem_allocate(uz size
, uz no
, u32 maf su_DBG_LOC_ARGS_DECL
);
82 EXPORT
void *su_mem_reallocate(void *ovp
, uz size
, uz no
, u32 maf
83 su_DBG_LOC_ARGS_DECL
);
84 EXPORT
void su_mem_free(void *ovp su_DBG_LOC_ARGS_DECL
);
85 #define su_MEM_ALLOCATE(SZ,NO,F) \
86 su_mem_allocate(SZ, NO, F su_DBG_LOC_ARGS_INJ)
87 #define su_MEM_REALLOCATE(OVP,SZ,NO,F) \
88 su_mem_reallocate(OVP, SZ, NO, F su_DBG_LOC_ARGS_INJ)
89 #ifdef su_HAVE_DBG_LOC_ARGS
90 # define su_MEM_ALLOCATE_LOC(SZ,NO,F,FNAME,LNNO) \
91 su_mem_allocate(SZ, NO, F, FNAME, LNNO)
92 # define su_MEM_REALLOCATE_LOC(OVP,SZ,NO,F,FNAME,LNNO) \
93 su_mem_reallocate(OVP, SZ, NO, F, FNAME, LNNO)
95 # define su_MEM_ALLOCATE_LOC(SZ,NO,F,FNAME,LNNO) \
96 su_mem_allocate(SZ, NO, F)
97 # define su_MEM_REALLOCATE_LOC(OVP,SZ,NO,F,FNAME,LNNO) \
98 su_mem_reallocate(OVP, SZ, NO, F)
100 /* The "normal" interface; there X, X_LOC, and X_LOCOR */
101 #define su_MEM_ALLOC(SZ) su_MEM_ALLOCATE(SZ, 1, su_MEM_ALLOC_NONE)
102 #define su_MEM_ALLOC_LOC(SZ,FNAME,LNNO) \
103 su_MEM_ALLOCATE_LOC(SZ, 1, su_MEM_ALLOC_NONE, FNAME, LNNO)
104 #define su_MEM_ALLOC_N(SZ,NO) su_MEM_ALLOCATE(SZ, NO, su_MEM_ALLOC_NONE)
105 #define su_MEM_ALLOC_N_LOC(SZ,NO,FNAME,LNNO) \
106 su_MEM_ALLOCATE_LOC(SZ, NO, su_MEM_ALLOC_NONE, FNAME, LNNO)
107 #define su_MEM_CALLOC(SZ) su_MEM_ALLOCATE(SZ, 1, su_MEM_ALLOC_CLEAR)
108 #define su_MEM_CALLOC_LOC(SZ,FNAME,LNNO) \
109 su_MEM_ALLOCATE_LOC(SZ, 1, su_MEM_ALLOC_CLEAR, FNAME, LNNO)
110 #define su_MEM_CALLOC_N(SZ,NO) su_MEM_ALLOCATE(SZ, NO, su_MEM_ALLOC_CLEAR)
111 #define su_MEM_CALLOC_N_LOC(SZ,NO,FNAME,LNNO) \
112 su_MEM_ALLOCATE_LOC(SZ, NO, su_MEM_ALLOC_CLEAR, FNAME, LNNO)
113 #define su_MEM_REALLOC(OVP,SZ) su_MEM_REALLOCATE(OVP, SZ, 1, su_MEM_ALLOC_NONE)
114 #define su_MEM_REALLOC_LOC(OVP,SZ,FNAME,LNNO) \
115 su_MEM_REALLOCATE_LOC(OVP, SZ, 1, su_MEM_ALLOC_NONE, FNAME, LNNO)
116 #define su_MEM_REALLOC_N(OVP,SZ,NO) \
117 su_MEM_REALLOCATE(OVP, SZ, NO, su_MEM_ALLOC_NONE)
118 #define su_MEM_REALLOC_N_LOC(OVP,SZ,NO,FNAME,LNNO) \
119 su_MEM_REALLOCATE_LOC(OVP, SZ, NO, su_MEM_ALLOC_NONE, FNAME, LNNO)
120 #define su_MEM_TALLOC(T,NO) su_S(T *,su_MEM_ALLOC_N(sizeof(T), NO))
121 #define su_MEM_TALLOC_LOC(T,NO,FNAME,LNNO) \
122 su_S(T *,su_MEM_ALLOC_N_LOC(sizeof(T), NO, FNAME, LNNO))
123 #define su_MEM_TCALLOC(T,NO) su_S(T *,su_MEM_CALLOC_N(sizeof(T), NO))
124 #define su_MEM_TCALLOC_LOC(T,NO,FNAME,LNNO) \
125 su_S(T *,su_MEM_CALLOC_N_LOC(sizeof(T), NO, FNAME, LNNO))
126 #define su_MEM_TREALLOC(T,OVP,NO) \
127 su_S(T *,su_MEM_REALLOC_N(OVP, sizeof(T), NO))
128 #define su_MEM_TREALLOC_LOC(T,OVP,NO,FNAME,LNNO) \
129 su_S(T *,su_MEM_REALLOC_N_LOC(OVP, sizeof(T), NO, FNAME, LNNO))
130 #define su_MEM_TALLOCF(T,NO,F) su_S(T *,su_MEM_ALLOCATE(sizeof(T), NO, F))
131 #define su_MEM_TALLOCF_LOC(T,NO,F,FNAME,LNNO) \
132 su_S(T *,su_MEM_ALLOCATE_LOC(sizeof(T), NO, F, FNAME, LNNO))
133 #define su_MEM_TCALLOCF(T,NO,F) \
134 su_S(T *,su_MEM_ALLOCATE(sizeof(T), NO, su_MEM_ALLOC_CLEAR | (F)))
135 #define su_MEM_TCALLOCF_LOC(T,NO,F,FNAME,LNNO) \
136 su_S(T *,su_MEM_ALLOCATE_LOC(sizeof(T), NO, su_MEM_ALLOC_CLEAR | (F)),\
138 #define su_MEM_TREALLOCF(T,OVP,NO,F) \
139 su_S(T *,su_MEM_REALLOCATE(OVP, sizeof(T), NO, F))
140 #define su_MEM_TREALLOCF_LOC(T,OVP,NO,F,FNAME,LNNO) \
141 su_S(T *,su_MEM_REALLOCATE_LOC(OVP, sizeof(T), NO, F, FNAME, LNNO))
142 #define su_MEM_FREE(OVP) su_mem_free(OVP su_DBG_LOC_ARGS_INJ)
143 #ifdef su_HAVE_DBG_LOC_ARGS
144 # define su_MEM_FREE_LOC(OVP,FNAME,LNNO) su_mem_free(OVP, FNAME, LNNO)
146 # define su_MEM_FREE_LOC(OVP,FNAME,LNNO) su_mem_free(OVP)
148 /* (The painful _LOCOR series) */
149 #ifdef su_HAVE_DBG_LOC_ARGS
150 # define su_MEM_ALLOC_LOCOR(SZ,ORARGS) su_MEM_ALLOC_LOC(SZ, ORARGS)
151 # define su_MEM_ALLOC_N_LOCOR(SZ,NO,ORARGS) su_MEM_ALLOC_N_LOC(SZ, NO, ORARGS)
152 # define su_MEM_CALLOC_LOCOR(SZ,ORARGS) su_MEM_CALLOC_LOC(SZ, ORGARGS)
153 # define su_MEM_CALLOC_N_LOCOR(SZ,NO,ORARGS) \
154 su_MEM_CALLOC_N_LOC(SZ, NO, ORARGS)
155 # define su_MEM_REALLOC_LOCOR(OVP,SZ,ORARGS) \
156 su_MEM_REALLOC_LOC(OVP, SZ, ORARGS)
157 # define su_MEM_REALLOC_N_LOCOR(OVP,SZ,NO,ORARGS) \
158 su_MEM_REALLOC_N_LOC(OVP, SZ, NO, ORARGS)
159 # define su_MEM_TALLOC_LOCOR(T,NO,ORARGS) su_MEM_TALLOC_LOC(T, NO, ORARGS)
160 # define su_MEM_TCALLOC_LOCOR(T,NO,ORARGS) su_MEM_TCALLOC_LOC(T, NO, ORARGS)
161 # define su_MEM_TREALLOC_LOCOR(T,OVP,NO,ORARGS) \
162 su_MEM_TREALLOC_LOC(T, OVP, NO, ORARGS)
163 # define su_MEM_TALLOCF_LOCOR(T,NO,F,ORARGS) \
164 su_MEM_TALLOCF_LOC(T, NO, F, ORARGS)
165 # define su_MEM_TCALLOCF_LOCOR(T,NO,F,ORARGS) \
166 su_MEM_TCALLOCF_LOC(T, NO, F, ORARGS)
167 # define su_MEM_TREALLOCF_LOCOR(T,OVP,NO,F,ORARGS) \
168 su_MEM_TREALLOCF_LOC(T, OVP, NO, F, ORARGS)
169 # define su_MEM_FREE_LOCOR(OVP,ORARGS) su_MEM_FREE_LOC(OVP, ORARGS)
171 # define su_MEM_ALLOC_LOCOR(SZ,ORARGS) su_MEM_ALLOC(SZ)
172 # define su_MEM_ALLOC_N_LOCOR(SZ,NO,ORARGS) su_MEM_ALLOC_N(SZ, NO)
173 # define su_MEM_CALLOC_LOCOR(SZ,ORARGS) su_MEM_CALLOC(SZ)
174 # define su_MEM_CALLOC_N_LOCOR(SZ,NO,ORARGS) su_MEM_CALLOC_N(SZ, NO)
175 # define su_MEM_REALLOC_LOCOR(OVP,SZ,ORARGS) su_MEM_REALLOC(OVP, SZ)
176 # define su_MEM_REALLOC_N_LOCOR(OVP,SZ,NO,ORARGS) su_MEM_REALLOC_N(OVP, SZ, NO)
177 # define su_MEM_TALLOC_LOCOR(T,NO,ORARGS) su_MEM_TALLOC(T, NO)
178 # define su_MEM_TCALLOC_LOCOR(T,NO,ORARGS) su_MEM_TCALLOC(T, NO)
179 # define su_MEM_TREALLOC_LOCOR(T,OVP,NO) su_MEM_TREALLOC(T, OVP, NO)
180 # define su_MEM_TALLOCF_LOCOR(T,NO,F,ORARGS) su_MEM_TALLOCF(T, NO, F)
181 # define su_MEM_TCALLOCF_LOCOR(T,NO,F,ORARGS) su_MEM_TCALLOCF(T, NO, F)
182 # define su_MEM_TREALLOCF_LOCOR(T,OVP,F,NO) su_MEM_TREALLOCF(T, OVP, NO, F)
183 # define su_MEM_FREE_LOCOR(OVP,ORARGS) su_MEM_FREE_LOC(OVP, ORARGS)
184 #endif /* !su_HAVE_DBG_LOC_ARGS */
185 INLINE boole
su_mem_get_can_book(uz size
, uz no
, uz notoadd
){
186 if(UZ_MAX
- no
<= notoadd
)
192 if(no
< size
|| (size
!= 1 && no
== size
))
194 #ifdef su_MEM_ALLOC_DEBUG
195 if(!su__mem_get_can_book(size
, no
))
200 #define su_mem_get_usable_size(SZ) su_Z_ALIGN(SZ) /* XXX fake */
201 #define su_mem_get_usable_size_32(SZ) su_S(su_u32,su_Z_ALIGN(SZ)) /*XXX*/
202 /* XXX get_usable_size_ptr(), get_memory_usage() */
203 EXPORT
void su_mem_set_conf(u32 mco
, uz val
);
204 INLINE boole
su_mem_check(void){
205 #ifdef su_MEM_ALLOC_DEBUG
206 return su__mem_check(su_DBG_LOC_ARGS_INJ_SOLE
);
211 /* XXX mem_check_ptr() */
212 /* XXX mem_[usage_]info(); opt: output channel, thread ptr */
213 INLINE boole
su_mem_trace(void){ /* XXX ochannel, thrptr*/
214 #ifdef su_MEM_ALLOC_DEBUG
215 return su__mem_trace(su_DBG_LOC_ARGS_INJ_SOLE
);
221 #include <su/code-ou.h>
222 #endif /* !su_MEM_H */