1 | /******************************************************************* |
---|
2 | * File: omAlloc.c |
---|
3 | * Purpose: implementation of main omalloc functions |
---|
4 | * Author: obachman@mathematik.uni-kl.de (Olaf Bachmann) |
---|
5 | * Created: 11/99 |
---|
6 | * Version: $Id: omAlloc.c,v 1.11 2000-12-12 15:26:14 obachman Exp $ |
---|
7 | *******************************************************************/ |
---|
8 | #ifndef OM_ALLOC_C |
---|
9 | #define OM_ALLOC_C |
---|
10 | |
---|
11 | #include "om_Alloc.h" |
---|
12 | /******************************************************************* |
---|
13 | * |
---|
14 | * global variables |
---|
15 | * |
---|
16 | *******************************************************************/ |
---|
17 | |
---|
18 | omBinPage_t om_ZeroPage[] = {{0, NULL, NULL, NULL, NULL}}; |
---|
19 | omSpecBin om_SpecBin = NULL; |
---|
20 | |
---|
21 | #include "omTables.inc" |
---|
22 | |
---|
23 | |
---|
24 | /******************************************************************* |
---|
25 | * |
---|
26 | * Local stuff |
---|
27 | * |
---|
28 | *******************************************************************/ |
---|
29 | |
---|
30 | /* Get new page and initialize */ |
---|
31 | static omBinPage omAllocNewBinPage(omBin bin) |
---|
32 | { |
---|
33 | omBinPage newpage; |
---|
34 | void* tmp; |
---|
35 | int i = 1; |
---|
36 | |
---|
37 | if (bin->max_blocks > 0) newpage = omAllocBinPage(); |
---|
38 | else newpage = omAllocBinPages(-bin->max_blocks); |
---|
39 | |
---|
40 | omAssume(omIsAddrPageAligned((void*) newpage)); |
---|
41 | |
---|
42 | omSetTopBinAndStickyOfPage(newpage, bin, bin->sticky); |
---|
43 | newpage->used_blocks = -1; |
---|
44 | newpage->current = (void*) (((void*)newpage) + SIZEOF_OM_BIN_PAGE_HEADER); |
---|
45 | tmp = newpage->current; |
---|
46 | while (i < bin->max_blocks) |
---|
47 | { |
---|
48 | tmp = *((void**)tmp) = ((void**) tmp) + bin->sizeW; |
---|
49 | i++; |
---|
50 | } |
---|
51 | *((void**)tmp) = NULL; |
---|
52 | omAssume(omListLength(newpage->current) == |
---|
53 | (bin->max_blocks > 1 ? bin->max_blocks : 1)); |
---|
54 | return newpage; |
---|
55 | } |
---|
56 | |
---|
57 | /* primitives for handling of list of pages */ |
---|
58 | OM_INLINE_LOCAL void omTakeOutBinPage(omBinPage page, omBin bin) |
---|
59 | { |
---|
60 | if (bin->current_page == page) |
---|
61 | { |
---|
62 | if (page->next == NULL) |
---|
63 | { |
---|
64 | if (page->prev == NULL) |
---|
65 | { |
---|
66 | omAssume(bin->last_page == page); |
---|
67 | bin->last_page = NULL; |
---|
68 | bin->current_page = om_ZeroPage; |
---|
69 | return; |
---|
70 | } |
---|
71 | bin->current_page = page->prev; |
---|
72 | } |
---|
73 | else |
---|
74 | bin->current_page = page->next; |
---|
75 | } |
---|
76 | if (bin->last_page == page) |
---|
77 | { |
---|
78 | omAssume(page->prev != NULL && page->next == NULL); |
---|
79 | bin->last_page = page->prev; |
---|
80 | } |
---|
81 | else |
---|
82 | { |
---|
83 | omAssume(page->next != NULL); |
---|
84 | page->next->prev = page->prev; |
---|
85 | } |
---|
86 | if (page->prev != NULL) page->prev->next = page->next; |
---|
87 | } |
---|
88 | |
---|
89 | OM_INLINE_LOCAL void omInsertBinPage(omBinPage after, omBinPage page, omBin bin) |
---|
90 | { |
---|
91 | if (bin->current_page == om_ZeroPage) |
---|
92 | { |
---|
93 | omAssume(bin->last_page == NULL); |
---|
94 | page->next = NULL; |
---|
95 | page->prev = NULL; |
---|
96 | bin->current_page = page; |
---|
97 | bin->last_page = page; |
---|
98 | } |
---|
99 | else |
---|
100 | { |
---|
101 | omAssume(after != NULL && bin->last_page != NULL); |
---|
102 | if (after == bin->last_page) |
---|
103 | { |
---|
104 | bin->last_page = page; |
---|
105 | } |
---|
106 | else |
---|
107 | { |
---|
108 | omAssume(after->next != NULL); |
---|
109 | after->next->prev = page; |
---|
110 | } |
---|
111 | page->next = after->next; |
---|
112 | after->next = page; |
---|
113 | page->prev = after; |
---|
114 | } |
---|
115 | } |
---|
116 | |
---|
117 | /* bin->current_page is empty, get new bin->current_page, return addr*/ |
---|
118 | void* omAllocBinFromFullPage(omBin bin) |
---|
119 | { |
---|
120 | void* addr; |
---|
121 | omBinPage newpage; |
---|
122 | omAssume(bin->current_page->current == NULL); |
---|
123 | |
---|
124 | if (bin->current_page != om_ZeroPage) |
---|
125 | { |
---|
126 | omAssume(bin->last_page != NULL); |
---|
127 | /* Set this to zero, but preserve the first bit, |
---|
128 | so that tracking works */ |
---|
129 | #ifdef OM_HAVE_TRACK |
---|
130 | bin->current_page->used_blocks &= (((unsigned long) 1) << (BIT_SIZEOF_LONG -1)); |
---|
131 | #else |
---|
132 | bin->current_page->used_blocks = 0; |
---|
133 | #endif |
---|
134 | } |
---|
135 | |
---|
136 | if (!bin->sticky && bin->current_page->next != NULL) |
---|
137 | { |
---|
138 | omAssume(bin->current_page->next->current != NULL); |
---|
139 | newpage = bin->current_page->next; |
---|
140 | } |
---|
141 | else |
---|
142 | { |
---|
143 | // need to Allocate new page |
---|
144 | newpage = omAllocNewBinPage(bin); |
---|
145 | omInsertBinPage(bin->current_page, newpage, bin); |
---|
146 | } |
---|
147 | |
---|
148 | bin->current_page = newpage; |
---|
149 | omAssume(newpage != NULL && newpage != om_ZeroPage && |
---|
150 | newpage->current != NULL); |
---|
151 | __omTypeAllocFromNonEmptyPage(void*, addr, newpage); |
---|
152 | return addr; |
---|
153 | } |
---|
154 | |
---|
155 | |
---|
156 | /* page->used_blocks <= 0, so, either free page or reallocate to |
---|
157 | the right of current_page */ |
---|
158 | /* |
---|
159 | * Now: there are three different strategies here, on what to do with |
---|
160 | * pages which were full and now have a free block: |
---|
161 | * 1.) Insert at the end (default) |
---|
162 | * 2.) Insert after current_page => #define PAGE_AFTER_CURRENT |
---|
163 | * 3.) Let it be new current_page => #define PAGE_BEFORE_CURRENT |
---|
164 | * Still need to try out which is best |
---|
165 | */ |
---|
166 | void omFreeToPageFault(omBinPage page, void* addr) |
---|
167 | { |
---|
168 | omBin bin; |
---|
169 | omAssume(page->used_blocks <= 0); |
---|
170 | |
---|
171 | #ifdef OM_HAVE_TRACK |
---|
172 | if (page->used_blocks < 0) |
---|
173 | { |
---|
174 | omFreeTrackAddr(addr); |
---|
175 | return; |
---|
176 | } |
---|
177 | #endif |
---|
178 | |
---|
179 | bin = omGetBinOfPage(page); |
---|
180 | if (page->current != NULL || bin->max_blocks <= 1) |
---|
181 | { |
---|
182 | // all blocks of page are now collected |
---|
183 | omTakeOutBinPage(page, bin); |
---|
184 | // page can be freed |
---|
185 | if (bin->max_blocks > 0) |
---|
186 | omFreeBinPage(page); |
---|
187 | else |
---|
188 | omFreeBinPages(page, - bin->max_blocks); |
---|
189 | #ifdef OM_HAVE_TRACK |
---|
190 | om_JustFreedPage = page; |
---|
191 | #endif |
---|
192 | } |
---|
193 | else |
---|
194 | { |
---|
195 | // page was full |
---|
196 | page->current = addr; |
---|
197 | page->used_blocks = bin->max_blocks - 2; |
---|
198 | *((void**)addr) = NULL; |
---|
199 | |
---|
200 | omTakeOutBinPage(page, bin); |
---|
201 | #if defined(PAGE_BEFORE_CURRENT) |
---|
202 | if (bin->current_page->prev != NULL) |
---|
203 | omInsertBinPage(bin->current_page->prev, page); |
---|
204 | else |
---|
205 | omInsertBinPage(bin->current_page, page, bin); |
---|
206 | bin->current_page = page; |
---|
207 | #else |
---|
208 | # if defined(PAGE_AFTER_CURRENT) |
---|
209 | omInsertBinPage(bin->current_page, page, bin); |
---|
210 | # else |
---|
211 | omInsertBinPage(bin->last_page, page, bin); |
---|
212 | # endif |
---|
213 | #endif |
---|
214 | } |
---|
215 | } |
---|
216 | |
---|
217 | /******************************************************************* |
---|
218 | * |
---|
219 | * DoRealloc |
---|
220 | * |
---|
221 | *******************************************************************/ |
---|
222 | #ifdef OM_ALIGNMNET_NEEDS_WORK |
---|
223 | #define DO_ZERO(flag) (flag & 1) |
---|
224 | #else |
---|
225 | #define DO_ZERO(flag) flag |
---|
226 | #endif |
---|
227 | |
---|
228 | void* omDoRealloc(void* old_addr, size_t new_size, int flag) |
---|
229 | { |
---|
230 | void* new_addr; |
---|
231 | |
---|
232 | if (!omIsBinPageAddr(old_addr) && new_size > OM_MAX_BLOCK_SIZE) |
---|
233 | { |
---|
234 | if (DO_ZERO(flag)) |
---|
235 | return omRealloc0Large(old_addr, new_size); |
---|
236 | else |
---|
237 | return omReallocLarge(old_addr, new_size); |
---|
238 | } |
---|
239 | else |
---|
240 | { |
---|
241 | size_t old_size = omSizeOfAddr(old_addr); |
---|
242 | size_t min_size; |
---|
243 | |
---|
244 | omAssume(OM_IS_ALIGNED(old_addr)); |
---|
245 | |
---|
246 | #ifdef OM_ALIGNMENT_NEEDS_WORK |
---|
247 | if (flag & 2) |
---|
248 | __omTypeAllocAligned(void*, new_addr, new_size); |
---|
249 | else |
---|
250 | #endif |
---|
251 | __omTypeAlloc(void*, new_addr, new_size); |
---|
252 | |
---|
253 | new_size = omSizeOfAddr(new_addr); |
---|
254 | min_size = (old_size < new_size ? old_size : new_size); |
---|
255 | omMemcpyW(new_addr, old_addr, min_size >> LOG_SIZEOF_LONG); |
---|
256 | |
---|
257 | if (DO_ZERO(flag) && (new_size > old_size)) |
---|
258 | omMemsetW((void*) new_addr + min_size, 0, (new_size - old_size) >> LOG_SIZEOF_LONG); |
---|
259 | |
---|
260 | __omFreeSize(old_addr, old_size); |
---|
261 | |
---|
262 | return new_addr; |
---|
263 | } |
---|
264 | } |
---|
265 | |
---|
266 | #endif /* OM_ALLOC_C */ |
---|