1 /*@ Mem bag objects to throw in and possibly forget about allocations.
2  *@ Depends on su_HAVE_MEM_BAG_{AUTO,LOFI}. TODO FLUX
3  *@ The allocation interface is macro-based for the sake of debugging.
4  *
5  * Copyright (c) 2012 - 2020 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
6  * SPDX-License-Identifier: ISC
7  *
8  * Permission to use, copy, modify, and/or distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 #ifndef su_MEM_BAG_H
21 #define su_MEM_BAG_H
22 #include <su/code.h>
23 #if defined su_HAVE_MEM_BAG_AUTO || defined su_HAVE_MEM_BAG_LOFI
24 # define su_HAVE_MEM_BAG
25 #endif
26 #ifdef su_HAVE_MEM_BAG
27 #define su_HEADER
28 #include <su/code-in.h>
29 C_DECL_BEGIN
30 struct su_mem_bag;
31 #ifdef su_USECASE_MX
32 # define su_MEM_BAG_SELF (n_go_data->gdc_membag)
33 #endif
34 /* Equality CTAsserted */
35 enum su_mem_bag_alloc_flags{
36    su_MEM_BAG_ALLOC_NONE,
37    su_MEM_BAG_ALLOC_CLEAR = 1u<<1,
38    su_MEM_BAG_ALLOC_OVERFLOW_OK = su_STATE_ERR_OVERFLOW,
39    su_MEM_BAG_ALLOC_NOMEM_OK = su_STATE_ERR_NOMEM,
40    su_MEM_BAG_ALLOC_MAYFAIL = su_STATE_ERR_PASS,
41    su_MEM_BAG_ALLOC_MUSTFAIL = su_STATE_ERR_NOPASS,
42    su__MEM_BAG_ALLOC_USER_MASK = 0xFF | su_STATE_ERR_MASK
43 };
44 struct su_mem_bag{
45    struct su_mem_bag *mb_top; /* Stacktop (outermost object only) */
46    struct su_mem_bag *mb_outer; /* Outer object in stack */
47    struct su_mem_bag *mb_outer_save;
48    u32 mb_bsz; /* Pool size available to users.. */
49    u32 mb_bsz_wo_gap; /* ..less some GAP */
50 #ifdef su_HAVE_MEM_BAG_AUTO
51    sz mb_auto_relax_recur;
52    struct su__mem_bag_auto_buf *mb_auto_top;
53    struct su__mem_bag_auto_buf *mb_auto_full;
54    struct su__mem_bag_auto_huge *mb_auto_huge;
55 #endif
56 #ifdef su_HAVE_MEM_BAG_LOFI
57    struct su__mem_bag_lofi_pool *mb_lofi_pool;
58    struct su__mem_bag_lofi_chunk *mb_lofi_top;
59 #endif
60 };
61 EXPORT struct su_mem_bag *su_mem_bag_create(struct su_mem_bag *self, uz bsz);
62 EXPORT void su_mem_bag_gut(struct su_mem_bag *self);
63 EXPORT struct su_mem_bag *su_mem_bag_fixate(struct su_mem_bag *self);
64 EXPORT struct su_mem_bag *su_mem_bag_reset(struct su_mem_bag *self);
65 EXPORT struct su_mem_bag *su_mem_bag_push(struct su_mem_bag *self,
66       struct su_mem_bag *that_one);
67 EXPORT struct su_mem_bag *su_mem_bag_pop(struct su_mem_bag *self,
68       struct su_mem_bag *that_one);
su_mem_bag_top(struct su_mem_bag * self)69 INLINE struct su_mem_bag *su_mem_bag_top(struct su_mem_bag *self){
70    ASSERT_RET(self != NIL, NIL);
71 #if ASSERT_INJOR(1, 0)
72    if(self->mb_outer != NIL){
73       ASSERT_EXEC(self->mb_outer == NIL, (void)0);
74       do
75          self = self->mb_outer;
76       while(self->mb_outer != NIL);
77    }
78 #endif
79    return (self->mb_top != NIL) ? self->mb_top : self;
80 }
81 /*
82  * Allocation interface: auto
83  */
84 #ifdef su_HAVE_MEM_BAG_AUTO
85 EXPORT struct su_mem_bag *su_mem_bag_auto_relax_create(
86       struct su_mem_bag *self);
87 EXPORT struct su_mem_bag *su_mem_bag_auto_relax_gut(struct su_mem_bag *self);
88 EXPORT struct su_mem_bag *su_mem_bag_auto_relax_unroll(
89       struct su_mem_bag *self);
90 EXPORT void *su_mem_bag_auto_allocate(struct su_mem_bag *self, uz size, uz no,
91       u32 mbaf  su_DBG_LOC_ARGS_DECL);
92 # define su_MEM_BAG_AUTO_ALLOCATE(BAGP,SZ,NO,F) \
93       su_mem_bag_auto_allocate(BAGP, SZ, NO, F  su_DBG_LOC_ARGS_INJ)
94 # ifdef su_HAVE_DBG_LOC_ARGS
95 #  define su_MEM_BAG_AUTO_ALLOCATE_LOC(BAGP,SZ,NO,F,FNAME,LNNO) \
96       su_mem_bag_auto_allocate(BAGP, SZ, NO, F, FNAME, LNNO)
97 # else
98 #  define su_MEM_BAG_AUTO_ALLOCATE_LOC(BAGP,SZ,NO,F,FNAME,LNNO) \
99       su_mem_bag_auto_allocate(BAGP, SZ, NO, F)
100 # endif
101 /* The "normal" interface, slim, but su_USECASE_ specific: use _ALLOCATE_ for
102  * other use cases.  These set MUSTFAIL and always return a valid pointer. */
103 # ifdef su_MEM_BAG_SELF
104 #  define su_MEM_BAG_SELF_AUTO_ALLOC(SZ) \
105       su_MEM_BAG_AUTO_ALLOCATE(su_MEM_BAG_SELF, SZ, 1,\
106          su_MEM_BAG_ALLOC_MUSTFAIL)
107 #  define su_MEM_BAG_SELF_AUTO_ALLOC_LOC(SZ,FNAME,LNNO) \
108       su_MEM_BAG_AUTO_ALLOCATE_LOC(su_MEM_BAG_SELF, SZ, 1,\
109          su_MEM_BAG_ALLOC_MUSTFAIL, FNAME, LNNO)
110 #  define su_MEM_BAG_SELF_AUTO_ALLOC_N(SZ,NO) \
111       su_MEM_BAG_AUTO_ALLOCATE(su_MEM_BAG_SELF, SZ, NO,\
112          su_MEM_BAG_ALLOC_MUSTFAIL)
113 #  define su_MEM_BAG_SELF_AUTO_ALLOC_N_LOC(SZ,NO,FNAME,LNNO) \
114       su_MEM_BAG_AUTO_ALLOCATE_LOC(su_MEM_BAG_SELF, SZ, NO,\
115          su_MEM_BAG_ALLOC_MUSTFAIL, FNAME, LNNO)
116 #  define su_MEM_BAG_SELF_AUTO_CALLOC(SZ) \
117       su_MEM_BAG_AUTO_ALLOCATE(su_MEM_BAG_SELF, SZ, 1,\
118          su_MEM_BAG_ALLOC_CLEAR | su_MEM_BAG_ALLOC_MUSTFAIL)
119 #  define su_MEM_BAG_SELF_AUTO_CALLOC_LOC(SZ,FNAME,LNNO) \
120       su_MEM_BAG_AUTO_ALLOCATE_LOC(su_MEM_BAG_SELF, SZ, 1,\
121          su_MEM_BAG_ALLOC_CLEAR | su_MEM_BAG_ALLOC_MUSTFAIL, FNAME, LNNO)
122 #  define su_MEM_BAG_SELF_AUTO_CALLOC_N(SZ,NO) \
123       su_MEM_BAG_AUTO_ALLOCATE(su_MEM_BAG_SELF, SZ, NO,\
124          su_MEM_BAG_ALLOC_CLEAR | su_MEM_BAG_ALLOC_MUSTFAIL)
125 #  define su_MEM_BAG_SELF_AUTO_CALLOC_N_LOC(SZ,NO,FNAME,LNNO) \
126       su_MEM_BAG_AUTO_ALLOCATE_LOC(su_MEM_BAG_SELF, SZ, NO,\
127          su_MEM_BAG_ALLOC_CLEAR | su_MEM_BAG_ALLOC_MUSTFAIL, FNAME, LNNO)
128 #  define su_MEM_BAG_SELF_AUTO_TALLOC(T,NO) \
129       su_S(T *,su_MEM_BAG_SELF_AUTO_ALLOC_N(sizeof(T), su_S(su_uz,NO)))
130 #  define su_MEM_BAG_SELF_AUTO_TALLOC_LOC(T,NO,FNAME,LNNO) \
131       su_S(T *,su_MEM_BAG_SELF_AUTO_ALLOC_N_LOC(sizeof(T), su_S(su_uz,NO),\
132          FNAME, LNNO))
133 #  define su_MEM_BAG_SELF_AUTO_TCALLOC(T,NO) \
134       su_S(T *,su_MEM_BAG_SELF_AUTO_CALLOC_N(sizeof(T), su_S(su_uz,NO)))
135 #  define su_MEM_BAG_SELF_AUTO_TCALLOC_LOC(T,NO,FNAME,LNNO) \
136       su_S(T *,su_MEM_BAG_SELF_AUTO_CALLOC_N_LOC(sizeof(T), su_S(su_uz,NO),\
137          FNAME, LNNO))
138    /* (The painful _LOCOR series) */
139 #  ifdef su_HAVE_DBG_LOC_ARGS
140 #   define su_MEM_BAG_SELF_AUTO_ALLOC_LOCOR(SZ,ORARGS) \
141       su_MEM_BAG_SELF_AUTO_ALLOC_LOC(SZ, ORARGS)
142 #   define su_MEM_BAG_SELF_AUTO_ALLOC_N_LOCOR(SZ,NO,ORARGS) \
143       su_MEM_BAG_SELF_AUTO_ALLOC_N_LOC(SZ, NO, ORARGS)
144 #   define su_MEM_BAG_SELF_AUTO_CALLOC_LOCOR(SZ,ORARGS) \
145       su_MEM_BAG_SELF_AUTO_CALLOC_LOC(SZ, ORGARGS)
146 #   define su_MEM_BAG_SELF_AUTO_CALLOC_N_LOCOR(SZ,NO,ORARGS) \
147       su_MEM_BAG_SELF_AUTO_CALLOC_N_LOC(SZ, NO, ORARGS)
148 #   define su_MEM_BAG_SELF_AUTO_TALLOC_LOCOR(T,NO,ORARGS) \
149       su_MEM_BAG_SELF_AUTO_TALLOC_LOC(T, NO, ORARGS)
150 #   define su_MEM_BAG_SELF_AUTO_TCALLOC_LOCOR(T,NO,ORARGS) \
151       su_MEM_BAG_SELF_AUTO_TCALLOC_LOC(T, NO, ORARGS)
152 #  else
153 #   define su_MEM_BAG_SELF_AUTO_ALLOC_LOCOR(SZ,ORARGS) \
154       su_MEM_BAG_SELF_AUTO_ALLOC(SZ)
155 #   define su_MEM_BAG_SELF_AUTO_ALLOC_N_LOCOR(SZ,NO,ORARGS) \
156       su_MEM_BAG_SELF_AUTO_ALLOC_N(SZ, NO)
157 #   define su_MEM_BAG_SELF_AUTO_CALLOC_LOCOR(SZ,ORARGS) \
158       su_MEM_BAG_SELF_AUTO_CALLOC(SZ)
159 #   define su_MEM_BAG_SELF_AUTO_CALLOC_N_LOCOR(SZ,NO,ORARGS) \
160       su_MEM_BAG_SELF_AUTO_CALLOC_N(SZ, NO)
161 #   define su_MEM_BAG_SELF_AUTO_TALLOC_LOCOR(T,NO,ORARGS) \
162       su_MEM_BAG_SELF_AUTO_TALLOC(T, NO)
163 #   define su_MEM_BAG_SELF_AUTO_TCALLOC_LOCOR(T,NO,ORARGS) \
164       su_MEM_BAG_SELF_AUTO_TCALLOC(T, NO)
165 #  endif /* !su_HAVE_DBG_LOC_ARGS */
166 # endif /* su_MEM_BAG_SELF */
167 #endif /* su_HAVE_MEM_BAG_AUTO */
168 /*
169  * Allocation interface: lofi
170  */
171 #ifdef su_HAVE_MEM_BAG_LOFI
172 EXPORT void *su_mem_bag_lofi_snap_create(struct su_mem_bag *self);
173 EXPORT struct su_mem_bag *su_mem_bag_lofi_snap_unroll(struct su_mem_bag *self,
174       void *cookie);
175 EXPORT void *su_mem_bag_lofi_allocate(struct su_mem_bag *self, uz size, uz no,
176       u32 mbaf  su_DBG_LOC_ARGS_DECL);
177 EXPORT struct su_mem_bag *su_mem_bag_lofi_free(struct su_mem_bag *self,
178       void *ovp su_DBG_LOC_ARGS_DECL);
179 # define su_MEM_BAG_LOFI_ALLOCATE(BAGP,SZ,NO,F) \
180       su_mem_bag_lofi_allocate(BAGP, SZ, NO, F  su_DBG_LOC_ARGS_INJ)
181 # ifdef su_HAVE_DBG_LOC_ARGS
182 #  define su_MEM_BAG_LOFI_ALLOCATE_LOC(BAGP,SZ,NO,F,FNAME,LNNO) \
183       su_mem_bag_lofi_allocate(BAGP, SZ, NO, F, FNAME, LNNO)
184 # else
185 #  define su_MEM_BAG_LOFI_ALLOCATE_LOC(BAGP,SZ,NO,F,FNAME,LNNO) \
186       su_mem_bag_lofi_allocate(BAGP, SZ, NO, F)
187 # endif
188 # define su_MEM_BAG_LOFI_FREE(BAGP,OVP) \
189    su_mem_bag_lofi_free(BAGP, OVP  su_DBG_LOC_ARGS_INJ)
190 # ifdef su_HAVE_DBG_LOC_ARGS
191 #  define su_MEM_BAG_LOFI_FREE_LOC(BAGP,OVP,FNAME,LNNO) \
192       su_mem_bag_lofi_free(BAGP, OVP, FNAME, LNNO)
193 # else
194 #  define su_MEM_BAG_LOFI_FREE_LOC(BAGP,OVP,FNAME,LNNO) \
195       su_mem_bag_lofi_free(BAGP, OVP)
196 # endif
197 /* The "normal" interface, slim, but su_USECASE_ specific: use _ALLOCATE_ for
198  * other use cases.  These set MUSTFAIL and always return a valid pointer. */
199 # ifdef su_MEM_BAG_SELF
200 #  define su_MEM_BAG_SELF_LOFI_ALLOC(SZ) \
201       su_MEM_BAG_LOFI_ALLOCATE(su_MEM_BAG_SELF, SZ, 1,\
202          su_MEM_BAG_ALLOC_MUSTFAIL)
203 #  define su_MEM_BAG_SELF_LOFI_ALLOC_LOC(SZ,FNAME,LNNO) \
204       su_MEM_BAG_LOFI_ALLOCATE_LOC(su_MEM_BAG_SELF, SZ, 1,\
205          su_MEM_BAG_ALLOC_MUSTFAIL, FNAME, LNNO)
206 #  define su_MEM_BAG_SELF_LOFI_ALLOC_N(SZ,NO) \
207       su_MEM_BAG_LOFI_ALLOCATE(su_MEM_BAG_SELF, SZ, NO,\
208          su_MEM_BAG_ALLOC_MUSTFAIL)
209 #  define su_MEM_BAG_SELF_LOFI_ALLOC_N_LOC(SZ,NO,FNAME,LNNO) \
210       su_MEM_BAG_LOFI_ALLOCATE_LOC(su_MEM_BAG_SELF, SZ, NO,\
211          su_MEM_BAG_ALLOC_MUSTFAIL, FNAME, LNNO)
212 #  define su_MEM_BAG_SELF_LOFI_CALLOC(SZ) \
213       su_MEM_BAG_LOFI_ALLOCATE(su_MEM_BAG_SELF, SZ, 1,\
214          su_MEM_BAG_ALLOC_CLEAR | su_MEM_BAG_ALLOC_MUSTFAIL)
215 #  define su_MEM_BAG_SELF_LOFI_CALLOC_LOC(SZ,FNAME,LNNO) \
216       su_MEM_BAG_LOFI_SELF_ALLOCATE_LOC(su_MEM_BAG_SELF, SZ, 1,\
217          su_MEM_BAG_ALLOC_CLEAR | su_MEM_BAG_ALLOC_MUSTFAIL, FNAME, LNNO)
218 #  define su_MEM_BAG_SELF_LOFI_CALLOC_N(SZ,NO) \
219       su_MEM_BAG_LOFI_ALLOCATE(su_MEM_BAG_SELF, SZ, NO,\
220          su_MEM_BAG_ALLOC_CLEAR | su_MEM_BAG_ALLOC_MUSTFAIL)
221 #  define su_MEM_BAG_SELF_LOFI_CALLOC_N_LOC(SZ,NO,FNAME,LNNO) \
222       su_MEM_BAG_LOFI_ALLOCATE_LOC(su_MEM_BAG_SELF, SZ, NO,\
223          su_MEM_BAG_ALLOC_CLEAR | su_MEM_BAG_ALLOC_MUSTFAIL, FNAME, LNNO)
224 #  define su_MEM_BAG_SELF_LOFI_TALLOC(T,NO) \
225       su_S(T *,su_MEM_BAG_SELF_LOFI_ALLOC_N(sizeof(T), su_S(su_uz,NO)))
226 #  define su_MEM_BAG_SELF_LOFI_TALLOC_LOC(T,NO,FNAME,LNNO) \
227       su_S(T *,su_MEM_BAG_SELF_LOFI_ALLOC_N_LOC(sizeof(T), su_S(su_uz,NO),\
228          FNAME, LNNO))
229 #  define su_MEM_BAG_SELF_LOFI_TCALLOC(T,NO) \
230       su_S(T *,su_MEM_BAG_SELF_LOFI_CALLOC_N(sizeof(T), su_S(su_uz,NO))
231 #  define su_MEM_BAG_SELF_LOFI_TCALLOC_LOC(T,NO,FNAME,LNNO) \
232       su_S(T *,su_MEM_BAG_SELF_LOFI_CALLOC_N_LOC(sizeof(T), su_S(su_uz,NO),\
233          FNAME, LNNO))
234 #  define su_MEM_BAG_SELF_LOFI_FREE(OVP) \
235       su_MEM_BAG_LOFI_FREE(su_MEM_BAG_SELF, OVP)
236 #  define su_MEM_BAG_SELF_LOFI_FREE_LOC(OVP,FNAME,LNNO) \
237       su_MEM_BAG_LOFI_FREE_LOC(su_MEM_BAG_SELF, OVP, FNAME, LNNO)
238    /* (The painful _LOCOR series) */
239 #  ifdef su_HAVE_DBG_LOC_ARGS
240 #   define su_MEM_BAG_SELF_LOFI_ALLOC_LOCOR(SZ,ORARGS) \
241       su_MEM_BAG_SELF_LOFI_ALLOC_LOC(SZ, ORARGS)
242 #   define su_MEM_BAG_SELF_LOFI_ALLOC_N_LOCOR(SZ,NO,ORARGS) \
243       su_MEM_BAG_SELF_LOFI_ALLOC_N_LOC(SZ, NO, ORARGS)
244 #   define su_MEM_BAG_SELF_LOFI_CALLOC_LOCOR(SZ,ORARGS) \
245       su_MEM_BAG_SELF_LOFI_CALLOC_LOC(SZ, ORGARGS)
246 #   define su_MEM_BAG_SELF_LOFI_CALLOC_N_LOCOR(SZ,NO,ORARGS) \
247       su_MEM_BAG_SELF_LOFI_CALLOC_N_LOC(SZ, NO, ORARGS)
248 #   define su_MEM_BAG_SELF_LOFI_TALLOC_LOCOR(T,NO,ORARGS) \
249       su_MEM_BAG_SELF_LOFI_TALLOC_LOC(T, NO, ORARGS)
250 #   define su_MEM_BAG_SELF_LOFI_TCALLOC_LOCOR(T,NO,ORARGS) \
251       su_MEM_BAG_SELF_LOFI_TCALLOC_LOC(T, NO, ORARGS)
252 #   define su_MEM_BAG_SELF_LOFI_FREE_LOCOR(OVP,ORARGS) \
253       su_MEM_BAG_SELF_LOFI_FREE_LOC(OVP, ORARGS)
254 #  else
255 #   define su_MEM_BAG_SELF_LOFI_ALLOC_LOCOR(SZ,ORARGS) \
256       su_MEM_BAG_SELF_LOFI_ALLOC(SZ)
257 #   define su_MEM_BAG_SELF_LOFI_ALLOC_N_LOCOR(SZ,NO,ORARGS) \
258       su_MEM_BAG_SELF_LOFI_ALLOC_N(SZ, NO)
259 #   define su_MEM_BAG_SELF_LOFI_CALLOC_LOCOR(SZ,ORARGS) \
260       su_MEM_BAG_SELF_LOFI_CALLOC(SZ)
261 #   define su_MEM_BAG_SELF_LOFI_CALLOC_N_LOCOR(SZ,NO,ORARGS) \
262       su_MEM_BAG_SELF_LOFI_CALLOC_N(SZ, NO)
263 #   define su_MEM_BAG_SELF_LOFI_TALLOC_LOCOR(T,NO,ORARGS) \
264       su_MEM_BAG_SELF_LOFI_TALLOC(T, NO)
265 #   define su_MEM_BAG_SELF_LOFI_TCALLOC_LOCOR(T,NO,ORARGS) \
266       su_MEM_BAG_SELF_LOFI_TCALLOC(T, NO)
267 #   define su_MEM_BAG_SELF_LOFI_FREE_LOCOR(OVP,ORARGS) \
268       su_MEM_BAG_SELF_LOFI_FREE_LOC(OVP, ORARGS)
269 #  endif /* !su_HAVE_DBG_LOC_ARGS */
270 # endif /* su_MEM_BAG_SELF */
271 #endif /* su_HAVE_MEM_BAG_LOFI */
272 C_DECL_END
273 #include <su/code-ou.h>
274 #endif /* su_HAVE_MEM_BAG */
275 #endif /* !su_MEM_BAG_H */
276 /* s-it-mode */
277