#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" |
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) |
ao2_container * | _ao2_container_alloc (const unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn) |
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_lock (void *user_data, const char *file, const char *func, int line, const char *var) |
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) |
int | _ao2_trylock (void *user_data, const char *file, const char *func, int line, const char *var) |
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) |
int | _ao2_unlock (void *user_data, const char *file, const char *func, int line, const char *var) |
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. | |
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(), and __ao2_callback().
#define N1 20 |
Referenced by ao2_bt().
#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 342 of file astobj2.c.
References __ast_calloc(), AO2_MAGIC, ast_atomic_fetchadd_int(), ast_calloc, ast_mutex_init(), and EXTERNAL_OBJ.
Referenced by _ao2_alloc(), and _ao2_alloc_debug().
00343 { 00344 /* allocation */ 00345 struct astobj2 *obj; 00346 00347 if (data_size < sizeof(void *)) 00348 data_size = sizeof(void *); 00349 00350 #if defined(__AST_DEBUG_MALLOC) 00351 obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, funcname); 00352 #else 00353 obj = ast_calloc(1, sizeof(*obj) + data_size); 00354 #endif 00355 00356 if (obj == NULL) 00357 return NULL; 00358 00359 ast_mutex_init(&obj->priv_data.lock); 00360 obj->priv_data.magic = AO2_MAGIC; 00361 obj->priv_data.data_size = data_size; 00362 obj->priv_data.ref_counter = 1; 00363 obj->priv_data.destructor_fn = destructor_fn; /* can be NULL */ 00364 00365 #ifdef AO2_DEBUG 00366 ast_atomic_fetchadd_int(&ao2.total_objects, 1); 00367 ast_atomic_fetchadd_int(&ao2.total_mem, data_size); 00368 ast_atomic_fetchadd_int(&ao2.total_refs, 1); 00369 #endif 00370 00371 /* return a pointer to the user data */ 00372 return EXTERNAL_OBJ(obj); 00373 }
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 632 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().
00635 { 00636 int i, start, last; /* search boundaries */ 00637 void *ret = NULL; 00638 00639 if (INTERNAL_OBJ(c) == NULL) /* safety check on the argument */ 00640 return NULL; 00641 00642 if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) { 00643 ast_log(LOG_WARNING, "multiple data return not implemented yet (flags %x)\n", flags); 00644 return NULL; 00645 } 00646 00647 /* override the match function if necessary */ 00648 if (cb_fn == NULL) /* if NULL, match everything */ 00649 cb_fn = cb_true; 00650 /* 00651 * XXX this can be optimized. 00652 * If we have a hash function and lookup by pointer, 00653 * run the hash function. Otherwise, scan the whole container 00654 * (this only for the time being. We need to optimize this.) 00655 */ 00656 if ((flags & OBJ_POINTER)) /* we know hash can handle this case */ 00657 start = i = c->hash_fn(arg, flags & OBJ_POINTER) % c->n_buckets; 00658 else /* don't know, let's scan all buckets */ 00659 start = i = -1; /* XXX this must be fixed later. */ 00660 00661 /* determine the search boundaries: i..last-1 */ 00662 if (i < 0) { 00663 start = i = 0; 00664 last = c->n_buckets; 00665 } else if ((flags & OBJ_CONTINUE)) { 00666 last = c->n_buckets; 00667 } else { 00668 last = i + 1; 00669 } 00670 00671 ao2_lock(c); /* avoid modifications to the content */ 00672 00673 for (; i < last ; i++) { 00674 /* scan the list with prev-cur pointers */ 00675 struct bucket_list *cur; 00676 00677 AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) { 00678 int match = cb_fn(EXTERNAL_OBJ(cur->astobj), arg, flags) & (CMP_MATCH | CMP_STOP); 00679 00680 /* we found the object, performing operations according flags */ 00681 if (match == 0) { /* no match, no stop, continue */ 00682 continue; 00683 } else if (match == CMP_STOP) { /* no match but stop, we are done */ 00684 i = last; 00685 break; 00686 } 00687 /* we have a match (CMP_MATCH) here */ 00688 if (!(flags & OBJ_NODATA)) { /* if must return the object, record the value */ 00689 /* it is important to handle this case before the unlink */ 00690 ret = EXTERNAL_OBJ(cur->astobj); 00691 if (tag) 00692 _ao2_ref_debug(ret, 1, tag, file, line, funcname); 00693 else 00694 _ao2_ref(ret, 1); 00695 } 00696 00697 if (flags & OBJ_UNLINK) { /* must unlink */ 00698 struct bucket_list *x = cur; 00699 00700 /* we are going to modify the container, so update version */ 00701 ast_atomic_fetchadd_int(&c->version, 1); 00702 AST_LIST_REMOVE_CURRENT(entry); 00703 /* update number of elements and version */ 00704 ast_atomic_fetchadd_int(&c->elements, -1); 00705 if (tag) 00706 _ao2_ref_debug(EXTERNAL_OBJ(x->astobj), -1, tag, file, line, funcname); 00707 else 00708 _ao2_ref(EXTERNAL_OBJ(x->astobj), -1); 00709 free(x); /* free the link record */ 00710 } 00711 00712 if ((match & CMP_STOP) || (flags & OBJ_MULTIPLE) == 0) { 00713 /* We found the only match we need */ 00714 i = last; /* force exit from outer loop */ 00715 break; 00716 } 00717 if (!(flags & OBJ_NODATA)) { 00718 #if 0 /* XXX to be completed */ 00719 /* 00720 * This is the multiple-return case. We need to link 00721 * the object in a list. The refcount is already increased. 00722 */ 00723 #endif 00724 } 00725 } 00726 AST_LIST_TRAVERSE_SAFE_END; 00727 00728 if (ret) { 00729 /* This assumes OBJ_MULTIPLE with !OBJ_NODATA is still not implemented */ 00730 break; 00731 } 00732 00733 if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) { 00734 /* Move to the beginning to ensure we check every bucket */ 00735 i = -1; 00736 last = start; 00737 } 00738 } 00739 ao2_unlock(c); 00740 return ret; 00741 }
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] |
Definition at line 462 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.
00464 { 00465 /* XXX maybe consistency check on arguments ? */ 00466 /* compute the container size */ 00467 00468 if (!c) 00469 return NULL; 00470 00471 c->version = 1; /* 0 is a reserved value here */ 00472 c->n_buckets = n_buckets; 00473 c->hash_fn = hash_fn ? hash_fn : hash_zero; 00474 c->cmp_fn = cmp_fn; 00475 00476 #ifdef AO2_DEBUG 00477 ast_atomic_fetchadd_int(&ao2.total_containers, 1); 00478 #endif 00479 00480 return c; 00481 }
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] |
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 797 of file astobj2.c.
References AO2_ITERATOR_DONTLOCK, ao2_lock(), AST_LIST_NEXT, AST_LIST_TRAVERSE, ao2_iterator::bucket, ao2_container::buckets, ao2_iterator::c, ao2_iterator::c_version, bucket_list::entry, 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().
00798 { 00799 int lim; 00800 struct bucket_list *p = NULL; 00801 void *ret = NULL; 00802 00803 *q = NULL; 00804 00805 if (INTERNAL_OBJ(a->c) == NULL) 00806 return NULL; 00807 00808 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00809 ao2_lock(a->c); 00810 00811 /* optimization. If the container is unchanged and 00812 * we have a pointer, try follow it 00813 */ 00814 if (a->c->version == a->c_version && (p = a->obj) ) { 00815 if ( (p = AST_LIST_NEXT(p, entry)) ) 00816 goto found; 00817 /* nope, start from the next bucket */ 00818 a->bucket++; 00819 a->version = 0; 00820 a->obj = NULL; 00821 } 00822 00823 lim = a->c->n_buckets; 00824 00825 /* Browse the buckets array, moving to the next 00826 * buckets if we don't find the entry in the current one. 00827 * Stop when we find an element with version number greater 00828 * than the current one (we reset the version to 0 when we 00829 * switch buckets). 00830 */ 00831 for (; a->bucket < lim; a->bucket++, a->version = 0) { 00832 /* scan the current bucket */ 00833 AST_LIST_TRAVERSE(&a->c->buckets[a->bucket], p, entry) { 00834 if (p->version > a->version) 00835 goto found; 00836 } 00837 } 00838 00839 found: 00840 if (p) { 00841 a->version = p->version; 00842 a->obj = p; 00843 a->c_version = a->c->version; 00844 ret = EXTERNAL_OBJ(p->astobj); 00845 /* inc refcount of returned object */ 00846 *q = p; 00847 } 00848 00849 return ret; 00850 }
static struct bucket_list * __ao2_link | ( | struct ao2_container * | c, | |
void * | user_data | |||
) | [static] |
Definition at line 531 of file astobj2.c.
References ao2_lock(), ast_atomic_fetchadd_int(), ast_calloc, AST_LIST_INSERT_TAIL, bucket_list::entry, INTERNAL_OBJ(), and OBJ_POINTER.
Referenced by _ao2_link(), and _ao2_link_debug().
00532 { 00533 int i; 00534 /* create a new list entry */ 00535 struct bucket_list *p; 00536 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00537 00538 if (obj == NULL) 00539 return NULL; 00540 00541 if (INTERNAL_OBJ(c) == NULL) 00542 return NULL; 00543 00544 p = ast_calloc(1, sizeof(*p)); 00545 if (!p) 00546 return NULL; 00547 00548 i = abs(c->hash_fn(user_data, OBJ_POINTER)); 00549 00550 ao2_lock(c); 00551 i %= c->n_buckets; 00552 p->astobj = obj; 00553 p->version = ast_atomic_fetchadd_int(&c->version, 1); 00554 AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry); 00555 ast_atomic_fetchadd_int(&c->elements, 1); 00556 00557 /* the last two operations (ao2_ref, ao2_unlock) must be done by the calling func */ 00558 return p; 00559 }
static int __ao2_ref | ( | void * | user_data, | |
const int | delta | |||
) | [static] |
Definition at line 293 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().
00294 { 00295 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00296 int current_value; 00297 int ret; 00298 00299 if (obj == NULL) 00300 return -1; 00301 00302 /* if delta is 0, just return the refcount */ 00303 if (delta == 0) 00304 return (obj->priv_data.ref_counter); 00305 00306 /* we modify with an atomic operation the reference counter */ 00307 ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta); 00308 current_value = ret + delta; 00309 00310 #ifdef AO2_DEBUG 00311 ast_atomic_fetchadd_int(&ao2.total_refs, delta); 00312 #endif 00313 00314 /* this case must never happen */ 00315 if (current_value < 0) 00316 ast_log(LOG_ERROR, "refcount %d on object %p\n", current_value, user_data); 00317 00318 if (current_value <= 0) { /* last reference, destroy the object */ 00319 if (obj->priv_data.destructor_fn != NULL) { 00320 obj->priv_data.destructor_fn(user_data); 00321 } 00322 00323 ast_mutex_destroy(&obj->priv_data.lock); 00324 #ifdef AO2_DEBUG 00325 ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size); 00326 ast_atomic_fetchadd_int(&ao2.total_objects, -1); 00327 #endif 00328 /* for safety, zero-out the astobj2 header and also the 00329 * first word of the user-data, which we make sure is always 00330 * allocated. */ 00331 memset(obj, '\0', sizeof(struct astobj2 *) + sizeof(void *) ); 00332 free(obj); 00333 } 00334 00335 return ret; 00336 }
void* _ao2_alloc | ( | size_t | data_size, | |
ao2_destructor_fn | destructor_fn | |||
) |
Definition at line 396 of file astobj2.c.
References __ao2_alloc().
Referenced by _ao2_container_alloc().
00397 { 00398 return __ao2_alloc(data_size, destructor_fn, __FILE__, __LINE__, __FUNCTION__); 00399 }
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 375 of file astobj2.c.
References __ao2_alloc(), and REF_FILE.
Referenced by _ao2_container_alloc_debug(), and _moh_class_malloc().
00377 { 00378 /* allocation */ 00379 void *obj; 00380 FILE *refo = ref_debug ? fopen(REF_FILE,"a") : NULL; 00381 00382 obj = __ao2_alloc(data_size, destructor_fn, file, line, funcname); 00383 00384 if (obj == NULL) 00385 return NULL; 00386 00387 if (refo) { 00388 fprintf(refo, "%p =1 %s:%d:%s (%s)\n", obj, file, line, funcname, tag); 00389 fclose(refo); 00390 } 00391 00392 /* return a pointer to the user data */ 00393 return obj; 00394 }
void* _ao2_callback | ( | struct ao2_container * | c, | |
const enum search_flags | flags, | |||
ao2_callback_fn * | cb_fn, | |||
void * | arg | |||
) |
Definition at line 751 of file astobj2.c.
References __ao2_callback().
Referenced by _ao2_find(), _ao2_unlink(), and container_destruct().
00753 { 00754 return __ao2_callback(c,flags, cb_fn, arg, NULL, NULL, 0, NULL); 00755 }
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 743 of file astobj2.c.
References __ao2_callback().
Referenced by _ao2_find_debug(), _ao2_unlink_debug(), and container_destruct_debug().
00747 { 00748 return __ao2_callback(c,flags, cb_fn, arg, tag, file, line, funcname); 00749 }
struct ao2_container* _ao2_container_alloc | ( | const unsigned int | n_buckets, | |
ao2_hash_fn * | hash_fn, | |||
ao2_callback_fn * | cmp_fn | |||
) |
Definition at line 496 of file astobj2.c.
References __ao2_container_alloc(), _ao2_alloc(), container_destruct(), and ao2_container::n_buckets.
00498 { 00499 /* XXX maybe consistency check on arguments ? */ 00500 /* compute the container size */ 00501 00502 size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket); 00503 struct ao2_container *c = _ao2_alloc(container_size, container_destruct); 00504 00505 return __ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn); 00506 }
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 | |||
) |
Definition at line 483 of file astobj2.c.
References __ao2_container_alloc(), _ao2_alloc_debug(), container_destruct_debug(), and ao2_container::n_buckets.
00486 { 00487 /* XXX maybe consistency check on arguments ? */ 00488 /* compute the container size */ 00489 size_t container_size = sizeof(struct ao2_container) + n_buckets * sizeof(struct bucket); 00490 struct ao2_container *c = _ao2_alloc_debug(container_size, container_destruct_debug, tag, file, line, funcname, ref_debug); 00491 00492 return __ao2_container_alloc(c, n_buckets, hash_fn, cmp_fn); 00493 }
void* _ao2_find | ( | struct ao2_container * | c, | |
void * | arg, | |||
enum search_flags | flags | |||
) |
Definition at line 765 of file astobj2.c.
References _ao2_callback(), and ao2_container::cmp_fn.
Referenced by _get_mohbyname().
00766 { 00767 return _ao2_callback(c, flags, c->cmp_fn, arg); 00768 }
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 760 of file astobj2.c.
References _ao2_callback_debug(), and ao2_container::cmp_fn.
Referenced by _get_mohbyname().
00761 { 00762 return _ao2_callback_debug(c, flags, c->cmp_fn, arg, tag, file, line, funcname); 00763 }
void* _ao2_iterator_next | ( | struct ao2_iterator * | a | ) |
Definition at line 870 of file astobj2.c.
References __ao2_iterator_next(), _ao2_ref(), AO2_ITERATOR_DONTLOCK, ao2_unlock(), ao2_iterator::c, and ao2_iterator::flags.
00871 { 00872 struct bucket_list *p = NULL; 00873 void *ret = NULL; 00874 00875 ret = __ao2_iterator_next(a, &p); 00876 00877 if (p) { 00878 /* inc refcount of returned object */ 00879 _ao2_ref(ret, 1); 00880 } 00881 00882 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00883 ao2_unlock(a->c); 00884 00885 return ret; 00886 }
void* _ao2_iterator_next_debug | ( | struct ao2_iterator * | a, | |
char * | tag, | |||
char * | file, | |||
int | line, | |||
const char * | funcname | |||
) |
Definition at line 852 of file astobj2.c.
References __ao2_iterator_next(), _ao2_ref_debug(), AO2_ITERATOR_DONTLOCK, ao2_unlock(), ao2_iterator::c, and ao2_iterator::flags.
00853 { 00854 struct bucket_list *p; 00855 void *ret = NULL; 00856 00857 ret = __ao2_iterator_next(a, &p); 00858 00859 if (p) { 00860 /* inc refcount of returned object */ 00861 _ao2_ref_debug(ret, 1, tag, file, line, funcname); 00862 } 00863 00864 if (!(a->flags & AO2_ITERATOR_DONTLOCK)) 00865 ao2_unlock(a->c); 00866 00867 return ret; 00868 }
void* _ao2_link | ( | struct ao2_container * | c, | |
void * | user_data | |||
) |
Definition at line 572 of file astobj2.c.
References __ao2_link(), _ao2_ref(), and ao2_unlock().
00573 { 00574 struct bucket_list *p = __ao2_link(c, user_data); 00575 00576 if (p) { 00577 _ao2_ref(user_data, +1); 00578 ao2_unlock(c); 00579 } 00580 return p; 00581 }
void* _ao2_link_debug | ( | struct ao2_container * | c, | |
void * | user_data, | |||
char * | tag, | |||
char * | file, | |||
int | line, | |||
const char * | funcname | |||
) |
Definition at line 561 of file astobj2.c.
References __ao2_link(), _ao2_ref_debug(), and ao2_unlock().
00562 { 00563 struct bucket_list *p = __ao2_link(c, user_data); 00564 00565 if (p) { 00566 _ao2_ref_debug(user_data, +1, tag, file, line, funcname); 00567 ao2_unlock(c); 00568 } 00569 return p; 00570 }
int _ao2_lock | ( | void * | user_data, | |
const char * | file, | |||
const char * | func, | |||
int | line, | |||
const char * | var | |||
) |
Definition at line 162 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_lock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00163 { 00164 struct astobj2 *p = INTERNAL_OBJ(user_data); 00165 00166 if (p == NULL) 00167 return -1; 00168 00169 #ifdef AO2_DEBUG 00170 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00171 #endif 00172 00173 #ifndef DEBUG_THREADS 00174 return ast_mutex_lock(&p->priv_data.lock); 00175 #else 00176 return __ast_pthread_mutex_lock(file, line, func, var, &p->priv_data.lock); 00177 #endif 00178 }
int _ao2_ref | ( | void * | user_data, | |
const int | delta | |||
) |
Definition at line 283 of file astobj2.c.
References __ao2_ref(), and INTERNAL_OBJ().
Referenced by __ao2_callback(), _ao2_iterator_next(), _ao2_link(), and cd_cb().
00284 { 00285 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00286 00287 if (obj == NULL) 00288 return -1; 00289 00290 return __ao2_ref(user_data, delta); 00291 }
int _ao2_ref_debug | ( | void * | user_data, | |
const int | delta, | |||
char * | tag, | |||
char * | file, | |||
int | line, | |||
const char * | funcname | |||
) |
Definition at line 263 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().
00264 { 00265 struct astobj2 *obj = INTERNAL_OBJ(user_data); 00266 00267 if (obj == NULL) 00268 return -1; 00269 00270 if (delta != 0) { 00271 FILE *refo = fopen(REF_FILE,"a"); 00272 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); 00273 fclose(refo); 00274 } 00275 if (obj->priv_data.ref_counter + delta == 0 && obj->priv_data.destructor_fn != NULL) { /* this isn't protected with lock; just for o/p */ 00276 FILE *refo = fopen(REF_FILE,"a"); 00277 fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, funcname, tag); 00278 fclose(refo); 00279 } 00280 return __ao2_ref(user_data, delta); 00281 }
int _ao2_trylock | ( | void * | user_data, | |
const char * | file, | |||
const char * | func, | |||
int | line, | |||
const char * | var | |||
) |
Definition at line 228 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_trylock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00229 { 00230 struct astobj2 *p = INTERNAL_OBJ(user_data); 00231 int ret; 00232 00233 if (p == NULL) 00234 return -1; 00235 #ifndef DEBUG_THREADS 00236 ret = ast_mutex_trylock(&p->priv_data.lock); 00237 #else 00238 ret = __ast_pthread_mutex_trylock(file, line, func, var, &p->priv_data.lock); 00239 #endif 00240 00241 #ifdef AO2_DEBUG 00242 if (!ret) 00243 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00244 #endif 00245 return ret; 00246 }
void* _ao2_unlink | ( | struct ao2_container * | c, | |
void * | user_data | |||
) |
Definition at line 606 of file astobj2.c.
References _ao2_callback(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.
00607 { 00608 if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */ 00609 return NULL; 00610 00611 _ao2_callback(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data); 00612 00613 return NULL; 00614 }
void* _ao2_unlink_debug | ( | struct ao2_container * | c, | |
void * | user_data, | |||
char * | tag, | |||
char * | file, | |||
int | line, | |||
const char * | funcname | |||
) |
Definition at line 595 of file astobj2.c.
References _ao2_callback_debug(), ao2_match_by_addr, INTERNAL_OBJ(), OBJ_NODATA, OBJ_POINTER, and OBJ_UNLINK.
00597 { 00598 if (INTERNAL_OBJ(user_data) == NULL) /* safety check on the argument */ 00599 return NULL; 00600 00601 _ao2_callback_debug(c, OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA, ao2_match_by_addr, user_data, tag, file, line, funcname); 00602 00603 return NULL; 00604 }
int _ao2_unlock | ( | void * | user_data, | |
const char * | file, | |||
const char * | func, | |||
int | line, | |||
const char * | var | |||
) |
Definition at line 194 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_unlock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00195 { 00196 struct astobj2 *p = INTERNAL_OBJ(user_data); 00197 00198 if (p == NULL) 00199 return -1; 00200 00201 #ifdef AO2_DEBUG 00202 ast_atomic_fetchadd_int(&ao2.total_locked, -1); 00203 #endif 00204 00205 #ifndef DEBUG_THREADS 00206 return ast_mutex_unlock(&p->priv_data.lock); 00207 #else 00208 return __ast_pthread_mutex_unlock(file, line, func, var, &p->priv_data.lock); 00209 #endif 00210 }
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 511 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().
00512 { 00513 return c->elements; 00514 }
void ao2_iterator_destroy | ( | struct ao2_iterator * | i | ) |
Destroy a container iterator.
destroy an iterator
Definition at line 788 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(), 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 | |||
) |
Create an iterator for a container.
initialize an iterator so we start from the first object
Definition at line 773 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(), 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().
00774 { 00775 struct ao2_iterator a = { 00776 .c = c, 00777 .flags = flags 00778 }; 00779 00780 ao2_ref(c, +1); 00781 00782 return a; 00783 }
int ao2_lock | ( | void * | a | ) |
Lock an object.
a | A pointer to the object we want to lock. |
Definition at line 148 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(), inprocess_count(), 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().
00149 { 00150 struct astobj2 *p = INTERNAL_OBJ(user_data); 00151 00152 if (p == NULL) 00153 return -1; 00154 00155 #ifdef AO2_DEBUG 00156 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00157 #endif 00158 00159 return ast_mutex_lock(&p->priv_data.lock); 00160 }
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 248 of file astobj2.c.
References INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00249 { 00250 struct astobj2 *p = INTERNAL_OBJ(obj); 00251 00252 if (p == NULL) 00253 return NULL; 00254 00255 return &p->priv_data.lock; 00256 }
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 212 of file astobj2.c.
References ast_atomic_fetchadd_int(), ast_mutex_trylock(), INTERNAL_OBJ(), __priv_data::lock, and astobj2::priv_data.
00213 { 00214 struct astobj2 *p = INTERNAL_OBJ(user_data); 00215 int ret; 00216 00217 if (p == NULL) 00218 return -1; 00219 ret = ast_mutex_trylock(&p->priv_data.lock); 00220 00221 #ifdef AO2_DEBUG 00222 if (!ret) 00223 ast_atomic_fetchadd_int(&ao2.total_locked, 1); 00224 #endif 00225 return ret; 00226 }
int ao2_unlock | ( | void * | a | ) |
Unlock an object.
a | A pointer to the object we want unlock. |
Definition at line 180 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(), inprocess_count(), 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().
00181 { 00182 struct astobj2 *p = INTERNAL_OBJ(user_data); 00183 00184 if (p == NULL) 00185 return -1; 00186 00187 #ifdef AO2_DEBUG 00188 ast_atomic_fetchadd_int(&ao2.total_locked, -1); 00189 #endif 00190 00191 return ast_mutex_unlock(&p->priv_data.lock); 00192 }
int astobj2_init | ( | void | ) |
Provided by astobj2.c
Definition at line 1074 of file astobj2.c.
References ARRAY_LEN, and ast_cli_register_multiple().
Referenced by main().
01075 { 01076 #ifdef AO2_DEBUG 01077 ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2)); 01078 #endif 01079 01080 return 0; 01081 }
static int cb_true | ( | void * | user_data, | |
void * | arg, | |||
int | flags | |||
) | [static] |
special callback that matches all
Definition at line 619 of file astobj2.c.
References CMP_MATCH.
Referenced by __ao2_callback().
00620 { 00621 return CMP_MATCH; 00622 }
static int cd_cb | ( | void * | obj, | |
void * | arg, | |||
int | flag | |||
) | [static] |
Definition at line 891 of file astobj2.c.
References _ao2_ref().
Referenced by container_destruct().
00892 { 00893 _ao2_ref(obj, -1); 00894 return 0; 00895 }
static int cd_cb_debug | ( | void * | obj, | |
void * | arg, | |||
int | flag | |||
) | [static] |
Definition at line 897 of file astobj2.c.
References _ao2_ref_debug().
Referenced by container_destruct_debug().
00898 { 00899 _ao2_ref_debug(obj, -1, "deref object via container destroy", __FILE__, __LINE__, __PRETTY_FUNCTION__); 00900 return 0; 00901 }
static void container_destruct | ( | void * | c | ) | [static] |
Definition at line 903 of file astobj2.c.
References _ao2_callback(), 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().
00904 { 00905 struct ao2_container *c = _c; 00906 int i; 00907 00908 _ao2_callback(c, OBJ_UNLINK, cd_cb, NULL); 00909 00910 for (i = 0; i < c->n_buckets; i++) { 00911 struct bucket_list *current; 00912 00913 while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) { 00914 ast_free(current); 00915 } 00916 } 00917 00918 #ifdef AO2_DEBUG 00919 ast_atomic_fetchadd_int(&ao2.total_containers, -1); 00920 #endif 00921 }
static void container_destruct_debug | ( | void * | c | ) | [static] |
Definition at line 923 of file astobj2.c.
References _ao2_callback_debug(), ast_free, AST_LIST_REMOVE_HEAD, ao2_container::buckets, cd_cb_debug(), ao2_container::n_buckets, and OBJ_UNLINK.
Referenced by _ao2_container_alloc_debug().
00924 { 00925 struct ao2_container *c = _c; 00926 int i; 00927 00928 _ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__); 00929 00930 for (i = 0; i < c->n_buckets; i++) { 00931 struct bucket_list *current; 00932 00933 while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) { 00934 ast_free(current); 00935 } 00936 } 00937 00938 #ifdef AO2_DEBUG 00939 ast_atomic_fetchadd_int(&ao2.total_containers, -1); 00940 #endif 00941 }
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 454 of file astobj2.c.
Referenced by __ao2_container_alloc().
static struct astobj2* INTERNAL_OBJ | ( | void * | user_data | ) | [inline, static] |
convert from a pointer _p to a user-defined object
Definition at line 105 of file astobj2.c.
References AO2_MAGIC, ast_log(), and LOG_ERROR.
Referenced by __ao2_callback(), __ao2_iterator_next(), __ao2_link(), __ao2_ref(), _ao2_lock(), _ao2_ref(), _ao2_ref_debug(), _ao2_trylock(), _ao2_unlink(), _ao2_unlink_debug(), _ao2_unlock(), 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 }