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