1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
1 |
// Copyright (C) 2000 - 2002 Hewlett-Packard Company
|
2 |
//
|
|
3 |
// This program is free software; you can redistribute it and/or modify it
|
|
4 |
// under the term of the GNU Lesser General Public License as published by the
|
|
5 |
// Free Software Foundation; either version 2 of the License, or (at your
|
|
6 |
// option) any later version.
|
|
7 |
//
|
|
8 |
// This program is distributed in the hope that it will be useful, but WITHOUT
|
|
9 |
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
10 |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
11 |
// for more details.
|
|
12 |
//
|
|
13 |
// You should have received a copy of the GNU Lesser General Public License
|
|
14 |
// along with this program; if not, write to the Free Software Foundation,
|
|
15 |
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
16 |
// _________________
|
|
17 |
||
18 |
// @(#) $Revision: 4.51 $ $Source: /judy/src/JudyCommon/JudyFreeArray.c $
|
|
19 |
//
|
|
20 |
// Judy1FreeArray() and JudyLFreeArray() functions for Judy1 and JudyL.
|
|
21 |
// Compile with one of -DJUDY1 or -DJUDYL.
|
|
22 |
// Return the number of bytes freed from the array.
|
|
23 |
||
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
24 |
#if (! (defined(JUDY1) || defined(JUDYL)))
|
25 |
#error: One of -DJUDY1 or -DJUDYL must be specified.
|
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
26 |
#endif
|
27 |
||
28 |
#ifdef JUDY1
|
|
29 |
#include "Judy1.h" |
|
30 |
#else
|
|
31 |
#include "JudyL.h" |
|
32 |
#endif
|
|
33 |
||
34 |
#include "JudyPrivate1L.h" |
|
35 |
||
36 |
DBGCODE(extern void JudyCheckPop(Pvoid_t PArray);) |
|
37 |
||
38 |
||
39 |
// ****************************************************************************
|
|
40 |
// J U D Y 1 F R E E A R R A Y
|
|
41 |
// J U D Y L F R E E A R R A Y
|
|
42 |
//
|
|
43 |
// See the Judy*(3C) manual entry for details.
|
|
44 |
//
|
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
45 |
// This code is written recursively, at least at first, because thats much
|
46 |
// simpler. Hope its fast enough.
|
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
47 |
|
48 |
#ifdef JUDY1
|
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
49 |
FUNCTION Word_t Judy1FreeArray |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
50 |
#else
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
51 |
FUNCTION Word_t JudyLFreeArray |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
52 |
#endif
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
53 |
(
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
54 |
PPvoid_t PPArray, // array to free. |
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
55 |
PJError_t PJError // optional, for returning error info. |
56 |
)
|
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
57 |
{
|
58 |
jpm_t jpm; // local to accumulate free statistics. |
|
59 |
||
60 |
// CHECK FOR NULL POINTER (error by caller):
|
|
61 |
||
62 |
if (PPArray == (PPvoid_t) NULL) |
|
63 |
{
|
|
64 |
JU_SET_ERRNO(PJError, JU_ERRNO_NULLPPARRAY); |
|
65 |
return(JERR); |
|
66 |
}
|
|
67 |
||
68 |
DBGCODE(JudyCheckPop(*PPArray);) |
|
69 |
||
70 |
// Zero jpm.jpm_Pop0 (meaning the array will be empty in a moment) for accurate
|
|
71 |
// logging in TRACEMI2.
|
|
72 |
||
73 |
jpm.jpm_Pop0 = 0; // see above. |
|
74 |
jpm.jpm_TotalMemWords = 0; // initialize memory freed. |
|
75 |
||
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
76 |
// Empty array:
|
77 |
||
78 |
if (P_JLW(*PPArray) == (Pjlw_t) NULL) return(0); |
|
79 |
||
80 |
// PROCESS TOP LEVEL "JRP" BRANCHES AND LEAF:
|
|
81 |
||
82 |
if (JU_LEAFW_POP0(*PPArray) < cJU_LEAFW_MAXPOP1) // must be a LEAFW |
|
83 |
{
|
|
84 |
Pjlw_t Pjlw = P_JLW(*PPArray); // first word of leaf. |
|
85 |
||
86 |
j__udyFreeJLW(Pjlw, Pjlw[0] + 1, &jpm); |
|
87 |
*PPArray = (Pvoid_t) NULL; // make an empty array. |
|
88 |
return (-(jpm.jpm_TotalMemWords * cJU_BYTESPERWORD)); // see above. |
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
89 |
}
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
90 |
else
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
91 |
|
92 |
// Rootstate leaves: just free the leaf:
|
|
93 |
||
94 |
// Common code for returning the amount of memory freed.
|
|
95 |
//
|
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
96 |
// Note: In a an ordinary LEAFW, pop0 = *PPArray[0].
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
97 |
//
|
98 |
// Accumulate (negative) words freed, while freeing objects.
|
|
99 |
// Return the positive bytes freed.
|
|
100 |
||
101 |
{
|
|
102 |
Pjpm_t Pjpm = P_JPM(*PPArray); |
|
103 |
Word_t TotalMem = Pjpm->jpm_TotalMemWords; |
|
104 |
||
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
105 |
j__udyFreeSM(&(Pjpm->jpm_JP), &jpm); // recurse through tree. |
106 |
j__udyFreeJPM(Pjpm, &jpm); |
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
107 |
|
108 |
// Verify the array was not corrupt. This means that amount of memory freed
|
|
109 |
// (which is negative) is equal to the initial amount:
|
|
110 |
||
111 |
if (TotalMem + jpm.jpm_TotalMemWords) |
|
112 |
{
|
|
113 |
JU_SET_ERRNO(PJError, JU_ERRNO_CORRUPT); |
|
114 |
return(JERR); |
|
115 |
}
|
|
116 |
||
117 |
*PPArray = (Pvoid_t) NULL; // make an empty array. |
|
118 |
return (TotalMem * cJU_BYTESPERWORD); |
|
119 |
}
|
|
120 |
||
121 |
} // Judy1FreeArray() / JudyLFreeArray() |
|
122 |
||
123 |
||
124 |
// ****************************************************************************
|
|
125 |
// __ J U D Y F R E E S M
|
|
126 |
//
|
|
127 |
// Given a pointer to a JP, recursively visit and free (depth first) all nodes
|
|
128 |
// in a Judy array BELOW the JP, but not the JP itself. Accumulate in *Pjpm
|
|
129 |
// the total words freed (as a negative value). "SM" = State Machine.
|
|
130 |
//
|
|
131 |
// Note: Corruption is not detected at this level because during a FreeArray,
|
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
132 |
// if the code hasnt already core dumped, its better to remain silent, even
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
133 |
// if some memory has not been freed, than to bother the caller about the
|
134 |
// corruption. TBD: Is this true? If not, must list all legitimate JPNULL
|
|
135 |
// and JPIMMED above first, and revert to returning bool_t (see 4.34).
|
|
136 |
||
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
137 |
FUNCTION void j__udyFreeSM( |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
138 |
Pjp_t Pjp, // top of Judy (top-state). |
139 |
Pjpm_t Pjpm) // to return words freed. |
|
140 |
{
|
|
141 |
Word_t Pop1; |
|
142 |
||
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
143 |
switch (JU_JPTYPE(Pjp)) |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
144 |
{
|
145 |
||
146 |
#ifdef JUDY1
|
|
147 |
||
148 |
// FULL EXPANSE -- nothing to free for this jp_Type.
|
|
149 |
||
150 |
case cJ1_JPFULLPOPU1: |
|
151 |
break; |
|
152 |
#endif
|
|
153 |
||
154 |
// JUDY BRANCH -- free the sub-tree depth first:
|
|
155 |
||
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
156 |
// LINEAR BRANCH -- visit each JP in the JBLs list, then free the JBL:
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
157 |
//
|
158 |
// Note: There are no null JPs in a JBL.
|
|
159 |
||
160 |
case cJU_JPBRANCH_L: |
|
161 |
case cJU_JPBRANCH_L2: |
|
162 |
case cJU_JPBRANCH_L3: |
|
163 |
#ifdef JU_64BIT
|
|
164 |
case cJU_JPBRANCH_L4: |
|
165 |
case cJU_JPBRANCH_L5: |
|
166 |
case cJU_JPBRANCH_L6: |
|
167 |
case cJU_JPBRANCH_L7: |
|
168 |
#endif // JU_64BIT |
|
169 |
{
|
|
170 |
Pjbl_t Pjbl = P_JBL(Pjp->jp_Addr); |
|
171 |
Word_t offset; |
|
172 |
||
173 |
for (offset = 0; offset < Pjbl->jbl_NumJPs; ++offset) |
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
174 |
j__udyFreeSM((Pjbl->jbl_jp) + offset, Pjpm); |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
175 |
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
176 |
j__udyFreeJBL((Pjbl_t) (Pjp->jp_Addr), Pjpm); |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
177 |
break; |
178 |
}
|
|
179 |
||
180 |
||
181 |
// BITMAP BRANCH -- visit each JP in the JBBs list based on the bitmap, also
|
|
182 |
//
|
|
183 |
// Note: There are no null JPs in a JBB.
|
|
184 |
||
185 |
case cJU_JPBRANCH_B: |
|
186 |
case cJU_JPBRANCH_B2: |
|
187 |
case cJU_JPBRANCH_B3: |
|
188 |
#ifdef JU_64BIT
|
|
189 |
case cJU_JPBRANCH_B4: |
|
190 |
case cJU_JPBRANCH_B5: |
|
191 |
case cJU_JPBRANCH_B6: |
|
192 |
case cJU_JPBRANCH_B7: |
|
193 |
#endif // JU_64BIT |
|
194 |
{
|
|
195 |
Word_t subexp; |
|
196 |
Word_t offset; |
|
197 |
Word_t jpcount; |
|
198 |
||
199 |
Pjbb_t Pjbb = P_JBB(Pjp->jp_Addr); |
|
200 |
||
201 |
for (subexp = 0; subexp < cJU_NUMSUBEXPB; ++subexp) |
|
202 |
{
|
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
203 |
jpcount = j__udyCountBitsB(JU_JBB_BITMAP(Pjbb, subexp)); |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
204 |
|
205 |
if (jpcount) |
|
206 |
{
|
|
207 |
for (offset = 0; offset < jpcount; ++offset) |
|
208 |
{
|
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
209 |
j__udyFreeSM(P_JP(JU_JBB_PJP(Pjbb, subexp)) + offset, |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
210 |
Pjpm); |
211 |
}
|
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
212 |
j__udyFreeJBBJP(JU_JBB_PJP(Pjbb, subexp), jpcount, Pjpm); |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
213 |
}
|
214 |
}
|
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
215 |
j__udyFreeJBB((Pjbb_t) (Pjp->jp_Addr), Pjpm); |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
216 |
|
217 |
break; |
|
218 |
}
|
|
219 |
||
220 |
||
221 |
// UNCOMPRESSED BRANCH -- visit each JP in the JBU array, then free the JBU
|
|
222 |
// itself:
|
|
223 |
//
|
|
224 |
// Note: Null JPs are handled during recursion at a lower state.
|
|
225 |
||
226 |
case cJU_JPBRANCH_U: |
|
227 |
case cJU_JPBRANCH_U2: |
|
228 |
case cJU_JPBRANCH_U3: |
|
229 |
#ifdef JU_64BIT
|
|
230 |
case cJU_JPBRANCH_U4: |
|
231 |
case cJU_JPBRANCH_U5: |
|
232 |
case cJU_JPBRANCH_U6: |
|
233 |
case cJU_JPBRANCH_U7: |
|
234 |
#endif // JU_64BIT |
|
235 |
{
|
|
236 |
Word_t offset; |
|
237 |
Pjbu_t Pjbu = P_JBU(Pjp->jp_Addr); |
|
238 |
||
239 |
for (offset = 0; offset < cJU_BRANCHUNUMJPS; ++offset) |
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
240 |
j__udyFreeSM((Pjbu->jbu_jp) + offset, Pjpm); |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
241 |
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
242 |
j__udyFreeJBU((Pjbu_t) (Pjp->jp_Addr), Pjpm); |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
243 |
break; |
244 |
}
|
|
245 |
||
246 |
||
247 |
// -- Cases below here terminate and do not recurse. --
|
|
248 |
||
249 |
||
250 |
// LINEAR LEAF -- just free the leaf; size is computed from jp_Type:
|
|
251 |
//
|
|
252 |
// Note: cJU_JPLEAF1 is a special case, see discussion in ../Judy1/Judy1.h
|
|
253 |
||
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
254 |
#if (defined(JUDYL) || (! defined(JU_64BIT)))
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
255 |
case cJU_JPLEAF1: |
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
256 |
Pop1 = JU_JPLEAF_POP0(Pjp) + 1; |
257 |
j__udyFreeJLL1((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm); |
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
258 |
break; |
259 |
#endif
|
|
260 |
||
261 |
case cJU_JPLEAF2: |
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
262 |
Pop1 = JU_JPLEAF_POP0(Pjp) + 1; |
263 |
j__udyFreeJLL2((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm); |
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
264 |
break; |
265 |
||
266 |
case cJU_JPLEAF3: |
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
267 |
Pop1 = JU_JPLEAF_POP0(Pjp) + 1; |
268 |
j__udyFreeJLL3((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm); |
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
269 |
break; |
270 |
||
271 |
#ifdef JU_64BIT
|
|
272 |
case cJU_JPLEAF4: |
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
273 |
Pop1 = JU_JPLEAF_POP0(Pjp) + 1; |
274 |
j__udyFreeJLL4((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm); |
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
275 |
break; |
276 |
||
277 |
case cJU_JPLEAF5: |
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
278 |
Pop1 = JU_JPLEAF_POP0(Pjp) + 1; |
279 |
j__udyFreeJLL5((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm); |
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
280 |
break; |
281 |
||
282 |
case cJU_JPLEAF6: |
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
283 |
Pop1 = JU_JPLEAF_POP0(Pjp) + 1; |
284 |
j__udyFreeJLL6((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm); |
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
285 |
break; |
286 |
||
287 |
case cJU_JPLEAF7: |
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
288 |
Pop1 = JU_JPLEAF_POP0(Pjp) + 1; |
289 |
j__udyFreeJLL7((Pjll_t) (Pjp->jp_Addr), Pop1, Pjpm); |
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
290 |
break; |
291 |
#endif // JU_64BIT |
|
292 |
||
293 |
||
294 |
// BITMAP LEAF -- free sub-expanse arrays of JPs, then free the JBB.
|
|
295 |
||
296 |
case cJU_JPLEAF_B1: |
|
297 |
{
|
|
298 |
#ifdef JUDYL
|
|
299 |
Word_t subexp; |
|
300 |
Word_t jpcount; |
|
301 |
Pjlb_t Pjlb = P_JLB(Pjp->jp_Addr); |
|
302 |
||
303 |
// Free the value areas in the bitmap leaf:
|
|
304 |
||
305 |
for (subexp = 0; subexp < cJU_NUMSUBEXPL; ++subexp) |
|
306 |
{
|
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
307 |
jpcount = j__udyCountBitsL(JU_JLB_BITMAP(Pjlb, subexp)); |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
308 |
|
309 |
if (jpcount) |
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
310 |
j__udyLFreeJV(JL_JLB_PVALUE(Pjlb, subexp), jpcount, Pjpm); |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
311 |
}
|
312 |
#endif // JUDYL |
|
313 |
||
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
314 |
j__udyFreeJLB1((Pjlb_t) (Pjp->jp_Addr), Pjpm); |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
315 |
break; |
316 |
||
317 |
} // case cJU_JPLEAF_B1 |
|
318 |
||
319 |
#ifdef JUDYL
|
|
320 |
||
321 |
||
322 |
// IMMED*:
|
|
323 |
//
|
|
324 |
// For JUDYL, all non JPIMMED_*_01s have a LeafV which must be freed:
|
|
325 |
||
326 |
case cJU_JPIMMED_1_02: |
|
327 |
case cJU_JPIMMED_1_03: |
|
328 |
#ifdef JU_64BIT
|
|
329 |
case cJU_JPIMMED_1_04: |
|
330 |
case cJU_JPIMMED_1_05: |
|
331 |
case cJU_JPIMMED_1_06: |
|
332 |
case cJU_JPIMMED_1_07: |
|
333 |
#endif
|
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
334 |
Pop1 = JU_JPTYPE(Pjp) - cJU_JPIMMED_1_02 + 2; |
335 |
j__udyLFreeJV((Pjv_t) (Pjp->jp_Addr), Pop1, Pjpm); |
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
336 |
break; |
337 |
||
338 |
#ifdef JU_64BIT
|
|
339 |
case cJU_JPIMMED_2_02: |
|
340 |
case cJU_JPIMMED_2_03: |
|
341 |
||
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
342 |
Pop1 = JU_JPTYPE(Pjp) - cJU_JPIMMED_2_02 + 2; |
343 |
j__udyLFreeJV((Pjv_t) (Pjp->jp_Addr), Pop1, Pjpm); |
|
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
344 |
break; |
345 |
||
346 |
case cJU_JPIMMED_3_02: |
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
347 |
j__udyLFreeJV((Pjv_t) (Pjp->jp_Addr), 2, Pjpm); |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
348 |
break; |
349 |
||
350 |
#endif // JU_64BIT |
|
351 |
#endif // JUDYL |
|
352 |
||
353 |
||
354 |
// OTHER JPNULL, JPIMMED, OR UNEXPECTED TYPE -- nothing to free for this type:
|
|
355 |
//
|
|
356 |
// Note: Lump together no-op and invalid JP types; see function header
|
|
357 |
// comments.
|
|
358 |
||
359 |
default: break; |
|
360 |
||
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
361 |
} // switch (JU_JPTYPE(Pjp)) |
1
by Theodore Y. Ts'o
Import upstream version 0.0.4 |
362 |
|
1.1.1
by Troy Heber
Import upstream version 1.0.1 |
363 |
} // j__udyFreeSM() |