1 /*******************************************************************
2  *  File:    omAllocPrivate.h
3  *  Purpose: declaration of "private" (but visible to the outside)
4  *           routines for omalloc
5  *  Author:  obachman (Olaf Bachmann)
6  *  Created: 11/99
7  *******************************************************************/
8 #ifndef OM_ALLOC_PRIVATE_H
9 #define OM_ALLOC_PRIVATE_H
10 #include "omalloc/omAllocSystem.h"
11 
12 /*******************************************************************
13  *
14  *  Definitions of structures we work with
15  *
16  *******************************************************************/
17 /* Need to define it here, has to be known to macros */
18 struct omBinPage_s
19 {
20   long          used_blocks;    /* number of used blocks of this page */
21   void*         current;        /* pointer to current freelist */
22   omBinPage     next;           /* next/prev pointer of pages */
23   omBinPage     prev;
24   void*         bin_sticky;     /* bin this page belongs to with
25                                    sticky tag of page hidden in ptr */
26   omBinPageRegion region;       /* BinPageRegion of this page */
27 };
28 
29 /* Change this appropriately, if you change omBinPage                 */
30 /* However, make sure that omBinPage is a multiple of SIZEOF_MAX_TYPE */
31 #define SIZEOF_OM_BIN_PAGE_HEADER (5*SIZEOF_VOIDP + SIZEOF_LONG)
32 #define SIZEOF_OM_BIN_PAGE (SIZEOF_SYSTEM_PAGE - SIZEOF_OM_BIN_PAGE_HEADER)
33 
34 /* keep all members of omBin_s a sizeof(long) type,
35    otherwise list operations will fail */
36 struct omBin_s
37 {
38   omBinPage     current_page;   /* page of current freelist */
39   omBinPage     last_page;      /* pointer to last page of freelist */
40   omBin         next;           /* sticky bins of the same size */
41   size_t        sizeW;          /* size in words */
42   long          max_blocks;     /* if > 0   # blocks in one page,
43                                    if < 0   # pages for one block */
44   unsigned long sticky;         /* sticky tag */
45 };
46 
47 struct omSpecBin_s
48 {
49   omSpecBin        next;       /* pointer to next bin */
50   omBin            bin;        /* pointer to bin itself */
51   long             max_blocks; /* max_blocks of bin*/
52   long             ref;        /* ref count */
53 };
54 
55 extern  omSpecBin   om_SpecBin;
56 extern  omBin       om_StickyBins;
57 extern  omBinPage_t om_ZeroPage[];
58 extern  omBin       om_Size2Bin[];
59 
60 /*******************************************************************
61  *
62  *  Working with pages/bins
63  *
64  *******************************************************************/
65 #define omGetTopBinOfPage(page) \
66   ((omBin) ( ((unsigned long) ((page)->bin_sticky)) & ~((unsigned long)SIZEOF_VOIDP - 1)))
67 #define omGetStickyOfPage(page) \
68   (((unsigned long) ((page)->bin_sticky)) & ((unsigned long)SIZEOF_VOIDP-1))
69 #define omSetTopBinOfPage(page, bin) \
70   (page)->bin_sticky= (void*)((unsigned long)bin + omGetStickyOfPage(page))
71 #define omSetStickyOfPage(page, sticky) \
72   (page)->bin_sticky = (void*)(((unsigned long)sticky & ((unsigned long)SIZEOF_VOIDP-1)) + \
73                                 (unsigned long)omGetTopBinOfPage(page))
74 #define omSetTopBinAndStickyOfPage(page, bin, sticky) \
75   (page)->bin_sticky= (void*)(((unsigned long)sticky & (SIZEOF_VOIDP-1)) \
76                                + (unsigned long)bin)
77 
78 #define omGetTopBinOfAddr(addr) \
79   omGetTopBinOfPage(((omBinPage) omGetPageOfAddr(addr)))
80 #define omGetBinOfAddr(addr) omGetBinOfPage(omGetBinPageOfAddr(addr))
81 
82 #ifndef OM_GENERATE_INC
83 extern omBin_t om_StaticBin[];
84 extern omBin om_Size2Bin[];
85 #ifdef OM_ALIGNMENT_NEEDS_WORK
86 extern omBin om_Size2AlignedBin[];
87 #endif
88 
89 /*******************************************************************
90  *
91  *  SizeOfAddr
92  *
93  *******************************************************************/
94 #ifdef OM_INTERNAL_DEBUG
95 size_t omSizeOfBinAddr(void* addr);
96 #else
97 #define omSizeOfBinAddr(addr) _omSizeOfBinAddr(addr)
98 #endif
99 
100 #define omSizeWOfBin(bin_ptr) ((bin_ptr)->sizeW)
101 
102 #define _omSizeOfBinAddr(addr)  ((omSizeWOfBinAddr(addr)) << LOG_SIZEOF_LONG)
103 #define omSizeWOfBinAddr(addr) ((omGetTopBinOfAddr(addr))->sizeW)
104 
105 /*******************************************************************
106  *
107  *  lowest level alloc/free macros
108  *
109  *******************************************************************/
110 extern void* omAllocBinFromFullPage(omBin bin);
111 extern void  omFreeToPageFault(omBinPage page, void* addr);
112 
113 /*******************************************************************/
114 /* Page                                                            */
115 #define __omTypeAllocFromNonEmptyPage(type, addr, page) \
116 do                                                      \
117 {                                                       \
118   ((page)->used_blocks)++;                              \
119   addr = (type)((page)->current);                       \
120   (page)->current =  *((void**) (page)->current);       \
121 }                                                       \
122 while (0)
123 
124 #define __omFreeToPage(addr, page)              \
125 do                                              \
126 {                                               \
127   if ((page)->used_blocks > 0L)                 \
128   {                                             \
129     *((void**) (addr)) = (page)->current;       \
130     ((page)->used_blocks)--;                    \
131     (page)->current = (addr);                   \
132   }                                             \
133   else                                          \
134   {                                             \
135     omFreeToPageFault(page, addr);              \
136   }                                             \
137 }                                               \
138 while (0)
139 
140 
141 /*******************************************************************/
142 /* Bin                                                             */
143 #define __omTypeAllocBin(type, addr, bin)                   \
144 do                                                          \
145 {                                                           \
146   REGISTER omBinPage __om_page = (bin)->current_page;       \
147   if (__om_page->current != NULL)                           \
148     __omTypeAllocFromNonEmptyPage(type, addr, __om_page);   \
149   else                                                      \
150     addr = (type) omAllocBinFromFullPage(bin);              \
151 }                                                           \
152 while (0)
153 
154 #define __omTypeAlloc0Bin(type, addr, bin)      \
155 do                                              \
156 {                                               \
157   __omTypeAllocBin(type, addr, bin);            \
158   omMemsetW(addr, 0, (bin)->sizeW);             \
159 }                                               \
160 while (0)
161 
162 
163 #define __omFreeBinAddr(addr)                                   \
164 do                                                              \
165 {                                                               \
166   REGISTER void* __om_addr = (void*) (addr);                    \
167   REGISTER omBinPage __om_page = omGetBinPageOfAddr(__om_addr); \
168   __omFreeToPage(__om_addr, __om_page);                         \
169 }                                                               \
170 while (0)
171 
172 #define __omTypeReallocBin(old_addr, old_bin, new_type, new_addr, new_bin)                              \
173 do                                                                                                      \
174 {                                                                                                       \
175   if (old_bin != new_bin)                                                                               \
176   {                                                                                                     \
177     size_t old_sizeW = (omIsNormalBinPageAddr(old_addr) ? old_bin->sizeW : omSizeWOfAddr(old_addr));    \
178     __omTypeAllocBin(new_type, new_addr, new_bin);                                                      \
179     omMemcpyW(new_addr, old_addr, (new_bin->sizeW > old_sizeW ? old_sizeW : new_bin->sizeW));           \
180     __omFreeBinAddr(old_addr);                                                                     \
181   }                                                                                                     \
182   else                                                                                                  \
183   {                                                                                                     \
184     new_addr = (new_type) old_addr;                                                                     \
185   }                                                                                                     \
186 }                                                                                                       \
187 while (0)
188 
189 
190 #define __omTypeRealloc0Bin(old_addr, old_bin, new_type, new_addr, new_bin)                             \
191 do                                                                                                      \
192 {                                                                                                       \
193   if (old_bin != new_bin)                                                                               \
194   {                                                                                                     \
195     size_t old_sizeW = (omIsNormalBinPageAddr(old_addr) ? old_bin->sizeW : omSizeWOfAddr(old_addr));    \
196     __omTypeAllocBin(new_type, new_addr, new_bin);                                                      \
197     omMemcpyW(new_addr, old_addr, (new_bin->sizeW > old_sizeW ? old_sizeW : new_bin->sizeW));           \
198     if (new_bin->sizeW > old_sizeW)                                                                     \
199        omMemsetW((void**)new_addr + old_sizeW, 0, new_bin->sizeW - old_sizeW);                          \
200     __omFreeBinAddr(old_addr);                                                                     \
201   }                                                                                                     \
202   else                                                                                                  \
203   {                                                                                                     \
204     new_addr = (new_type) old_addr;                                                                     \
205   }                                                                                                     \
206 }                                                                                                       \
207 while (0)
208 
209 /*******************************************************************/
210 /* Size                                                            */
211 #define omSmallSize2Bin(size) om_Size2Bin[((size) -1)>>LOG_SIZEOF_OM_ALIGNMENT]
212 
213 #define __omTypeAlloc(type, addr, size)         \
214 do                                              \
215 {                                               \
216   size_t __size = size;                         \
217   if (__size <= OM_MAX_BLOCK_SIZE)              \
218   {                                             \
219     omBin __om_bin = omSmallSize2Bin(__size);   \
220     __omTypeAllocBin(type, addr, __om_bin);     \
221   }                                             \
222   else                                          \
223   {                                             \
224     addr = (type) omAllocLarge(__size);         \
225   }                                             \
226 }                                               \
227 while(0)
228 
229 #define __omTypeAlloc0(type, addr, size)        \
230 do                                              \
231 {                                               \
232   size_t __size = size;                         \
233   if (__size <= OM_MAX_BLOCK_SIZE)              \
234   {                                             \
235     omBin __om_bin = omSmallSize2Bin(__size);   \
236     __omTypeAlloc0Bin(type, addr, __om_bin);    \
237   }                                             \
238   else                                          \
239   {                                             \
240     addr = (type) omAlloc0Large(__size);        \
241   }                                             \
242 }                                               \
243 while (0)
244 
245 #ifdef OM_ALIGNMENT_NEEDS_WORK
246 #define omSmallSize2AlignedBin(size) om_Size2AlignedBin[((size) -1)>>LOG_SIZEOF_OM_ALIGNMENT]
247 
248 #define __omTypeAllocAligned(type, addr, size)          \
249 do                                                      \
250 {                                                       \
251   size_t __size = size;                                 \
252   if (__size <= OM_MAX_BLOCK_SIZE)                      \
253   {                                                     \
254     omBin __om_bin = omSmallSize2AlignedBin(__size);    \
255     __omTypeAllocBin(type, addr, __om_bin);             \
256   }                                                     \
257   else                                                  \
258   {                                                     \
259     addr = (type) omAllocLarge(__size);                 \
260   }                                                     \
261 }                                                       \
262 while(0)
263 
264 #define __omTypeAlloc0Aligned(type, addr, size)         \
265 do                                                      \
266 {                                                       \
267   size_t __size = size;                                 \
268   if (__size <= OM_MAX_BLOCK_SIZE)                      \
269   {                                                     \
270     omBin __om_bin = omSmallSize2AlignedBin(__size);    \
271     __omTypeAlloc0Bin(type, addr, __om_bin);            \
272   }                                                     \
273   else                                                  \
274   {                                                     \
275     addr = (type) omAlloc0Large(__size);                \
276   }                                                     \
277 }                                                       \
278 while (0)
279 #else
280 #define __omTypeAllocAligned    __omTypeAlloc
281 #define __omTypeAlloc0Aligned   __omTypeAlloc0
282 #endif /* OM_ALIGNMENT_NEEDS_WORK */
283 
284 #define __omFreeSize(addr, size)                            \
285 do                                                          \
286 {                                                           \
287   if ((size <= OM_MAX_BLOCK_SIZE) || omIsBinPageAddr(addr)) \
288   {                                                         \
289     __omFreeBinAddr(addr);                                  \
290   }                                                         \
291   else                                                      \
292   {                                                         \
293     omFreeLarge(addr);                                      \
294   }                                                         \
295 }                                                           \
296 while (0)
297 
298 #define __omFree(addr)                          \
299 do                                              \
300 {                                               \
301   if (omIsBinPageAddr(addr))                    \
302   {                                             \
303     __omFreeBinAddr(addr);                         \
304   }                                             \
305   else                                          \
306   {                                             \
307     omFreeLarge(addr);                          \
308   }                                             \
309 }                                               \
310 while (0)
311 
312 void* omDoRealloc(void* old_addr, size_t new_size, int flags);
313 
314 #define ___omTypeRealloc(old_addr, new_type, new_addr, new_size, SIZE_2_BIN, REALLOC_BIN, flags)    \
315 do                                                                                                  \
316 {                                                                                                   \
317   size_t __new_size = new_size;                                                                     \
318   if (__new_size <= OM_MAX_BLOCK_SIZE && omIsBinPageAddr(old_addr))                                 \
319   {                                                                                                 \
320     omBin __old_bin = omGetBinOfAddr(old_addr);                                                     \
321     omBin __new_bin = SIZE_2_BIN(__new_size);                                                       \
322     REALLOC_BIN(old_addr, __old_bin, new_type, new_addr, __new_bin);                                \
323   }                                                                                                 \
324   else                                                                                              \
325   {                                                                                                 \
326     new_addr = (new_type) omDoRealloc(old_addr, __new_size, flags);                                 \
327   }                                                                                                 \
328 }                                                                                                   \
329 while (0)
330 
331 #define ___omTypeReallocSize(old_addr, old_size, new_type, new_addr, new_size, SIZE_2_BIN, REALLOC_BIN, flags)  \
332 do                                                                                                              \
333 {                                                                                                               \
334   size_t __new_size = new_size;                                                                                 \
335   if (__new_size <= OM_MAX_BLOCK_SIZE && old_size <= OM_MAX_BLOCK_SIZE)                                         \
336   {                                                                                                             \
337     omBin __old_bin = omGetBinOfAddr(old_addr);                                                                 \
338     omBin __new_bin = SIZE_2_BIN(__new_size);                                                                   \
339     REALLOC_BIN(old_addr, __old_bin, new_type, new_addr, __new_bin);                                            \
340   }                                                                                                             \
341   else                                                                                                          \
342   {                                                                                                             \
343     new_addr = (new_type) omDoRealloc(old_addr, __new_size, flags);                                             \
344   }                                                                                                             \
345 }                                                                                                               \
346 while (0)
347 
348 #define __omTypeRealloc(old_addr, new_type, new_addr, new_size)                 \
349   ___omTypeRealloc(old_addr, new_type, new_addr, new_size, omSmallSize2Bin, __omTypeReallocBin, 0)
350 #define __omTypeRealloc0(old_addr, new_type, new_addr, new_size)                \
351   ___omTypeRealloc(old_addr, new_type, new_addr, new_size, omSmallSize2Bin, __omTypeRealloc0Bin, 1)
352 #define __omTypeReallocSize(old_addr, old_size, new_type, new_addr, new_size)     \
353   ___omTypeReallocSize(old_addr, old_size, new_type, new_addr, new_size, omSmallSize2Bin, __omTypeReallocBin, 0)
354 #define __omTypeRealloc0Size(old_addr, old_size, new_type, new_addr, new_size)    \
355   ___omTypeReallocSize(old_addr, old_size, new_type, new_addr, new_size, omSmallSize2Bin, __omTypeRealloc0Bin, 1)
356 
357 #ifdef OM_ALIGNMENT_NEEDS_WORK
358 #define __omTypeReallocAligned(old_addr, new_type, new_addr, new_size)                 \
359   ___omTypeRealloc(old_addr, new_type, new_addr, new_size, omSmallSize2AlignedBin, __omTypeReallocBin, 2)
360 #define __omTypeRealloc0Aligned(old_addr, new_type, new_addr, new_size)                \
361   ___omTypeRealloc(old_addr, new_type, new_addr, new_size, omSmallSize2AlignedBin, __omTypeRealloc0Bin, 3)
362 #define __omTypeReallocAlignedSize(old_addr, old_size, new_type, new_addr, new_size)     \
363   ___omTypeReallocSize(old_addr, old_size, new_type, new_addr, new_size, omSmallSize2AlignedBin, __omTypeReallocBin, 2)
364 #define __omTypeRealloc0AlignedSize(old_addr, old_size, new_type, new_addr, new_size)    \
365   ___omTypeReallocSize(old_addr, old_size, new_type, new_addr, new_size, omSmallSize2AlignedBin, __omTypeRealloc0Bin, 3)
366 #else
367 #define __omTypeReallocAligned      __omTypeRealloc
368 #define __omTypeRealloc0Aligned     __omTypeRealloc0
369 #define __omTypeReallocAlignedSize      __omTypeReallocSize
370 #define __omTypeRealloc0AlignedSize     __omTypeRealloc0Size
371 #endif
372 
373 #endif /* OM_GENERATE_INC */
374 #endif /* OM_ALLOC_PRIVATE_H */
375