#include "asterisk.h"#include "asterisk/_private.h"#include "asterisk/astobj2.h"#include "asterisk/utils.h"#include "asterisk/cli.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 | REF_FILE "/tmp/refs" |
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, ao2_callback_fn *cb_fn, void *arg, 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) |
| 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_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 | 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 |
| #define EXTERNAL_OBJ | ( | _p | ) | ((_p) == NULL ? NULL : (_p)->user_data) |
convert from a pointer _p to an astobj2 object
Definition at line 128 of file astobj2.c.
Referenced by __ao2_alloc(), __ao2_callback(), and __ao2_iterator_next().
| #define REF_FILE "/tmp/refs" |
| 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 300 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().
00301 { 00302 /* allocation */ 00303 struct astobj2 *obj; 00304 00305 if (data_size < sizeof(void *)) 00306 data_size = sizeof(void *); 00307 00308 #if defined(__AST_DEBUG_MALLOC) 00309 obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, funcname); 00310 #else 00311 obj = ast_calloc(1, sizeof(*obj) + data_size); 00312 #endif 00313 00314 if (obj == NULL) 00315 return NULL; 00316 00317 ast_mutex_init(&obj->priv_data.lock); 00318 obj->priv_data.magic = AO2_MAGIC; 00319 obj->priv_data.data_size = data_size; 00320 obj->priv_data.ref_counter = 1; 00321 obj->priv_data.destructor_fn = destructor_fn; /* can be NULL */ 00322 00323 #ifdef AO2_DEBUG 00324 ast_atomic_fetchadd_int(&ao2.total_objects, 1); 00325 ast_atomic_fetchadd_int(&ao2.total_mem, data_size); 00326 ast_atomic_fetchadd_int(&ao2.total_refs, 1); 00327 #endif 00328 00329 /* return a pointer to the user data */ 00330 return EXTERNAL_OBJ(obj); 00331 }
| static void * __ao2_callback | ( | 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 | |||
| ) | [static] |
Browse the container using different stategies accoding the flags.
Definition at line 590 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(), 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, and ao2_container::version.
Referenced by _ao2_callback(), and _ao2_callback_debug().
00593 { 00594 int i, start, last; /* search boundaries */ 00595 void *ret = NULL; 00596 00597 if (INTERNAL_OBJ(c) == NULL) /* safety check on the argument */ 00598 return NULL; 00599 00600 if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) { 00601 ast_log(LOG_WARNING, "multiple data return not implemented yet (flags %x)\n", flags); 00602 return NULL; 00603 } 00604 00605 /* override the match function if necessary */ 00606 if (cb_fn == NULL) /* if NULL, match everything */ 00607 cb_fn = cb_true; 00608 /* 00609 * XXX this can be optimized. 00610 * If we have a hash function and lookup by pointer, 00611 * run the hash function. Otherwise, scan the whole container 00612 * (this only for the time being. We need to optimize this.) 00613 */ 00614 if ((flags & OBJ_POINTER)) /* we know hash can handle this case */ 00615 start = i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets; 00616 else /* don't know, let's scan all buckets */ 00617 start = i = -1; /* XXX this must be fixed later. */ 00618 00619 /* determine the search boundaries: i..last-1 */ 00620 if (i < 0) { 00621 start = i = 0; 00622 last = c->n_buckets; 00623 } else if ((flags & OBJ_CONTINUE)) { 00624 last = c->n_buckets; 00625 } else { 00626 last = i + 1; 00627 } 00628 00629 ao2_lock(c); /* avoid modifications to the content */ 00630 00631 for (; i < last ; i++) { 00632 /* scan the list with prev-cur pointers */ 00633 struct bucket_list *cur; 00634 00635 AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) { 00636 int match = cb_fn(EXTERNAL_OBJ(cur->astobj), arg, flags) & (CMP_MATCH | CMP_STOP); 00637 00638 /* we found the object, performing operations according flags */ 00639 if (match == 0) { /* no match, no stop, continue */ 00640 continue; 00641 } else if (match == CMP_STOP) { /* no match but stop, we are done */ 00642 i = last; 00643 break; 00644 } 00645 /* we have a match (CMP_MATCH) here */ 00646 if (!(flags & OBJ_NODATA)) { /* if must return the object, record the value */ 00647 /* it is important to handle this case before the unlink */ 00648 ret = EXTERNAL_OBJ(cur->astobj); 00649 if (tag) 00650 _ao2_ref_debug(ret, 1, tag, file, line, funcname); 00651 else 00652 _ao2_ref(ret, 1); 00653 } 00654 00655 if (flags & OBJ_UNLINK) { /* must unlink */ 00656 struct bucket_list *x = cur; 00657 00658 /* we are going to modify the container, so update version */ 00659 ast_atomic_fetchadd_int(&c->version, 1); 00660 AST_LIST_REMOVE_CURRENT(entry); 00661 /* update number of elements and version */ 00662 ast_atomic_fetchadd_int(&c->elements, -1); 00663 if (tag) 00664 _ao2_ref_debug(EXTERNAL_OBJ(x->astobj), -1, tag, file, line, funcname); 00665 else 00666 _ao2_ref(EXTERNAL_OBJ(x->astobj), -1); 00667 free(x); /* free the link record */ 00668 } 00669 00670 if ((match & CMP_STOP) || (flags & OBJ_MULTIPLE) == 0) { 00671 /* We found the only match we need */ 00672 i = last; /* force exit from outer loop */ 00673 break; 00674 } 00675 if (!(flags & OBJ_NODATA)) { 00676 #if 0 /* XXX to be completed */ 00677 /* 00678 * This is the multiple-return case. We need to link 00679 * the object in a list. The refcount is already increased. 00680 */ 00681 #endif 00682 } 00683 } 00684 AST_LIST_TRAVERSE_SAFE_END; 00685 00686 if (ret) { 00687 /* This assumes OBJ_MULTIPLE with !OBJ_NODATA is still not implemented */ 00688 break; 00689 } 00690 00691 if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) { 00692 /* Move to the beginning to ensure we check every bucket */ 00693 i = -1; 00694 last = start; 00695 } 00696 } 00697 ao2_unlock(c); 00698 return ret; 00699 }
| 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 420 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.
00422 { 00423 /* XXX maybe consistency check on arguments ? */ 00424 /* compute the container size */ 00425 00426 if (!c) 00427 return NULL; 00428 00429 c->version = 1; /* 0 is a reserved value here */ 00430 c->n_buckets = n_buckets; 00431 c->hash_fn = hash_fn ? hash_fn : hash_zero; 00432 c->cmp_fn = cmp_fn; 00433 00434 #ifdef AO2_DEBUG 00435 ast_atomic_fetchadd_int(&ao2.total_containers, 1); 00436 #endif 00437 00438 return c; 00439 }
| 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 755 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().
00756 { 00757 int lim; 00758 struct bucket_list *p = NULL; 00759 void *ret = NULL; 00760 00761 *q = NULL; 00762 00763 if (INTERNAL_OBJ(a->c) == NULL) 00764 return NULL; 00765 00766 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00767 ao2_lock(a->c); 00768 00769 /* optimization. If the container is unchanged and 00770 * we have a pointer, try follow it 00771 */ 00772 if (a->c->version == a->c_version && (p = a->obj) ) { 00773 if ( (p = AST_LIST_NEXT(p, entry)) ) 00774 goto found; 00775 /* nope, start from the next bucket */ 00776 a->bucket++; 00777 a->version = 0; 00778 a->obj = NULL; 00779 } 00780 00781 lim = a->c->n_buckets; 00782 00783 /* Browse the buckets array, moving to the next 00784 * buckets if we don't find the entry in the current one. 00785 * Stop when we find an element with version number greater 00786 * than the current one (we reset the version to 0 when we 00787 * switch buckets). 00788 */ 00789 for (; a->bucket < lim; a->bucket++, a->version = 0) { 00790 /* scan the current bucket */ 00791 AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) { 00792 if (p->version > a->version) 00793 goto found; 00794 } 00795 } 00796 00797 found: 00798 if (p) { 00799 a->version = p->version; 00800 a->obj = p; 00801 a->c_version = a->c->version; 00802 ret = EXTERNAL_OBJ(p->astobj); 00803 /* inc refcount of returned object */ 00804 *q = p; 00805 } 00806 00807 return ret; 00808 }
| static struct bucket_list * __ao2_link | ( | struct ao2_container * | c, | |
| void * | user_data | |||
| ) | [static, read] |
Definition at line 489 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().
00490 { 00491 int i; 00492 /* create a new list entry */ 00493 struct bucket_list *p; 00494 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00495 00496 if (!obj) 00497 return NULL; 00498 00499 if (INTERNAL_OBJ(c) == NULL) 00500 return NULL; 00501 00502 p = ast_calloc(1, sizeof(*p)); 00503 if (!p) 00504 return NULL; 00505 00506 i = abs(c->hash_fn(user_data, OBJ_POINTER)); 00507 00508 ao2_lock(c); 00509 i %= c->n_buckets; 00510 p->astobj = obj; 00511 p->version = ast_atomic_fetchadd_int(&c->version, 1); 00512 AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry); 00513 ast_atomic_fetchadd_int(&c->elements, 1); 00514 00515 /* the last two operations (ao2_ref, ao2_unlock) must be done by the calling func */ 00516 return p; 00517 }
| static int __ao2_ref | ( | void * | user_data, | |
| const int | delta | |||
| ) | [static] |
Definition at line 254 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().
00255 { 00256 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00257 int current_value; 00258 int ret; 00259 00260 /* if delta is 0, just return the refcount */ 00261 if (delta == 0) 00262 return (obj->priv_data.ref_counter); 00263 00264 /* we modify with an atomic operation the reference counter */ 00265 ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta); 00266 current_value = ret + delta; 00267 00268 #ifdef AO2_DEBUG 00269 ast_atomic_fetchadd_int(&ao2.total_refs, delta); 00270 #endif 00271 00272 /* this case must never happen */ 00273 if (current_value < 0) 00274 ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data); 00275 00276 if (current_value <= 0) { /* last reference, destroy the object */ 00277 if (obj->priv_data.destructor_fn != NULL) { 00278 obj->priv_data.destructor_fn(user_data); 00279 } 00280 00281 ast_mutex_destroy(&obj->priv_data.lock); 00282 #ifdef AO2_DEBUG 00283 ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size); 00284 ast_atomic_fetchadd_int(&ao2.total_objects, -1); 00285 #endif 00286 /* for safety, zero-out the astobj2 header and also the 00287 * first word of the user-data, which we make sure is always 00288 * allocated. */ 00289 memset(obj, '\0', sizeof(struct astobj2 *) + sizeof(void *) ); 00290 free(obj); 00291 } 00292 00293 return ret; 00294 }
| void* _ao2_alloc | ( | size_t | data_size, | |
| ao2_destructor_fn | destructor_fn | |||
| ) |
Definition at line 354 of file astobj2.c.
References __ao2_alloc().
Referenced by _ao2_container_alloc().
00355 { 00356 return __ao2_alloc(data_size, destructor_fn, __FILE__, __LINE__, __FUNCTION__); 00357 }
| 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 333 of file astobj2.c.
References __ao2_alloc(), and REF_FILE.
Referenced by _ao2_container_alloc_debug().
00335 { 00336 /* allocation */ 00337 void *obj; 00338 FILE *refo = ref_debug ? fopen(REF_FILE,"a") : NULL; 00339 00340 obj = __ao2_alloc(data_size, destructor_fn, file, line, funcname); 00341 00342 if (obj == NULL) 00343 return NULL; 00344 00345 if (refo) { 00346 fprintf(refo, "%p =1 %s:%d:%s (%s)\n", obj, file, line, funcname, tag); 00347 fclose(refo); 00348 } 00349 00350 /* return a pointer to the user data */ 00351 return obj; 00352 }
| void* _ao2_callback | ( | struct ao2_container * | c, | |
| const enum search_flags | flags, | |||
| ao2_callback_fn * | cb_fn, | |||
| void * | arg | |||
| ) |
Definition at line 709 of file astobj2.c.
References __ao2_callback().
Referenced by _ao2_find(), _ao2_unlink(), and container_destruct().
00711 { 00712 return __ao2_callback(c,flags, cb_fn, arg, NULL, NULL, 0, NULL); 00713 }
| 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 701 of file astobj2.c.
References __ao2_callback().
Referenced by _ao2_find_debug(), _ao2_unlink_debug(), and container_destruct_debug().
00705 { 00706 return __ao2_callback(c,flags, cb_fn, arg, tag, file, line, funcname); 00707 }
| 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 454 of file astobj2.c.
References __ao2_container_alloc(), _ao2_alloc(), and container_destruct().
00456 { 00457 /* XXX maybe consistency check on arguments ? */ 00458 /* compute the container size */ 00459 00460 size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket); 00461 struct ao2_container *c = _ao2_alloc(container_size, container_destruct); 00462 00463 return __ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn); 00464 }
| 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 441 of file astobj2.c.
References __ao2_container_alloc(), _ao2_alloc_debug(), and container_destruct_debug().
00444 { 00445 /* XXX maybe consistency check on arguments ? */ 00446 /* compute the container size */ 00447 size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket); 00448 struct ao2_container *c = _ao2_alloc_debug(container_size, container_destruct_debug, tag, file, line, funcname, ref_debug); 00449 00450 return __ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn); 00451 }
| void* _ao2_find | ( | struct ao2_container * | c, | |
| void * | arg, | |||
| enum search_flags | flags | |||
| ) |
Definition at line 723 of file astobj2.c.
References _ao2_callback(), and ao2_container::cmp_fn.
00724 { 00725 return _ao2_callback(c, flags, c->cmp_fn, arg); 00726 }
| 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 718 of file astobj2.c.
References _ao2_callback_debug(), and ao2_container::cmp_fn.
00719 { 00720 return _ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname); 00721 }
| void* _ao2_iterator_next | ( | struct ao2_iterator * | a | ) |
Definition at line 828 of file astobj2.c.
References __ao2_iterator_next(), _ao2_ref(), AO2_ITERATOR_DONTLOCK, ao2_unlock(), ao2_iterator::c, and ao2_iterator::flags.
00829 { 00830 struct bucket_list *p = NULL; 00831 void *ret = NULL; 00832 00833 ret = __ao2_iterator_next(a, &p); 00834 00835 if (p) { 00836 /* inc refcount of returned object */ 00837 _ao2_ref(ret, 1); 00838 } 00839 00840 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00841 ao2_unlock(a->c); 00842 00843 return ret; 00844 }
| void* _ao2_iterator_next_debug | ( | struct ao2_iterator * | a, | |
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 810 of file astobj2.c.
References __ao2_iterator_next(), _ao2_ref_debug(), AO2_ITERATOR_DONTLOCK, ao2_unlock(), ao2_iterator::c, and ao2_iterator::flags.
00811 { 00812 struct bucket_list *p; 00813 void *ret = NULL; 00814 00815 ret = __ao2_iterator_next(a, &p); 00816 00817 if (p) { 00818 /* inc refcount of returned object */ 00819 _ao2_ref_debug(ret, 1, tag, file, line, funcname); 00820 } 00821 00822 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00823 ao2_unlock(a->c); 00824 00825 return ret; 00826 }
| void* _ao2_link | ( | struct ao2_container * | c, | |
| void * | user_data | |||
| ) |
Definition at line 530 of file astobj2.c.
References __ao2_link(), _ao2_ref(), and ao2_unlock().
00531 { 00532 struct bucket_list *p = __ao2_link(c, user_data); 00533 00534 if (p) { 00535 _ao2_ref(user_data, +1); 00536 ao2_unlock(c); 00537 } 00538 return p; 00539 }
| void* _ao2_link_debug | ( | struct ao2_container * | c, | |
| void * | user_data, | |||
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 519 of file astobj2.c.
References __ao2_link(), _ao2_ref_debug(), and ao2_unlock().
00520 { 00521 struct bucket_list *p = __ao2_link(c, user_data); 00522 00523 if (p) { 00524 _ao2_ref_debug(user_data, +1, tag, file, line, funcname); 00525 ao2_unlock(c); 00526 } 00527 return p; 00528 }
| int _ao2_ref | ( | void * | user_data, | |
| const int | delta | |||
| ) |
Definition at line 244 of file astobj2.c.
References __ao2_ref(), and INTERNAL_OBJ().
Referenced by __ao2_callback(), _ao2_iterator_next(), _ao2_link(), and cd_cb().
00245 { 00246 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00247 00248 if (obj == NULL) 00249 return -1; 00250 00251 return __ao2_ref(user_data, delta); 00252 }
| int _ao2_ref_debug | ( | void * | user_data, | |
| const int | delta, | |||
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 224 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().
00225 { 00226 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00227 00228 if (obj == NULL) 00229 return -1; 00230 00231 if (delta != 0) { 00232 FILE *refo = fopen(REF_FILE,"a"); 00233 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); 00234 fclose(refo); 00235 } 00236 if (obj->priv_data.ref_counter + delta == 0 && obj->priv_data.destructor_fn != NULL) { /* this isn't protected with lock; just for o/p */ 00237 FILE *refo = fopen(REF_FILE,"a"); 00238 fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, funcname, tag); 00239 fclose(refo); 00240 } 00241 return __ao2_ref(user_data, delta); 00242 }
| void* _ao2_unlink | ( | struct ao2_container * | c, | |
| void * | user_data | |||
| ) |
Definition at line 564 of file astobj2.c.
References _ao2_callback(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.
00565 { 00566 if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */ 00567 return NULL; 00568 00569 _ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data); 00570 00571 return NULL; 00572 }
| void* _ao2_unlink_debug | ( | struct ao2_container * | c, | |
| void * | user_data, | |||
| char * | tag, | |||
| char * | file, | |||
| int | line, | |||
| const char * | funcname | |||
| ) |
Definition at line 553 of file astobj2.c.
References _ao2_callback_debug(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.
00555 { 00556 if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */ 00557 return NULL; 00558 00559 _ao2_callback_debug(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data, tag, file, line, funcname); 00560 00561 return NULL; 00562 }
| 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 469 of file astobj2.c.
References ao2_container::elements.
Referenced by __queues_show(), _sip_show_peers(), cli_tps_report(), do_timing(), get_unused_callno(), lock_broker(), pthread_timer_open(), and unload_module().
00470 { 00471 return c->elements; 00472 }
| void ao2_iterator_destroy | ( | struct ao2_iterator * | i | ) |
Destroy a container iterator.
destroy an iterator
Definition at line 746 of file astobj2.c.
References ao2_ref, and ao2_iterator::c.
Referenced by __iax2_show_peers(), __queues_show(), _sip_show_peers(), authenticate_reply(), check_access(), 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(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), interface_exists_global(), 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 731 of file astobj2.c.
References ao2_ref, ao2_iterator::c, and ao2_iterator::flags.
Referenced by __iax2_show_peers(), __queues_show(), _sip_show_peers(), ast_odbc_request_obj(), authenticate_reply(), check_access(), cli_console_active(), cli_list_devices(), cli_tps_report(), 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(), 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(), iax2_getpeername(), iax2_getpeertrunk(), interface_exists(), interface_exists_global(), 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(), reload_queues(), 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(), update_realtime_members(), and update_status().
00732 { 00733 struct ao2_iterator a = { 00734 .c = c, 00735 .flags = flags 00736 }; 00737 00738 ao2_ref(c, +1); 00739 00740 return a; 00741 }
| int ao2_lock | ( | void * | a | ) |
Lock an object.
| a | A pointer to the object we want to lock. |
Definition at line 142 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_taskprocessor_get(), ast_taskprocessor_unreference(), build_callno_limits(), build_parkinglot(), compare_weight(), complete_queue_remove_member(), complete_sip_user(), dialog_needdestroy(), end_bridge_callback(), find_call(), find_queue_by_name_rt(), get_member_penalty(), get_member_status(), get_unused_callno(), handle_request_subscribe(), interface_exists_global(), is_our_turn(), join_queue(), leave_queue(), load_config(), load_realtime_queue(), manager_queues_status(), manager_queues_summary(), moh_release(), mohalloc(), monmp3thread(), mwi_event_cb(), peercnt_add(), peercnt_remove(), 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(), 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(), try_calling(), update_call_counter(), update_queue(), update_realtime_members(), and update_status().
00146 { 00147 struct astobj2 *p = INTERNAL_OBJ(user_data); 00148 00149 if (p == NULL) 00150 return -1; 00151 00152 #ifdef AO2_DEBUG 00153 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00154 #endif 00155 00156 #ifndef DEBUG_THREADS 00157 return ast_mutex_lock(&p->priv_data.lock); 00158 #else 00159 return __ast_pthread_mutex_lock(file, line, func, var, &p->priv_data.lock); 00160 #endif 00161 }
| 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. |
Definition at line 209 of file astobj2.c.
References INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00210 { 00211 struct astobj2 *p = INTERNAL_OBJ(obj); 00212 00213 if (p == NULL) 00214 return NULL; 00215 00216 return &p->priv_data.lock; 00217 }
| 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 186 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_trylock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00190 { 00191 struct astobj2 *p = INTERNAL_OBJ(user_data); 00192 int ret; 00193 00194 if (p == NULL) 00195 return -1; 00196 #ifndef DEBUG_THREADS 00197 ret = ast_mutex_trylock(&p->priv_data.lock); 00198 #else 00199 ret = __ast_pthread_mutex_trylock(file, line, func, var, &p->priv_data.lock); 00200 #endif 00201 00202 #ifdef AO2_DEBUG 00203 if (!ret) 00204 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00205 #endif 00206 return ret; 00207 }
| int ao2_unlock | ( | void * | a | ) |
Unlock an object.
| a | A pointer to the object we want unlock. |
Definition at line 164 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_taskprocessor_get(), ast_taskprocessor_unreference(), build_callno_limits(), build_parkinglot(), compare_weight(), complete_queue_remove_member(), complete_sip_user(), dialog_needdestroy(), end_bridge_callback(), find_call(), find_queue_by_name_rt(), get_member_penalty(), get_member_status(), get_unused_callno(), handle_request_subscribe(), interface_exists_global(), is_our_turn(), join_queue(), leave_queue(), load_config(), load_realtime_queue(), manager_queues_status(), manager_queues_summary(), moh_release(), mohalloc(), monmp3thread(), mwi_event_cb(), peercnt_add(), peercnt_remove(), 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(), 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(), try_calling(), update_call_counter(), update_queue(), update_realtime_members(), and update_status().
00168 { 00169 struct astobj2 *p = INTERNAL_OBJ(user_data); 00170 00171 if (p == NULL) 00172 return -1; 00173 00174 #ifdef AO2_DEBUG 00175 ast_atomic_fetchadd_int(&ao2.total_locked, -1); 00176 #endif 00177 00178 #ifndef DEBUG_THREADS 00179 return ast_mutex_unlock(&p->priv_data.lock); 00180 #else 00181 return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock); 00182 #endif 00183 }
| int astobj2_init | ( | void | ) |
Provided by astobj2.c
Definition at line 1032 of file astobj2.c.
References ARRAY_LEN, and ast_cli_register_multiple().
Referenced by main().
01033 { 01034 #ifdef AO2_DEBUG 01035 ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2)); 01036 #endif 01037 01038 return 0; 01039 }
| static int cb_true | ( | void * | user_data, | |
| void * | arg, | |||
| int | flags | |||
| ) | [static] |
special callback that matches all
Definition at line 577 of file astobj2.c.
References CMP_MATCH.
Referenced by __ao2_callback().
00578 { 00579 return CMP_MATCH; 00580 }
| static int cd_cb | ( | void * | obj, | |
| void * | arg, | |||
| int | flag | |||
| ) | [static] |
Definition at line 849 of file astobj2.c.
References _ao2_ref().
Referenced by container_destruct().
00850 { 00851 _ao2_ref(obj, -1); 00852 return 0; 00853 }
| static int cd_cb_debug | ( | void * | obj, | |
| void * | arg, | |||
| int | flag | |||
| ) | [static] |
Definition at line 855 of file astobj2.c.
References _ao2_ref_debug().
Referenced by container_destruct_debug().
00856 { 00857 _ao2_ref_debug(obj, -1, "deref object via container destroy", __FILE__, __LINE__, __PRETTY_FUNCTION__); 00858 return 0; 00859 }
| static void container_destruct | ( | void * | c | ) | [static] |
Definition at line 861 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().
00862 { 00863 struct ao2_container *c = _c; 00864 int i; 00865 00866 _ao2_callback(c, OBJ_UNLINK, cd_cb, NULL); 00867 00868 for (i = 0; i < c->n_buckets; i++) { 00869 struct bucket_list *current; 00870 00871 while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) { 00872 ast_free(current); 00873 } 00874 } 00875 00876 #ifdef AO2_DEBUG 00877 ast_atomic_fetchadd_int(&ao2.total_containers, -1); 00878 #endif 00879 }
| static void container_destruct_debug | ( | void * | c | ) | [static] |
Definition at line 881 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().
00882 { 00883 struct ao2_container *c = _c; 00884 int i; 00885 00886 _ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__); 00887 00888 for (i = 0; i < c->n_buckets; i++) { 00889 struct bucket_list *current; 00890 00891 while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) { 00892 ast_free(current); 00893 } 00894 } 00895 00896 #ifdef AO2_DEBUG 00897 ast_atomic_fetchadd_int(&ao2.total_containers, -1); 00898 #endif 00899 }
| 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 412 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.5.6