#include "asterisk.h"#include "asterisk/_private.h"#include "asterisk/astobj2.h"#include "asterisk/utils.h"#include "asterisk/cli.h"#include <execinfo.h>
Go to the source code of this file.
Data Structures | |
| struct | __priv_data |
| struct | ao2_container |
| struct | astobj2 |
| struct | bucket |
| struct | bucket_list |
Defines | |
| #define | AO2_MAGIC 0xa570b123 |
| #define | EXTERNAL_OBJ(_p) ((_p) == NULL ? NULL : (_p)->user_data) |
| convert from a pointer _p to an astobj2 object | |
| #define | N1 20 |
| #define | REF_FILE "/tmp/refs" |
Enumerations | |
| enum | ao2_callback_type { DEFAULT, WITH_DATA } |
Functions | |
| static void * | __ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn, const char *file, int line, const char *funcname) |
| static void * | __ao2_callback (struct ao2_container *c, const enum search_flags flags, void *cb_fn, void *arg, void *data, enum ao2_callback_type type, char *tag, char *file, int line, const char *funcname) |
| static struct ao2_container * | __ao2_container_alloc (struct ao2_container *c, const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn) |
| static struct ao2_container * | __ao2_container_alloc (struct ao2_container *c, const uint n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn) |
| static void * | __ao2_iterator_next (struct ao2_iterator *a, struct bucket_list **q) |
| static struct bucket_list * | __ao2_link (struct ao2_container *c, void *user_data, const char *file, int line, const char *func) |
| static int | __ao2_ref (void *user_data, const int delta) |
| void * | _ao2_alloc (size_t data_size, ao2_destructor_fn destructor_fn) |
| void * | _ao2_alloc_debug (size_t data_size, ao2_destructor_fn destructor_fn, char *tag, const char *file, int line, const char *funcname, int ref_debug) |
| void * | _ao2_callback (struct ao2_container *c, const enum search_flags flags, ao2_callback_fn *cb_fn, void *arg) |
| void * | _ao2_callback_data (struct ao2_container *c, const enum search_flags flags, ao2_callback_data_fn *cb_fn, void *arg, void *data) |
| void * | _ao2_callback_data_debug (struct ao2_container *c, const enum search_flags flags, ao2_callback_data_fn *cb_fn, void *arg, void *data, char *tag, char *file, int line, const char *funcname) |
| void * | _ao2_callback_debug (struct ao2_container *c, const enum search_flags flags, ao2_callback_fn *cb_fn, void *arg, char *tag, char *file, int line, const char *funcname) |
| struct ao2_container * | _ao2_container_alloc (const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn) |
| struct ao2_container * | _ao2_container_alloc_debug (const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn, char *tag, char *file, int line, const char *funcname, int ref_debug) |
| void * | _ao2_find (struct ao2_container *c, void *arg, enum search_flags flags) |
| void * | _ao2_find_debug (struct ao2_container *c, void *arg, enum search_flags flags, char *tag, char *file, int line, const char *funcname) |
| void * | _ao2_iterator_next (struct ao2_iterator *a) |
| void * | _ao2_iterator_next_debug (struct ao2_iterator *a, char *tag, char *file, int line, const char *funcname) |
| void * | _ao2_link (struct ao2_container *c, void *user_data) |
| void * | _ao2_link_debug (struct ao2_container *c, void *user_data, char *tag, char *file, int line, const char *funcname) |
| int | _ao2_ref (void *user_data, const int delta) |
| int | _ao2_ref_debug (void *user_data, const int delta, char *tag, char *file, int line, const char *funcname) |
| void * | _ao2_unlink (struct ao2_container *c, void *user_data) |
| void * | _ao2_unlink_debug (struct ao2_container *c, void *user_data, char *tag, char *file, int line, const char *funcname) |
| void | ao2_bt (void) |
| int | ao2_container_count (struct ao2_container *c) |
| Returns the number of elements in a container. | |
| void | ao2_iterator_destroy (struct ao2_iterator *i) |
| Destroy a container iterator. | |
| struct ao2_iterator | ao2_iterator_init (struct ao2_container *c, int flags) |
| Create an iterator for a container. | |
| int | ao2_lock (void *user_data) |
| Lock an object. | |
| int | ao2_match_by_addr (void *user_data, void *arg, int flags) |
| another convenience function is a callback that matches on address | |
| void * | ao2_object_get_lockaddr (void *obj) |
| Return the lock address of an object. | |
| int | ao2_trylock (void *user_data) |
| Try locking-- (don't block if fail). | |
| int | ao2_unlock (void *user_data) |
| Unlock an object. | |
| int | astobj2_init (void) |
| static int | cb_true (void *user_data, void *arg, int flags) |
| special callback that matches all | |
| static int | cb_true_data (void *user_data, void *arg, void *data, int flags) |
| similar to cb_true, but is an ao2_callback_data_fn instead | |
| static int | cd_cb (void *obj, void *arg, int flag) |
| static int | cd_cb_debug (void *obj, void *arg, int flag) |
| static void | container_destruct (void *c) |
| static void | container_destruct_debug (void *c) |
| static int | hash_zero (const void *user_obj, const int flags) |
| always zero hash function | |
| static struct astobj2 * | INTERNAL_OBJ (void *user_data) |
| convert from a pointer _p to a user-defined object | |
| #define AO2_MAGIC 0xa570b123 |
Definition at line 51 of file astobj2.c.
Referenced by __ao2_alloc(), and INTERNAL_OBJ().
| #define EXTERNAL_OBJ | ( | _p | ) | ((_p) == NULL ? NULL : (_p)->user_data) |
convert from a pointer _p to an astobj2 object
Definition at line 133 of file astobj2.c.
Referenced by __ao2_alloc(), __ao2_callback(), and __ao2_iterator_next().
| #define N1 20 |
Referenced by ao2_bt().
| #define REF_FILE "/tmp/refs" |
Definition at line 28 of file astobj2.c.
Referenced by _ao2_alloc_debug(), and _ao2_ref_debug().
| enum ao2_callback_type |
| static void* __ao2_alloc | ( | size_t | data_size, | |
| ao2_destructor_fn | destructor_fn, | |||
| const char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) | [static] |
Definition at line 305 of file astobj2.c.
References __ast_calloc(), AO2_MAGIC, ast_atomic_fetchadd_int(), ast_calloc, ast_mutex_init(), __priv_data::data_size, __priv_data::destructor_fn, EXTERNAL_OBJ, __priv_data::lock, __priv_data::magic, astobj2::priv_data, and __priv_data::ref_counter.
Referenced by _ao2_alloc(), and _ao2_alloc_debug().
00306 { 00307 /* allocation */ 00308 struct astobj2 *obj; 00309 00310 if (data_size < sizeof(void *)) 00311 data_size = sizeof(void *); 00312 00313 #if defined(__AST_DEBUG_MALLOC) 00314 obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, funcname); 00315 #else 00316 obj = ast_calloc(1, sizeof(*obj) + data_size); 00317 #endif 00318 00319 if (obj == NULL) 00320 return NULL; 00321 00322 ast_mutex_init(&obj->priv_data.lock); 00323 obj->priv_data.magic = AO2_MAGIC; 00324 obj->priv_data.data_size = data_size; 00325 obj->priv_data.ref_counter = 1; 00326 obj->priv_data.destructor_fn = destructor_fn; /* can be NULL */ 00327 00328 #ifdef AO2_DEBUG 00329 ast_atomic_fetchadd_int(&ao2.total_objects, 1); 00330 ast_atomic_fetchadd_int(&ao2.total_mem, data_size); 00331 ast_atomic_fetchadd_int(&ao2.total_refs, 1); 00332 #endif 00333 00334 /* return a pointer to the user data */ 00335 return EXTERNAL_OBJ(obj); 00336 }
| static void * __ao2_callback | ( | struct ao2_container * | c, | |
| const enum search_flags | flags, | |||
| void * | cb_fn, | |||
| void * | arg, | |||
| void * | data, | |||
| enum ao2_callback_type | type, | |||
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) | [static] |
Browse the container using different stategies accoding the flags.
Definition at line 603 of file astobj2.c.
References _ao2_ref(), _ao2_ref_debug(), ao2_lock(), ao2_unlock(), ast_atomic_fetchadd_int(), AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, ast_log(), bucket_list::astobj, ao2_container::buckets, cb_true(), cb_true_data(), CMP_MATCH, CMP_STOP, ao2_container::elements, bucket_list::entry, EXTERNAL_OBJ, free, ao2_container::hash_fn, INTERNAL_OBJ(), last, LOG_WARNING, match(), ao2_container::n_buckets, OBJ_CONTINUE, OBJ_MULTIPLE, OBJ_NODATA, OBJ_POINTER, OBJ_UNLINK, ao2_container::version, and WITH_DATA.
Referenced by _ao2_callback(), _ao2_callback_data(), _ao2_callback_data_debug(), and _ao2_callback_debug().
00606 { 00607 int i, start, last; /* search boundaries */ 00608 void *ret = NULL; 00609 ao2_callback_fn *cb_default = NULL; 00610 ao2_callback_data_fn *cb_withdata = NULL; 00611 00612 if (INTERNAL_OBJ(c) == NULL) /* safety check on the argument */ 00613 return NULL; 00614 00615 if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) { 00616 ast_log(LOG_WARNING, "multiple data return not implemented yet (flags %x)\n", flags); 00617 return NULL; 00618 } 00619 00620 /* override the match function if necessary */ 00621 if (cb_fn == NULL) { /* if NULL, match everything */ 00622 if (type == WITH_DATA) { 00623 cb_withdata = cb_true_data; 00624 } else { 00625 cb_default = cb_true; 00626 } 00627 } else { 00628 /* We do this here to avoid the per object casting penalty (even though 00629 that is probably optimized away anyway. */ 00630 if (type == WITH_DATA) { 00631 cb_withdata = cb_fn; 00632 } else { 00633 cb_default = cb_fn; 00634 } 00635 } 00636 00637 /* 00638 * XXX this can be optimized. 00639 * If we have a hash function and lookup by pointer, 00640 * run the hash function. Otherwise, scan the whole container 00641 * (this only for the time being. We need to optimize this.) 00642 */ 00643 if ((flags & OBJ_POINTER)) /* we know hash can handle this case */ 00644 start = i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets; 00645 else /* don't know, let's scan all buckets */ 00646 start = i = -1; /* XXX this must be fixed later. */ 00647 00648 /* determine the search boundaries: i..last-1 */ 00649 if (i < 0) { 00650 start = i = 0; 00651 last = c->n_buckets; 00652 } else if ((flags & OBJ_CONTINUE)) { 00653 last = c->n_buckets; 00654 } else { 00655 last = i + 1; 00656 } 00657 00658 ao2_lock(c); /* avoid modifications to the content */ 00659 00660 for (; i < last ; i++) { 00661 /* scan the list with prev-cur pointers */ 00662 struct bucket_list *cur; 00663 00664 AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) { 00665 int match = (CMP_MATCH | CMP_STOP); 00666 00667 if (type == WITH_DATA) { 00668 match &= cb_withdata(EXTERNAL_OBJ(cur->astobj), arg, data, flags); 00669 } else { 00670 match &= cb_default(EXTERNAL_OBJ(cur->astobj), arg, flags); 00671 } 00672 00673 /* we found the object, performing operations according flags */ 00674 if (match == 0) { /* no match, no stop, continue */ 00675 continue; 00676 } else if (match == CMP_STOP) { /* no match but stop, we are done */ 00677 i = last; 00678 break; 00679 } 00680 /* we have a match (CMP_MATCH) here */ 00681 if (!(flags & OBJ_NODATA)) { /* if must return the object, record the value */ 00682 /* it is important to handle this case before the unlink */ 00683 ret = EXTERNAL_OBJ(cur->astobj); 00684 if (tag) 00685 _ao2_ref_debug(ret, 1, tag, file, line, funcname); 00686 else 00687 _ao2_ref(ret, 1); 00688 } 00689 00690 if (flags & OBJ_UNLINK) { /* must unlink */ 00691 struct bucket_list *x = cur; 00692 00693 /* we are going to modify the container, so update version */ 00694 ast_atomic_fetchadd_int(&c->version, 1); 00695 AST_LIST_REMOVE_CURRENT(entry); 00696 /* update number of elements and version */ 00697 ast_atomic_fetchadd_int(&c->elements, -1); 00698 if (tag) 00699 _ao2_ref_debug(EXTERNAL_OBJ(x->astobj), -1, tag, file, line, funcname); 00700 else 00701 _ao2_ref(EXTERNAL_OBJ(x->astobj), -1); 00702 free(x); /* free the link record */ 00703 } 00704 00705 if ((match & CMP_STOP) || (flags & OBJ_MULTIPLE) == 0) { 00706 /* We found the only match we need */ 00707 i = last; /* force exit from outer loop */ 00708 break; 00709 } 00710 if (!(flags & OBJ_NODATA)) { 00711 #if 0 /* XXX to be completed */ 00712 /* 00713 * This is the multiple-return case. We need to link 00714 * the object in a list. The refcount is already increased. 00715 */ 00716 #endif 00717 } 00718 } 00719 AST_LIST_TRAVERSE_SAFE_END; 00720 00721 if (ret) { 00722 /* This assumes OBJ_MULTIPLE with !OBJ_NODATA is still not implemented */ 00723 break; 00724 } 00725 00726 if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) { 00727 /* Move to the beginning to ensure we check every bucket */ 00728 i = -1; 00729 last = start; 00730 } 00731 } 00732 ao2_unlock(c); 00733 return ret; 00734 }
| static struct ao2_container* __ao2_container_alloc | ( | struct ao2_container * | c, | |
| const unsigned int | n_buckets, | |||
| ao2_hash_fn * | hash_fn, | |||
| ao2_callback_fn * | cmp_fn | |||
| ) | [static, read] |
Definition at line 425 of file astobj2.c.
References ast_atomic_fetchadd_int(), ao2_container::cmp_fn, ao2_container::hash_fn, hash_zero(), ao2_container::n_buckets, and ao2_container::version.
00427 { 00428 /* XXX maybe consistency check on arguments ? */ 00429 /* compute the container size */ 00430 00431 if (!c) 00432 return NULL; 00433 00434 c->version = 1; /* 0 is a reserved value here */ 00435 c->n_buckets = n_buckets; 00436 c->hash_fn = hash_fn ? hash_fn : hash_zero; 00437 c->cmp_fn = cmp_fn; 00438 00439 #ifdef AO2_DEBUG 00440 ast_atomic_fetchadd_int(&ao2.total_containers, 1); 00441 #endif 00442 00443 return c; 00444 }
| static struct ao2_container* __ao2_container_alloc | ( | struct ao2_container * | c, | |
| const uint | n_buckets, | |||
| ao2_hash_fn * | hash_fn, | |||
| ao2_callback_fn * | cmp_fn | |||
| ) | [static, read] |
Referenced by _ao2_container_alloc(), and _ao2_container_alloc_debug().
| static void * __ao2_iterator_next | ( | struct ao2_iterator * | a, | |
| struct bucket_list ** | q | |||
| ) | [static] |
Definition at line 804 of file astobj2.c.
References AO2_ITERATOR_DONTLOCK, ao2_lock(), AST_LIST_NEXT, AST_LIST_TRAVERSE, bucket_list::astobj, ao2_iterator::bucket, ao2_container::buckets, ao2_iterator::c, ao2_iterator::c_version, bucket_list::entry, EXTERNAL_OBJ, ao2_iterator::flags, INTERNAL_OBJ(), ao2_container::n_buckets, ao2_iterator::obj, bucket_list::version, ao2_iterator::version, and ao2_container::version.
Referenced by _ao2_iterator_next(), and _ao2_iterator_next_debug().
00805 { 00806 int lim; 00807 struct bucket_list *p = NULL; 00808 void *ret = NULL; 00809 00810 *q = NULL; 00811 00812 if (INTERNAL_OBJ(a->c) == NULL) 00813 return NULL; 00814 00815 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00816 ao2_lock(a->c); 00817 00818 /* optimization. If the container is unchanged and 00819 * we have a pointer, try follow it 00820 */ 00821 if (a->c->version == a->c_version && (p = a->obj) ) { 00822 if ( (p = AST_LIST_NEXT(p, entry)) ) 00823 goto found; 00824 /* nope, start from the next bucket */ 00825 a->bucket++; 00826 a->version = 0; 00827 a->obj = NULL; 00828 } 00829 00830 lim = a->c->n_buckets; 00831 00832 /* Browse the buckets array, moving to the next 00833 * buckets if we don't find the entry in the current one. 00834 * Stop when we find an element with version number greater 00835 * than the current one (we reset the version to 0 when we 00836 * switch buckets). 00837 */ 00838 for (; a->bucket < lim; a->bucket++, a->version = 0) { 00839 /* scan the current bucket */ 00840 AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) { 00841 if (p->version > a->version) 00842 goto found; 00843 } 00844 } 00845 00846 found: 00847 if (p) { 00848 a->version = p->version; 00849 a->obj = p; 00850 a->c_version = a->c->version; 00851 ret = EXTERNAL_OBJ(p->astobj); 00852 /* inc refcount of returned object */ 00853 *q = p; 00854 } 00855 00856 return ret; 00857 }
| static struct bucket_list * __ao2_link | ( | struct ao2_container * | c, | |
| void * | user_data, | |||
| const char * | file, | |||
| int | line, | |||
| const char * | func | |||
| ) | [static, read] |
Definition at line 494 of file astobj2.c.
References ao2_lock(), ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_TAIL, bucket_list::astobj, INTERNAL_OBJ(), OBJ_POINTER, and bucket_list::version.
Referenced by _ao2_link(), and _ao2_link_debug().
00495 { 00496 int i; 00497 /* create a new list entry */ 00498 struct bucket_list *p; 00499 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00500 00501 if (!obj) 00502 return NULL; 00503 00504 if (INTERNAL_OBJ(c) == NULL) 00505 return NULL; 00506 00507 p = ast_calloc(1, sizeof(*p)); 00508 if (!p) 00509 return NULL; 00510 00511 i = abs(c->hash_fn(user_data, OBJ_POINTER)); 00512 00513 ao2_lock(c); 00514 i %= c->n_buckets; 00515 p->astobj = obj; 00516 p->version = ast_atomic_fetchadd_int(&c->version, 1); 00517 AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry); 00518 ast_atomic_fetchadd_int(&c->elements, 1); 00519 00520 /* the last two operations (ao2_ref, ao2_unlock) must be done by the calling func */ 00521 return p; 00522 }
| static int __ao2_ref | ( | void * | user_data, | |
| const int | delta | |||
| ) | [static] |
Definition at line 259 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_log(), ast_mutex_destroy(), __priv_data::data_size, __priv_data::destructor_fn, free, INTERNAL_OBJ(), __priv_data::lock, LOG_ERROR, astobj2::priv_data, and __priv_data::ref_counter.
Referenced by _ao2_ref(), and _ao2_ref_debug().
00260 { 00261 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00262 int current_value; 00263 int ret; 00264 00265 /* if delta is 0, just return the refcount */ 00266 if (delta == 0) 00267 return (obj->priv_data.ref_counter); 00268 00269 /* we modify with an atomic operation the reference counter */ 00270 ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta); 00271 current_value = ret + delta; 00272 00273 #ifdef AO2_DEBUG 00274 ast_atomic_fetchadd_int(&ao2.total_refs, delta); 00275 #endif 00276 00277 /* this case must never happen */ 00278 if (current_value < 0) 00279 ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data); 00280 00281 if (current_value <= 0) { /* last reference, destroy the object */ 00282 if (obj->priv_data.destructor_fn != NULL) { 00283 obj->priv_data.destructor_fn(user_data); 00284 } 00285 00286 ast_mutex_destroy(&obj->priv_data.lock); 00287 #ifdef AO2_DEBUG 00288 ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size); 00289 ast_atomic_fetchadd_int(&ao2.total_objects, -1); 00290 #endif 00291 /* for safety, zero-out the astobj2 header and also the 00292 * first word of the user-data, which we make sure is always 00293 * allocated. */ 00294 memset(obj, '\0', sizeof(struct astobj2 *) + sizeof(void *) ); 00295 free(obj); 00296 } 00297 00298 return ret; 00299 }
| void* _ao2_alloc | ( | size_t | data_size, | |
| ao2_destructor_fn | destructor_fn | |||
| ) |
Definition at line 359 of file astobj2.c.
References __ao2_alloc().
Referenced by _ao2_container_alloc().
00360 { 00361 return __ao2_alloc(data_size, destructor_fn, __FILE__, __LINE__, __FUNCTION__); 00362 }
| void* _ao2_alloc_debug | ( | size_t | data_size, | |
| ao2_destructor_fn | destructor_fn, | |||
| char * | tag, | |||
| const char * | file, | |||
| int | line, | |||
| const char * | funcname, | |||
| int | ref_debug | |||
| ) |
Definition at line 338 of file astobj2.c.
References __ao2_alloc(), and REF_FILE.
Referenced by _ao2_container_alloc_debug(), and _moh_class_malloc().
00340 { 00341 /* allocation */ 00342 void *obj; 00343 FILE *refo = ref_debug ? fopen(REF_FILE,"a") : NULL; 00344 00345 obj = __ao2_alloc(data_size, destructor_fn, file, line, funcname); 00346 00347 if (obj == NULL) 00348 return NULL; 00349 00350 if (refo) { 00351 fprintf(refo, "%p =1 %s:%d:%s (%s)\n", obj, file, line, funcname, tag); 00352 fclose(refo); 00353 } 00354 00355 /* return a pointer to the user data */ 00356 return obj; 00357 }
| void* _ao2_callback | ( | struct ao2_container * | c, | |
| const enum search_flags | flags, | |||
| ao2_callback_fn * | cb_fn, | |||
| void * | arg | |||
| ) |
Definition at line 744 of file astobj2.c.
References __ao2_callback(), and DEFAULT.
Referenced by _ao2_find(), _ao2_unlink(), and container_destruct().
00746 { 00747 return __ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL); 00748 }
| void* _ao2_callback_data | ( | struct ao2_container * | c, | |
| const enum search_flags | flags, | |||
| ao2_callback_data_fn * | cb_fn, | |||
| void * | arg, | |||
| void * | data | |||
| ) |
Definition at line 758 of file astobj2.c.
References __ao2_callback(), and WITH_DATA.
00760 { 00761 return __ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL); 00762 }
| void* _ao2_callback_data_debug | ( | struct ao2_container * | c, | |
| const enum search_flags | flags, | |||
| ao2_callback_data_fn * | cb_fn, | |||
| void * | arg, | |||
| void * | data, | |||
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 750 of file astobj2.c.
References __ao2_callback(), and WITH_DATA.
00754 { 00755 return __ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, funcname); 00756 }
| void* _ao2_callback_debug | ( | struct ao2_container * | c, | |
| const enum search_flags | flags, | |||
| ao2_callback_fn * | cb_fn, | |||
| void * | arg, | |||
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 736 of file astobj2.c.
References __ao2_callback(), and DEFAULT.
Referenced by _ao2_find_debug(), _ao2_unlink_debug(), and container_destruct_debug().
00740 { 00741 return __ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, funcname); 00742 }
| struct ao2_container* _ao2_container_alloc | ( | const unsigned int | n_buckets, | |
| ao2_hash_fn * | hash_fn, | |||
| ao2_callback_fn * | cmp_fn | |||
| ) | [read] |
Definition at line 459 of file astobj2.c.
References __ao2_container_alloc(), _ao2_alloc(), and container_destruct().
00461 { 00462 /* XXX maybe consistency check on arguments ? */ 00463 /* compute the container size */ 00464 00465 size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket); 00466 struct ao2_container *c = _ao2_alloc(container_size, container_destruct); 00467 00468 return __ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn); 00469 }
| struct ao2_container* _ao2_container_alloc_debug | ( | const unsigned int | n_buckets, | |
| ao2_hash_fn * | hash_fn, | |||
| ao2_callback_fn * | cmp_fn, | |||
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname, | |||
| int | ref_debug | |||
| ) | [read] |
Definition at line 446 of file astobj2.c.
References __ao2_container_alloc(), _ao2_alloc_debug(), and container_destruct_debug().
00449 { 00450 /* XXX maybe consistency check on arguments ? */ 00451 /* compute the container size */ 00452 size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket); 00453 struct ao2_container *c = _ao2_alloc_debug(container_size, container_destruct_debug, tag, file, line, funcname, ref_debug); 00454 00455 return __ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn); 00456 }
| void* _ao2_find | ( | struct ao2_container * | c, | |
| void * | arg, | |||
| enum search_flags | flags | |||
| ) |
Definition at line 772 of file astobj2.c.
References _ao2_callback(), and ao2_container::cmp_fn.
Referenced by _get_mohbyname().
00773 { 00774 return _ao2_callback(c, flags, c->cmp_fn, arg); 00775 }
| void* _ao2_find_debug | ( | struct ao2_container * | c, | |
| void * | arg, | |||
| enum search_flags | flags, | |||
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
the find function just invokes the default callback with some reasonable flags.
Definition at line 767 of file astobj2.c.
References _ao2_callback_debug(), and ao2_container::cmp_fn.
Referenced by _get_mohbyname().
00768 { 00769 return _ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname); 00770 }
| void* _ao2_iterator_next | ( | struct ao2_iterator * | a | ) |
Definition at line 877 of file astobj2.c.
References __ao2_iterator_next(), _ao2_ref(), AO2_ITERATOR_DONTLOCK, ao2_unlock(), ao2_iterator::c, and ao2_iterator::flags.
00878 { 00879 struct bucket_list *p = NULL; 00880 void *ret = NULL; 00881 00882 ret = __ao2_iterator_next(a, &p); 00883 00884 if (p) { 00885 /* inc refcount of returned object */ 00886 _ao2_ref(ret, 1); 00887 } 00888 00889 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00890 ao2_unlock(a->c); 00891 00892 return ret; 00893 }
| void* _ao2_iterator_next_debug | ( | struct ao2_iterator * | a, | |
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 859 of file astobj2.c.
References __ao2_iterator_next(), _ao2_ref_debug(), AO2_ITERATOR_DONTLOCK, ao2_unlock(), ao2_iterator::c, and ao2_iterator::flags.
00860 { 00861 struct bucket_list *p; 00862 void *ret = NULL; 00863 00864 ret = __ao2_iterator_next(a, &p); 00865 00866 if (p) { 00867 /* inc refcount of returned object */ 00868 _ao2_ref_debug(ret, 1, tag, file, line, funcname); 00869 } 00870 00871 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00872 ao2_unlock(a->c); 00873 00874 return ret; 00875 }
| void* _ao2_link | ( | struct ao2_container * | c, | |
| void * | user_data | |||
| ) |
Definition at line 535 of file astobj2.c.
References __ao2_link(), _ao2_ref(), and ao2_unlock().
00536 { 00537 struct bucket_list *p = __ao2_link(c, user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__); 00538 00539 if (p) { 00540 _ao2_ref(user_data, +1); 00541 ao2_unlock(c); 00542 } 00543 return p; 00544 }
| void* _ao2_link_debug | ( | struct ao2_container * | c, | |
| void * | user_data, | |||
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 524 of file astobj2.c.
References __ao2_link(), _ao2_ref_debug(), and ao2_unlock().
00525 { 00526 struct bucket_list *p = __ao2_link(c, user_data, file, line, funcname); 00527 00528 if (p) { 00529 _ao2_ref_debug(user_data, +1, tag, file, line, funcname); 00530 ao2_unlock(c); 00531 } 00532 return p; 00533 }
| int _ao2_ref | ( | void * | user_data, | |
| const int | delta | |||
| ) |
Definition at line 249 of file astobj2.c.
References __ao2_ref(), and INTERNAL_OBJ().
Referenced by __ao2_callback(), _ao2_iterator_next(), _ao2_link(), and cd_cb().
00250 { 00251 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00252 00253 if (obj == NULL) 00254 return -1; 00255 00256 return __ao2_ref(user_data, delta); 00257 }
| int _ao2_ref_debug | ( | void * | user_data, | |
| const int | delta, | |||
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 229 of file astobj2.c.
References __ao2_ref(), __priv_data::destructor_fn, INTERNAL_OBJ(), astobj2::priv_data, __priv_data::ref_counter, and REF_FILE.
Referenced by __ao2_callback(), _ao2_iterator_next_debug(), _ao2_link_debug(), and cd_cb_debug().
00230 { 00231 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00232 00233 if (obj == NULL) 00234 return -1; 00235 00236 if (delta != 0) { 00237 FILE *refo = fopen(REF_FILE,"a"); 00238 fprintf(refo, "%p %s%d %s:%d:%s (%s) [@%d]\n", user_data, (delta<0? "":"+"), delta, file, line, funcname, tag, obj->priv_data.ref_counter); 00239 fclose(refo); 00240 } 00241 if (obj->priv_data.ref_counter + delta == 0 && obj->priv_data.destructor_fn != NULL) { /* this isn't protected with lock; just for o/p */ 00242 FILE *refo = fopen(REF_FILE,"a"); 00243 fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, funcname, tag); 00244 fclose(refo); 00245 } 00246 return __ao2_ref(user_data, delta); 00247 }
| void* _ao2_unlink | ( | struct ao2_container * | c, | |
| void * | user_data | |||
| ) |
Definition at line 569 of file astobj2.c.
References _ao2_callback(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.
00570 { 00571 if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */ 00572 return NULL; 00573 00574 _ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data); 00575 00576 return NULL; 00577 }
| void* _ao2_unlink_debug | ( | struct ao2_container * | c, | |
| void * | user_data, | |||
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 558 of file astobj2.c.
References _ao2_callback_debug(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.
00560 { 00561 if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */ 00562 return NULL; 00563 00564 _ao2_callback_debug(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data, tag, file, line, funcname); 00565 00566 return NULL; 00567 }
| void ao2_bt | ( | void | ) |
Definition at line 83 of file astobj2.c.
References ast_verbose, free, and N1.
00084 { 00085 int c, i; 00086 #define N1 20 00087 void *addresses[N1]; 00088 char **strings; 00089 00090 c = backtrace(addresses, N1); 00091 strings = backtrace_symbols(addresses,c); 00092 ast_verbose("backtrace returned: %d\n", c); 00093 for(i = 0; i < c; i++) { 00094 ast_verbose("%d: %p %s\n", i, addresses[i], strings[i]); 00095 } 00096 free(strings); 00097 }
| int ao2_container_count | ( | struct ao2_container * | c | ) |
Returns the number of elements in a container.
return the number of elements in the container
Definition at line 474 of file astobj2.c.
References ao2_container::elements.
Referenced by __queues_show(), _sip_show_peers(), ast_tone_zone_count(), cli_tps_report(), do_timing(), get_unused_callno(), lock_broker(), pthread_timer_open(), and unload_module().
00475 { 00476 return c->elements; 00477 }
| void ao2_iterator_destroy | ( | struct ao2_iterator * | i | ) |
Destroy a container iterator.
destroy an iterator
Definition at line 795 of file astobj2.c.
References ao2_ref, and ao2_iterator::c.
Referenced by __iax2_show_peers(), __queues_show(), _sip_show_peers(), alias_show(), authenticate_reply(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_list_devices(), compare_weight(), complete_iax2_peers(), complete_iax2_unregister(), complete_queue(), complete_queue_remove_member(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), complete_sipch(), delete_profiles(), delete_routes(), delete_users(), destroy_pvts(), dialgroup_read(), dump_queue_members(), find_queue_by_name_rt(), free_members(), get_member_status(), handle_cli_iax2_show_callno_limits(), handle_cli_iax2_show_users(), handle_cli_moh_show_classes(), handle_cli_moh_show_files(), handle_cli_odbc_show(), handle_request_subscribe(), handle_show_routes(), handle_statechange(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), manager_iax2_show_peer_list(), manager_queues_status(), manager_queues_summary(), num_available_members(), poke_all_peers(), pp_each_user_exec(), prune_peers(), prune_users(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), reload(), rt_handle_member_record(), set_member_paused(), set_member_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_channel(), sip_show_history(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), stop_streams(), try_calling(), unload_module(), update_queue(), and update_realtime_members().
| struct ao2_iterator ao2_iterator_init | ( | struct ao2_container * | c, | |
| int | flags | |||
| ) | [read] |
Create an iterator for a container.
initialize an iterator so we start from the first object
Definition at line 780 of file astobj2.c.
References ao2_ref, ao2_iterator::c, and ao2_iterator::flags.
Referenced by __iax2_show_peers(), __queues_show(), _sip_show_peers(), alias_show(), ast_tone_zone_iterator_init(), authenticate_reply(), check_access(), clear_queue(), clear_stats(), cli_console_active(), cli_list_devices(), cli_tps_report(), compare_weight(), complete_country(), complete_iax2_peers(), complete_iax2_unregister(), complete_queue(), complete_queue_remove_member(), complete_sip_peer(), complete_sip_registered_peer(), complete_sip_user(), complete_sipch(), delete_profiles(), delete_routes(), delete_users(), destroy_pvts(), dialgroup_read(), do_parking_thread(), dump_queue_members(), find_queue_by_name_rt(), free_members(), get_member_status(), handle_cli_iax2_show_callno_limits(), handle_cli_iax2_show_users(), handle_cli_moh_show_classes(), handle_cli_moh_show_files(), handle_cli_odbc_show(), handle_feature_show(), handle_parkedcalls(), handle_request_subscribe(), handle_show_routes(), handle_statechange(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), manager_iax2_show_peer_list(), manager_parking_status(), manager_queues_status(), manager_queues_summary(), num_available_members(), poke_all_peers(), pp_each_user_exec(), prune_peers(), prune_users(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), reload(), rt_handle_member_record(), set_member_paused(), set_member_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_channel(), sip_show_history(), sip_show_inuse(), sip_show_tcp(), sip_show_users(), stop_streams(), tps_taskprocessor_tab_complete(), try_calling(), unload_module(), update_queue(), and update_realtime_members().
00781 { 00782 struct ao2_iterator a = { 00783 .c = c, 00784 .flags = flags 00785 }; 00786 00787 ao2_ref(c, +1); 00788 00789 return a; 00790 }
| int ao2_lock | ( | void * | a | ) |
Lock an object.
| a | A pointer to the object we want to lock. |
Definition at line 147 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_lock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
Referenced by __ao2_callback(), __ao2_iterator_next(), __ao2_link(), __queues_show(), _sip_show_peers(), _sip_tcp_helper_thread(), add_calltoken_ignore(), add_to_queue(), ast_bridge_depart(), ast_bridge_destroy(), ast_bridge_dtmf_stream(), ast_bridge_merge(), ast_bridge_remove(), ast_bridge_suspend(), ast_bridge_unsuspend(), ast_get_indication_tone(), ast_get_indication_zone(), ast_register_indication_country(), ast_set_indication_country(), ast_taskprocessor_get(), ast_taskprocessor_unreference(), ast_unregister_indication_country(), attended_abort_transfer(), bridge_channel_join(), bridge_channel_join_multithreaded(), bridge_channel_join_singlethreaded(), bridge_thread(), build_callno_limits(), build_parkinglot(), clear_stats(), compare_weight(), complete_queue_remove_member(), complete_sip_user(), end_bridge_callback(), find_call(), find_queue_by_name_rt(), generic_thread_loop(), get_member_penalty(), get_member_status(), get_unused_callno(), handle_request_subscribe(), handle_statechange(), inprocess_count(), is_our_turn(), join_conference_bridge(), join_queue(), leave_conference_bridge(), leave_queue(), load_config(), load_indications(), load_realtime_queue(), manager_queues_status(), manager_queues_summary(), menu_callback(), moh_release(), mohalloc(), monmp3thread(), multiplexed_add_or_remove(), multiplexed_bridge_create(), multiplexed_bridge_destroy(), multiplexed_thread_function(), mwi_event_cb(), peercnt_add(), peercnt_remove(), play_prompt_to_channel(), post_join_marked(), post_join_unmarked(), pthread_timer_ack(), pthread_timer_disable_continuous(), pthread_timer_enable_continuous(), pthread_timer_get_event(), pthread_timer_open(), pthread_timer_set_rate(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_function_queuewaitingcount(), queue_function_var(), recalc_holdtime(), record_abandoned(), reload_queue_members(), reload_queues(), reload_single_queue(), remove_from_queue(), replace_callno(), ring_entry(), run_timer(), set_member_paused(), set_member_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_inuse(), sip_show_user(), sip_show_users(), sip_tcptls_write(), softmix_bridge_thread(), try_calling(), update_call_counter(), update_queue(), and update_realtime_members().
00151 { 00152 struct astobj2 *p = INTERNAL_OBJ(user_data); 00153 00154 if (p == NULL) 00155 return -1; 00156 00157 #ifdef AO2_DEBUG 00158 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00159 #endif 00160 00161 #ifndef DEBUG_THREADS 00162 return ast_mutex_lock(&p->priv_data.lock); 00163 #else 00164 return __ast_pthread_mutex_lock(file, line, func, var, &p->priv_data.lock); 00165 #endif 00166 }
| int ao2_match_by_addr | ( | void * | user_data, | |
| void * | arg, | |||
| int | flags | |||
| ) |
| void* ao2_object_get_lockaddr | ( | void * | obj | ) |
Return the lock address of an object.
| [in] | obj | A pointer to the object we want. |
This function comes in handy mainly for debugging locking situations, where the locking trace code reports the lock address, this allows you to correlate against object address, to match objects to reported locks.
Definition at line 214 of file astobj2.c.
References INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00215 { 00216 struct astobj2 *p = INTERNAL_OBJ(obj); 00217 00218 if (p == NULL) 00219 return NULL; 00220 00221 return &p->priv_data.lock; 00222 }
| int ao2_trylock | ( | void * | a | ) |
Try locking-- (don't block if fail).
| a | A pointer to the object we want to lock. |
Definition at line 191 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_trylock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00195 { 00196 struct astobj2 *p = INTERNAL_OBJ(user_data); 00197 int ret; 00198 00199 if (p == NULL) 00200 return -1; 00201 #ifndef DEBUG_THREADS 00202 ret = ast_mutex_trylock(&p->priv_data.lock); 00203 #else 00204 ret = __ast_pthread_mutex_trylock(file, line, func, var, &p->priv_data.lock); 00205 #endif 00206 00207 #ifdef AO2_DEBUG 00208 if (!ret) 00209 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00210 #endif 00211 return ret; 00212 }
| int ao2_unlock | ( | void * | a | ) |
Unlock an object.
| a | A pointer to the object we want unlock. |
Definition at line 169 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_unlock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
Referenced by __ao2_callback(), __queues_show(), _ao2_iterator_next(), _ao2_iterator_next_debug(), _ao2_link(), _ao2_link_debug(), _sip_show_peers(), _sip_tcp_helper_thread(), add_calltoken_ignore(), add_to_queue(), ast_bridge_depart(), ast_bridge_destroy(), ast_bridge_dtmf_stream(), ast_bridge_merge(), ast_bridge_remove(), ast_bridge_suspend(), ast_bridge_unsuspend(), ast_get_indication_tone(), ast_get_indication_zone(), ast_register_indication_country(), ast_set_indication_country(), ast_taskprocessor_get(), ast_taskprocessor_unreference(), ast_unregister_indication_country(), attended_abort_transfer(), bridge_channel_join(), bridge_channel_join_multithreaded(), bridge_channel_join_singlethreaded(), bridge_thread(), build_callno_limits(), build_parkinglot(), clear_stats(), compare_weight(), complete_queue_remove_member(), complete_sip_user(), end_bridge_callback(), find_call(), find_queue_by_name_rt(), generic_thread_loop(), get_member_penalty(), get_member_status(), get_unused_callno(), handle_request_subscribe(), handle_statechange(), inprocess_count(), is_our_turn(), join_conference_bridge(), join_queue(), leave_conference_bridge(), leave_queue(), load_config(), load_indications(), load_realtime_queue(), manager_queues_status(), manager_queues_summary(), menu_callback(), moh_release(), mohalloc(), monmp3thread(), multiplexed_add_or_remove(), multiplexed_bridge_create(), multiplexed_bridge_destroy(), multiplexed_thread_function(), mwi_event_cb(), peercnt_add(), peercnt_remove(), play_prompt_to_channel(), post_join_marked(), post_join_unmarked(), pthread_timer_ack(), pthread_timer_disable_continuous(), pthread_timer_enable_continuous(), pthread_timer_get_event(), pthread_timer_open(), pthread_timer_set_rate(), queue_function_qac(), queue_function_qac_dep(), queue_function_queuememberlist(), queue_function_queuewaitingcount(), queue_function_var(), recalc_holdtime(), record_abandoned(), reload_queue_members(), reload_queues(), reload_single_queue(), remove_from_queue(), replace_callno(), ring_entry(), run_timer(), set_member_paused(), set_member_penalty(), sip_poke_all_peers(), sip_prune_realtime(), sip_show_inuse(), sip_show_user(), sip_show_users(), sip_tcptls_write(), softmix_bridge_thread(), try_calling(), update_call_counter(), update_queue(), and update_realtime_members().
00173 { 00174 struct astobj2 *p = INTERNAL_OBJ(user_data); 00175 00176 if (p == NULL) 00177 return -1; 00178 00179 #ifdef AO2_DEBUG 00180 ast_atomic_fetchadd_int(&ao2.total_locked, -1); 00181 #endif 00182 00183 #ifndef DEBUG_THREADS 00184 return ast_mutex_unlock(&p->priv_data.lock); 00185 #else 00186 return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock); 00187 #endif 00188 }
| int astobj2_init | ( | void | ) |
Provided by astobj2.c
Definition at line 1081 of file astobj2.c.
References ARRAY_LEN, and ast_cli_register_multiple().
Referenced by main().
01082 { 01083 #ifdef AO2_DEBUG 01084 ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2)); 01085 #endif 01086 01087 return 0; 01088 }
| static int cb_true | ( | void * | user_data, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
special callback that matches all
Definition at line 582 of file astobj2.c.
References CMP_MATCH.
Referenced by __ao2_callback().
00583 { 00584 return CMP_MATCH; 00585 }
| static int cb_true_data | ( | void * | user_data, | |
| void * | arg, | |||
| void * | data, | |||
| int | flags | |||
| ) | [static] |
similar to cb_true, but is an ao2_callback_data_fn instead
Definition at line 590 of file astobj2.c.
References CMP_MATCH.
Referenced by __ao2_callback().
00591 { 00592 return CMP_MATCH; 00593 }
| static int cd_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flag | |||
| ) | [static] |
Definition at line 898 of file astobj2.c.
References _ao2_ref().
Referenced by container_destruct().
00899 { 00900 _ao2_ref(obj, -1); 00901 return 0; 00902 }
| static int cd_cb_debug | ( | void * | obj, | |
| void * | arg, | |||
| int | flag | |||
| ) | [static] |
Definition at line 904 of file astobj2.c.
References _ao2_ref_debug().
Referenced by container_destruct_debug().
00905 { 00906 _ao2_ref_debug(obj, -1, "deref object via container destroy", __FILE__, __LINE__, __PRETTY_FUNCTION__); 00907 return 0; 00908 }
| static void container_destruct | ( | void * | c | ) | [static] |
Definition at line 910 of file astobj2.c.
References _ao2_callback(), ast_atomic_fetchadd_int(), ast_free, AST_LIST_REMOVE_HEAD, ao2_container::buckets, cd_cb(), bucket_list::entry, ao2_container::n_buckets, and OBJ_UNLINK.
Referenced by _ao2_container_alloc().
00911 { 00912 struct ao2_container *c = _c; 00913 int i; 00914 00915 _ao2_callback(c, OBJ_UNLINK, cd_cb, NULL); 00916 00917 for (i = 0; i < c->n_buckets; i++) { 00918 struct bucket_list *current; 00919 00920 while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) { 00921 ast_free(current); 00922 } 00923 } 00924 00925 #ifdef AO2_DEBUG 00926 ast_atomic_fetchadd_int(&ao2.total_containers, -1); 00927 #endif 00928 }
| static void container_destruct_debug | ( | void * | c | ) | [static] |
Definition at line 930 of file astobj2.c.
References _ao2_callback_debug(), ast_atomic_fetchadd_int(), ast_free, AST_LIST_REMOVE_HEAD, ao2_container::buckets, cd_cb_debug(), bucket_list::entry, ao2_container::n_buckets, and OBJ_UNLINK.
Referenced by _ao2_container_alloc_debug().
00931 { 00932 struct ao2_container *c = _c; 00933 int i; 00934 00935 _ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__); 00936 00937 for (i = 0; i < c->n_buckets; i++) { 00938 struct bucket_list *current; 00939 00940 while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) { 00941 ast_free(current); 00942 } 00943 } 00944 00945 #ifdef AO2_DEBUG 00946 ast_atomic_fetchadd_int(&ao2.total_containers, -1); 00947 #endif 00948 }
| static int hash_zero | ( | const void * | user_obj, | |
| const int | flags | |||
| ) | [static] |
always zero hash function
it is convenient to have a hash function that always returns 0. This is basically used when we want to have a container that is a simple linked list.
Definition at line 417 of file astobj2.c.
Referenced by __ao2_container_alloc().
| static struct astobj2* INTERNAL_OBJ | ( | void * | user_data | ) | [static, read] |
convert from a pointer _p to a user-defined object
Definition at line 105 of file astobj2.c.
References AO2_MAGIC, ast_log(), LOG_ERROR, __priv_data::magic, and astobj2::priv_data.
Referenced by __ao2_callback(), __ao2_iterator_next(), __ao2_link(), __ao2_ref(), _ao2_ref(), _ao2_ref_debug(), _ao2_unlink(), _ao2_unlink_debug(), ao2_lock(), ao2_object_get_lockaddr(), ao2_trylock(), and ao2_unlock().
00106 { 00107 struct astobj2 *p; 00108 00109 if (!user_data) { 00110 ast_log(LOG_ERROR, "user_data is NULL\n"); 00111 return NULL; 00112 } 00113 00114 p = (struct astobj2 *) ((char *) user_data - sizeof(*p)); 00115 if (AO2_MAGIC != (p->priv_data.magic) ) { 00116 ast_log(LOG_ERROR, "bad magic number 0x%x for %p\n", p->priv_data.magic, p); 00117 p = NULL; 00118 } 00119 00120 return p; 00121 }
1.6.2