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_ */
717