1 /* $OpenBSD: rf_freelist.h,v 1.3 2002/12/16 07:01:04 tdeval Exp $ */
2 /* $NetBSD: rf_freelist.h,v 1.3 1999/02/05 00:06:11 oster Exp $ */
3
4 /*
5 * rf_freelist.h
6 */
7 /*
8 * Copyright (c) 1995 Carnegie-Mellon University.
9 * All rights reserved.
10 *
11 * Author: Jim Zelenka
12 *
13 * Permission to use, copy, modify and distribute this software and
14 * its documentation is hereby granted, provided that both the copyright
15 * notice and this permission notice appear in all copies of the
16 * software, derivative works or modified versions, and any portions
17 * thereof, and that both notices appear in supporting documentation.
18 *
19 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
20 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
21 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
22 *
23 * Carnegie Mellon requests users of this software to return to
24 *
25 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
26 * School of Computer Science
27 * Carnegie Mellon University
28 * Pittsburgh PA 15213-3890
29 *
30 * any improvements or extensions that they make and grant Carnegie the
31 * rights to redistribute these changes.
32 */
33
34 /*
35 * rf_freelist.h -- Code to manage counted freelists.
36 *
37 * Keep an arena of fixed-size objects. When a new object is needed,
38 * allocate it as necessary. When an object is freed, either put it
39 * in the arena, or really free it, depending on the maximum arena
40 * size.
41 */
42
43 #ifndef _RF__RF_FREELIST_H_
44 #define _RF__RF_FREELIST_H_
45
46 #include "rf_types.h"
47 #include "rf_debugMem.h"
48 #include "rf_general.h"
49 #include "rf_threadstuff.h"
50
51 #define RF_FREELIST_STATS 0
52
53 #if RF_FREELIST_STATS > 0
54 typedef struct RF_FreeListStats_s {
55 char *file;
56 int line;
57 int allocations;
58 int frees;
59 int max_free;
60 int grows;
61 int outstanding;
62 int max_outstanding;
63 } RF_FreeListStats_t;
64
65 #define RF_FREELIST_STAT_INIT(_fl_) \
66 do { \
67 bzero((char *)&((_fl_)->stats), sizeof(RF_FreeListStats_t)); \
68 (_fl_)->stats.file = __FILE__; \
69 (_fl_)->stats.line = __LINE__; \
70 } while (0)
71
72 #define RF_FREELIST_STAT_ALLOC(_fl_) \
73 do { \
74 (_fl_)->stats.allocations++; \
75 (_fl_)->stats.outstanding++; \
76 if ((_fl_)->stats.outstanding > (_fl_)->stats.max_outstanding) \
77 (_fl_)->stats.max_outstanding = \
78 (_fl_)->stats.outstanding; \
79 } while (0)
80
81 #define RF_FREELIST_STAT_FREE_UPDATE(_fl_) \
82 do { \
83 if ((_fl_)->free_cnt > (_fl_)->stats.max_free) \
84 (_fl_)->stats.max_free = (_fl_)->free_cnt; \
85 } while (0)
86
87 #define RF_FREELIST_STAT_FREE(_fl_) \
88 do { \
89 (_fl_)->stats.frees++; \
90 (_fl_)->stats.outstanding--; \
91 RF_FREELIST_STAT_FREE_UPDATE(_fl_); \
92 } while (0)
93
94 #define RF_FREELIST_STAT_GROW(_fl_) \
95 do { \
96 (_fl_)->stats.grows++; \
97 RF_FREELIST_STAT_FREE_UPDATE(_fl_); \
98 } while (0)
99
100 #define RF_FREELIST_STAT_REPORT(_fl_) \
101 do { \
102 printf("Freelist at %s %d (%s)\n", (_fl_)->stats.file, \
103 (_fl_)->stats.line, RF_STRING(_fl_)); \
104 printf(" %d allocations, %d frees\n", \
105 (_fl_)->stats.allocations, (_fl_)->stats.frees); \
106 printf(" %d grows\n", (_fl_)->stats.grows); \
107 printf(" %d outstanding\n", (_fl_)->stats.outstanding); \
108 printf(" %d free (max)\n", (_fl_)->stats.max_free); \
109 printf(" %d outstanding (max)\n", \
110 (_fl_)->stats.max_outstanding); \
111 } while (0)
112
113 #else /* RF_FREELIST_STATS > 0 */
114
115 #define RF_FREELIST_STAT_INIT(_fl_)
116 #define RF_FREELIST_STAT_ALLOC(_fl_)
117 #define RF_FREELIST_STAT_FREE_UPDATE(_fl_)
118 #define RF_FREELIST_STAT_FREE(_fl_)
119 #define RF_FREELIST_STAT_GROW(_fl_)
120 #define RF_FREELIST_STAT_REPORT(_fl_)
121
122 #endif /* RF_FREELIST_STATS > 0 */
123
124 struct RF_FreeList_s {
125 void *objlist; /* List of free obj. */
126 int free_cnt; /* How many free obj. */
127 int max_free_cnt; /* Max free arena size. */
128 int obj_inc; /* How many to allocate at a time. */
129 int obj_size; /* Size of objects. */
130 RF_DECLARE_MUTEX(lock);
131 #if RF_FREELIST_STATS > 0
132 RF_FreeListStats_t stats; /* Statistics. */
133 #endif /* RF_FREELIST_STATS > 0 */
134 };
135
136 /*
137 * fl = FreeList.
138 * maxcnt = Max number of items in arena.
139 * inc = How many to allocate at a time.
140 * size = Size of object.
141 */
142 #define RF_FREELIST_CREATE(_fl_,_maxcnt_,_inc_,_size_) \
143 do { \
144 int rc; \
145 RF_ASSERT((_inc_) > 0); \
146 RF_Malloc(_fl_, sizeof(RF_FreeList_t), (RF_FreeList_t *)); \
147 (_fl_)->objlist = NULL; \
148 (_fl_)->free_cnt = 0; \
149 (_fl_)->max_free_cnt = _maxcnt_; \
150 (_fl_)->obj_inc = _inc_; \
151 (_fl_)->obj_size = _size_; \
152 rc = rf_mutex_init(&(_fl_)->lock); \
153 if (rc) { \
154 RF_Free(_fl_, sizeof(RF_FreeList_t)); \
155 _fl_ = NULL; \
156 } \
157 RF_FREELIST_STAT_INIT(_fl_); \
158 } while (0)
159
160 /*
161 * fl = FreeList.
162 * cnt = Number to prime with.
163 * nextp = Name of "next" pointer in obj.
164 * cast = Object cast.
165 */
166 #define RF_FREELIST_PRIME(_fl_,_cnt_,_nextp_,_cast_) \
167 do { \
168 void *_p; \
169 int _i; \
170 RF_LOCK_MUTEX((_fl_)->lock); \
171 for (_i = 0; _i < (_cnt_); _i++) { \
172 RF_Calloc(_p, 1, (_fl_)->obj_size, (void *)); \
173 if (_p) { \
174 (_cast_(_p))->_nextp_ = (_fl_)->objlist; \
175 (_fl_)->objlist = _p; \
176 (_fl_)->free_cnt++; \
177 } \
178 else { \
179 break; \
180 } \
181 } \
182 RF_FREELIST_STAT_FREE_UPDATE(_fl_); \
183 RF_UNLOCK_MUTEX((_fl_)->lock); \
184 } while (0)
185
186 #define RF_FREELIST_MUTEX_OF(_fl_) ((_fl_)->lock)
187
188 #define RF_FREELIST_DO_UNLOCK(_fl_) RF_UNLOCK_MUTEX((_fl_)->lock)
189
190 #define RF_FREELIST_DO_LOCK(_fl_) RF_LOCK_MUTEX((_fl_)->lock)
191
192 /*
193 * fl = FreeList.
194 * cnt = Number to prime with.
195 * nextp = Name of "next" pointer in obj.
196 * cast = Object cast.
197 * init = Func to call to init obj.
198 */
199 #define RF_FREELIST_PRIME_INIT(_fl_,_cnt_,_nextp_,_cast_,_init_) \
200 do { \
201 void *_p; \
202 int _i; \
203 RF_LOCK_MUTEX((_fl_)->lock); \
204 for (_i = 0; _i < (_cnt_); _i++) { \
205 RF_Calloc(_p, 1, (_fl_)->obj_size, (void *)); \
206 if (_init_(_cast_ _p)) { \
207 RF_Free(_p, (_fl_)->obj_size); \
208 _p = NULL; \
209 } \
210 if (_p) { \
211 (_cast_(_p))->_nextp_ = (_fl_)->objlist; \
212 (_fl_)->objlist = _p; \
213 (_fl_)->free_cnt++; \
214 } \
215 else { \
216 break; \
217 } \
218 } \
219 RF_FREELIST_STAT_FREE_UPDATE(_fl_); \
220 RF_UNLOCK_MUTEX((_fl_)->lock); \
221 } while (0)
222
223 /*
224 * fl = FreeList.
225 * cnt = Number to prime with.
226 * nextp = Name of "next" pointer in obj.
227 * cast = Object cast.
228 * init = Func to call to init obj.
229 * arg = Arg to init obj func.
230 */
231 #define RF_FREELIST_PRIME_INIT_ARG(_fl_,_cnt_,_nextp_,_cast_,_init_,_arg_) \
232 do { \
233 void *_p; \
234 int _i; \
235 RF_LOCK_MUTEX((_fl_)->lock); \
236 for (_i = 0; _i < (_cnt_); _i++) { \
237 RF_Calloc(_p, 1, (_fl_)->obj_size, (void *)); \
238 if (_init_(_cast_ _p, _arg_)) { \
239 RF_Free(_p, (_fl_)->obj_size); \
240 _p = NULL; \
241 } \
242 if (_p) { \
243 (_cast_(_p))->_nextp_ = (_fl_)->objlist; \
244 (_fl_)->objlist = _p; \
245 (_fl_)->free_cnt++; \
246 } \
247 else { \
248 break; \
249 } \
250 } \
251 RF_FREELIST_STAT_FREE_UPDATE(_fl_); \
252 RF_UNLOCK_MUTEX((_fl_)->lock); \
253 } while (0)
254
255 /*
256 * fl = FreeList.
257 * obj = Object to allocate.
258 * nextp = Name of "next" pointer in obj.
259 * cast = Cast of obj assignment.
260 * init = Init obj func.
261 */
262 #define RF_FREELIST_GET_INIT(_fl_,_obj_,_nextp_,_cast_,_init_) \
263 do { \
264 void *_p; \
265 int _i; \
266 RF_LOCK_MUTEX((_fl_)->lock); \
267 RF_ASSERT(sizeof(*(_obj_)) == ((_fl_)->obj_size)); \
268 if (_fl_->objlist) { \
269 _obj_ = _cast_((_fl_)->objlist); \
270 (_fl_)->objlist = (void *)((_obj_)->_nextp_); \
271 (_fl_)->free_cnt--; \
272 } \
273 else { \
274 /* \
275 * Allocate one at a time so we can free \
276 * one at a time without cleverness when arena \
277 * is full. \
278 */ \
279 RF_Calloc(_obj_, 1, (_fl_)->obj_size, _cast_); \
280 if (_obj_) { \
281 if (_init_(_obj_)) { \
282 RF_Free(_obj_, (_fl_)->obj_size); \
283 _obj_ = NULL; \
284 } \
285 else { \
286 for (_i = 1; _i < (_fl_)->obj_inc; \
287 _i++) { \
288 RF_Calloc(_p, 1, \
289 (_fl_)->obj_size, \
290 (void *)); \
291 if (_p) { \
292 if (_init_(_p)) { \
293 RF_Free(_p, \
294 (_fl_)->obj_size); \
295 _p = NULL; \
296 break; \
297 } \
298 (_cast_(_p))->_nextp_ = \
299 (_fl_)->objlist; \
300 (_fl_)->objlist = _p; \
301 } \
302 else { \
303 break; \
304 } \
305 } \
306 } \
307 } \
308 RF_FREELIST_STAT_GROW(_fl_); \
309 } \
310 RF_FREELIST_STAT_ALLOC(_fl_); \
311 RF_UNLOCK_MUTEX((_fl_)->lock); \
312 } while (0)
313
314 /*
315 * fl = FreeList.
316 * obj = Object to allocate.
317 * nextp = Name of "next" pointer in obj.
318 * cast = Cast of obj assignment.
319 * init = Init obj func.
320 * arg = Arg to init obj func.
321 */
322 #define RF_FREELIST_GET_INIT_ARG(_fl_,_obj_,_nextp_,_cast_,_init_,_arg_) \
323 do { \
324 void *_p; \
325 int _i; \
326 RF_LOCK_MUTEX((_fl_)->lock); \
327 RF_ASSERT(sizeof(*(_obj_)) == ((_fl_)->obj_size)); \
328 if (_fl_->objlist) { \
329 _obj_ = _cast_((_fl_)->objlist); \
330 (_fl_)->objlist = (void *)((_obj_)->_nextp_); \
331 (_fl_)->free_cnt--; \
332 } \
333 else { \
334 /* \
335 * Allocate one at a time so we can free \
336 * one at a time without cleverness when arena \
337 * is full. \
338 */ \
339 RF_Calloc(_obj_, 1, (_fl_)->obj_size, _cast_); \
340 if (_obj_) { \
341 if (_init_(_obj_, _arg_)) { \
342 RF_Free(_obj_, (_fl_)->obj_size); \
343 _obj_ = NULL; \
344 } \
345 else { \
346 for (_i = 1; _i < (_fl_)->obj_inc; \
347 _i++) { \
348 RF_Calloc(_p, 1, \
349 (_fl_)->obj_size, (void *)); \
350 if (_p) { \
351 if (_init_(_p, _arg_)) \
352 { \
353 RF_Free(_p, \
354 (_fl_)->obj_size); \
355 _p = NULL; \
356 break; \
357 } \
358 (_cast_(_p))->_nextp_ = \
359 (_fl_)->objlist; \
360 (_fl_)->objlist = _p; \
361 } \
362 else { \
363 break; \
364 } \
365 } \
366 } \
367 } \
368 RF_FREELIST_STAT_GROW(_fl_); \
369 } \
370 RF_FREELIST_STAT_ALLOC(_fl_); \
371 RF_UNLOCK_MUTEX((_fl_)->lock); \
372 } while (0)
373
374 /*
375 * fl = FreeList.
376 * obj = Object to allocate.
377 * nextp = Name of "next" pointer in obj.
378 * cast = Cast of obj assignment.
379 * init = Init obj func.
380 */
381 #define RF_FREELIST_GET_INIT_NOUNLOCK(_fl_,_obj_,_nextp_,_cast_,_init_) \
382 do { \
383 void *_p; \
384 int _i; \
385 RF_LOCK_MUTEX((_fl_)->lock); \
386 RF_ASSERT(sizeof(*(_obj_)) == ((_fl_)->obj_size)); \
387 if (_fl_->objlist) { \
388 _obj_ = _cast_((_fl_)->objlist); \
389 (_fl_)->objlist = (void *)((_obj_)->_nextp_); \
390 (_fl_)->free_cnt--; \
391 } \
392 else { \
393 /* \
394 * Allocate one at a time so we can free \
395 * one at a time without cleverness when arena \
396 * is full. \
397 */ \
398 RF_Calloc(_obj_, 1, (_fl_)->obj_size, _cast_); \
399 if (_obj_) { \
400 if (_init_(_obj_)) { \
401 RF_Free(_obj_, (_fl_)->obj_size); \
402 _obj_ = NULL; \
403 } \
404 else { \
405 for (_i = 1; _i < (_fl_)->obj_inc; \
406 _i++) { \
407 RF_Calloc(_p, 1, \
408 (_fl_)->obj_size, \
409 (void *)); \
410 if (_p) { \
411 if (_init_(_p)) { \
412 RF_Free(_p, \
413 (_fl_)->obj_size); \
414 _p = NULL; \
415 break; \
416 } \
417 (_cast_(_p))->_nextp_ = \
418 (_fl_)->objlist; \
419 (_fl_)->objlist = _p; \
420 } \
421 else { \
422 break; \
423 } \
424 } \
425 } \
426 } \
427 RF_FREELIST_STAT_GROW(_fl_); \
428 } \
429 RF_FREELIST_STAT_ALLOC(_fl_); \
430 } while (0)
431
432 /*
433 * fl = FreeList.
434 * obj = Object to allocate.
435 * nextp = Name of "next" pointer in obj.
436 * cast = Cast of obj assignment.
437 */
438 #define RF_FREELIST_GET(_fl_,_obj_,_nextp_,_cast_) \
439 do { \
440 void *_p; \
441 int _i; \
442 RF_LOCK_MUTEX((_fl_)->lock); \
443 RF_ASSERT(sizeof(*(_obj_)) == ((_fl_)->obj_size)); \
444 if (_fl_->objlist) { \
445 _obj_ = _cast_((_fl_)->objlist); \
446 (_fl_)->objlist = (void *)((_obj_)->_nextp_); \
447 (_fl_)->free_cnt--; \
448 } \
449 else { \
450 /* \
451 * Allocate one at a time so we can free \
452 * one at a time without cleverness when arena \
453 * is full. \
454 */ \
455 RF_Calloc(_obj_, 1, (_fl_)->obj_size, _cast_); \
456 if (_obj_) { \
457 for (_i = 1; _i < (_fl_)->obj_inc; _i++) { \
458 RF_Calloc(_p, 1, (_fl_)->obj_size, \
459 (void *)); \
460 if (_p) { \
461 (_cast_(_p))->_nextp_ = \
462 (_fl_)->objlist; \
463 (_fl_)->objlist = _p; \
464 } \
465 else { \
466 break; \
467 } \
468 } \
469 } \
470 RF_FREELIST_STAT_GROW(_fl_); \
471 } \
472 RF_FREELIST_STAT_ALLOC(_fl_); \
473 RF_UNLOCK_MUTEX((_fl_)->lock); \
474 } while (0)
475
476 /*
477 * fl = FreeList.
478 * obj = Object to allocate.
479 * nextp = Name of "next" pointer in obj.
480 * cast = Cast of obj assignment.
481 * num = Num objs to return.
482 */
483 #define RF_FREELIST_GET_N(_fl_,_obj_,_nextp_,_cast_,_num_) \
484 do { \
485 void *_p, *_l, *_f; \
486 int _i, _n; \
487 _l = _f = NULL; \
488 _n = 0; \
489 RF_LOCK_MUTEX((_fl_)->lock); \
490 RF_ASSERT(sizeof(*(_obj_)) == ((_fl_)->obj_size)); \
491 for (_n = 0; _n < _num_; _n++) { \
492 if (_fl_->objlist) { \
493 _obj_ = _cast_((_fl_)->objlist); \
494 (_fl_)->objlist = (void *)((_obj_)->_nextp_); \
495 (_fl_)->free_cnt--; \
496 } \
497 else { \
498 /* \
499 * Allocate one at a time so we can free \
500 * one at a time without cleverness when arena \
501 * is full. \
502 */ \
503 RF_Calloc(_obj_, 1, (_fl_)->obj_size, _cast_); \
504 if (_obj_) { \
505 for (_i = 1; _i < (_fl_)->obj_inc; \
506 _i++) { \
507 RF_Calloc(_p, 1, \
508 (_fl_)->obj_size, \
509 (void *)); \
510 if (_p) { \
511 (_cast_(_p))->_nextp_ = \
512 (_fl_)->objlist; \
513 (_fl_)->objlist = _p; \
514 } \
515 else { \
516 break; \
517 } \
518 } \
519 } \
520 RF_FREELIST_STAT_GROW(_fl_); \
521 } \
522 if (_f == NULL) \
523 _f = _obj_; \
524 if (_obj_) { \
525 (_cast_(_obj_))->_nextp_ = _l; \
526 _l = _obj_; \
527 RF_FREELIST_STAT_ALLOC(_fl_); \
528 } \
529 else { \
530 (_cast_(_f))->_nextp_ = (_fl_)->objlist; \
531 (_fl_)->objlist = _l; \
532 _n = _num_; \
533 } \
534 } \
535 RF_UNLOCK_MUTEX((_fl_)->lock); \
536 } while (0)
537
538 /*
539 * fl = FreeList.
540 * obj = Object to free.
541 * nextp = Name of "next" pointer in obj.
542 */
543 #define RF_FREELIST_FREE(_fl_,_obj_,_nextp_) \
544 do { \
545 RF_LOCK_MUTEX((_fl_)->lock); \
546 if ((_fl_)->free_cnt == (_fl_)->max_free_cnt) { \
547 RF_Free(_obj_, (_fl_)->obj_size); \
548 } \
549 else { \
550 RF_ASSERT((_fl_)->free_cnt < (_fl_)->max_free_cnt); \
551 (_obj_)->_nextp_ = (_fl_)->objlist; \
552 (_fl_)->objlist = (void *)(_obj_); \
553 (_fl_)->free_cnt++; \
554 } \
555 RF_FREELIST_STAT_FREE(_fl_); \
556 RF_UNLOCK_MUTEX((_fl_)->lock); \
557 } while (0)
558
559 /*
560 * fl = FreeList.
561 * obj = Object to free.
562 * nextp = Name of "next" pointer in obj.
563 * num = Num to free (debugging).
564 */
565 #define RF_FREELIST_FREE_N(_fl_,_obj_,_nextp_,_cast_,_num_) \
566 do { \
567 void *_no; \
568 int _n; \
569 _n = 0; \
570 RF_LOCK_MUTEX((_fl_)->lock); \
571 while(_obj_) { \
572 _no = (_cast_(_obj_))->_nextp_; \
573 if ((_fl_)->free_cnt == (_fl_)->max_free_cnt) { \
574 RF_Free(_obj_, (_fl_)->obj_size); \
575 } \
576 else { \
577 RF_ASSERT((_fl_)->free_cnt < \
578 (_fl_)->max_free_cnt); \
579 (_obj_)->_nextp_ = (_fl_)->objlist; \
580 (_fl_)->objlist = (void *)(_obj_); \
581 (_fl_)->free_cnt++; \
582 } \
583 _n++; \
584 _obj_ = _no; \
585 RF_FREELIST_STAT_FREE(_fl_); \
586 } \
587 RF_ASSERT(_n==(_num_)); \
588 RF_UNLOCK_MUTEX((_fl_)->lock); \
589 } while (0)
590
591 /*
592 * fl = FreeList.
593 * obj = Object to free.
594 * nextp = Name of "next" pointer in obj.
595 * clean = Undo for init.
596 */
597 #define RF_FREELIST_FREE_CLEAN(_fl_,_obj_,_nextp_,_clean_) \
598 do { \
599 RF_LOCK_MUTEX((_fl_)->lock); \
600 if ((_fl_)->free_cnt == (_fl_)->max_free_cnt) { \
601 _clean_(_obj_); \
602 RF_Free(_obj_, (_fl_)->obj_size); \
603 } \
604 else { \
605 RF_ASSERT((_fl_)->free_cnt < (_fl_)->max_free_cnt); \
606 (_obj_)->_nextp_ = (_fl_)->objlist; \
607 (_fl_)->objlist = (void *)(_obj_); \
608 (_fl_)->free_cnt++; \
609 } \
610 RF_FREELIST_STAT_FREE(_fl_); \
611 RF_UNLOCK_MUTEX((_fl_)->lock); \
612 } while (0)
613
614 /*
615 * fl = FreeList.
616 * obj = Object to free.
617 * nextp = Name of "next" pointer in obj.
618 * clean = Undo for init.
619 * arg = Arg for undo func.
620 */
621 #define RF_FREELIST_FREE_CLEAN_ARG(_fl_,_obj_,_nextp_,_clean_,_arg_) \
622 do { \
623 RF_LOCK_MUTEX((_fl_)->lock); \
624 if ((_fl_)->free_cnt == (_fl_)->max_free_cnt) { \
625 _clean_(_obj_, _arg_); \
626 RF_Free(_obj_, (_fl_)->obj_size); \
627 } \
628 else { \
629 RF_ASSERT((_fl_)->free_cnt < (_fl_)->max_free_cnt); \
630 (_obj_)->_nextp_ = (_fl_)->objlist; \
631 (_fl_)->objlist = (void *)(_obj_); \
632 (_fl_)->free_cnt++; \
633 } \
634 RF_FREELIST_STAT_FREE(_fl_); \
635 RF_UNLOCK_MUTEX((_fl_)->lock); \
636 } while (0)
637
638 /*
639 * fl = FreeList.
640 * obj = Object to free.
641 * nextp = Name of "next" pointer in obj.
642 * clean = Undo for init.
643 */
644 #define RF_FREELIST_FREE_CLEAN_NOUNLOCK(_fl_,_obj_,_nextp_,_clean_) \
645 do { \
646 RF_LOCK_MUTEX((_fl_)->lock); \
647 if ((_fl_)->free_cnt == (_fl_)->max_free_cnt) { \
648 _clean_(_obj_); \
649 RF_Free(_obj_, (_fl_)->obj_size); \
650 } \
651 else { \
652 RF_ASSERT((_fl_)->free_cnt < (_fl_)->max_free_cnt); \
653 (_obj_)->_nextp_ = (_fl_)->objlist; \
654 (_fl_)->objlist = (void *)(_obj_); \
655 (_fl_)->free_cnt++; \
656 } \
657 RF_FREELIST_STAT_FREE(_fl_); \
658 } while (0)
659
660 /*
661 * fl = FreeList.
662 * nextp = Name of "next" pointer in obj.
663 * cast = Cast to object type.
664 */
665 #define RF_FREELIST_DESTROY(_fl_,_nextp_,_cast_) \
666 do { \
667 void *_cur, *_next; \
668 RF_FREELIST_STAT_REPORT(_fl_); \
669 rf_mutex_destroy(&((_fl_)->lock)); \
670 for (_cur = (_fl_)->objlist; _cur; _cur = _next) { \
671 _next = (_cast_ _cur)->_nextp_; \
672 RF_Free(_cur, (_fl_)->obj_size); \
673 } \
674 RF_Free(_fl_, sizeof(RF_FreeList_t)); \
675 } while (0)
676
677 /*
678 * fl = FreeList.
679 * nextp = Name of "next" pointer in obj.
680 * cast = Cast to object type.
681 * clean = Func to undo obj init.
682 */
683 #define RF_FREELIST_DESTROY_CLEAN(_fl_,_nextp_,_cast_,_clean_) \
684 do { \
685 void *_cur, *_next; \
686 RF_FREELIST_STAT_REPORT(_fl_); \
687 rf_mutex_destroy(&((_fl_)->lock)); \
688 for (_cur = (_fl_)->objlist; _cur; _cur = _next) { \
689 _next = (_cast_ _cur)->_nextp_; \
690 _clean_(_cur); \
691 RF_Free(_cur, (_fl_)->obj_size); \
692 } \
693 RF_Free(_fl_, sizeof(RF_FreeList_t)); \
694 } while (0)
695
696 /*
697 * fl = FreeList.
698 * nextp = Name of "next" pointer in obj.
699 * cast = Cast to object type.
700 * clean = Func to undo obj init.
701 * arg = Arg for undo func.
702 */
703 #define RF_FREELIST_DESTROY_CLEAN_ARG(_fl_,_nextp_,_cast_,_clean_,_arg_) \
704 do { \
705 void *_cur, *_next; \
706 RF_FREELIST_STAT_REPORT(_fl_); \
707 rf_mutex_destroy(&((_fl_)->lock)); \
708 for (_cur = (_fl_)->objlist; _cur; _cur = _next) { \
709 _next = (_cast_ _cur)->_nextp_; \
710 _clean_(_cur, _arg_); \
711 RF_Free(_cur, (_fl_)->obj_size); \
712 } \
713 RF_Free(_fl_, sizeof(RF_FreeList_t)); \
714 } while (0)
715
716 #endif /* !_RF__RF_FREELIST_H_ */