2 * astobj2 - replacement containers for asterisk data structures.
4 * Copyright (C) 2006 Marta Carbone, Luigi Rizzo - Univ. di Pisa, Italy
6 * See http://www.asterisk.org for more information about
7 * the Asterisk project. Please do not directly contact
8 * any of the maintainers of this project for assistance;
9 * the project provides a web site, mailing lists and IRC
10 * channels for your use.
12 * This program is free software, distributed under the terms of
13 * the GNU General Public License Version 2. See the LICENSE file
14 * at the top of the source tree.
19 * \brief Functions implementing astobj2 objects.
21 * \author Richard Mudgett <rmudgett@digium.com>
25 <support_level>core</support_level>
30 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
32 #include "asterisk/_private.h"
33 #include "asterisk/astobj2.h"
34 #include "asterisk/dlinkedlists.h"
35 #include "asterisk/utils.h"
36 #include "asterisk/cli.h"
37 #define REF_FILE "/tmp/refs"
39 #if defined(TEST_FRAMEWORK)
40 /* We are building with the test framework enabled so enable AO2 debug tests as well. */
42 #endif /* defined(TEST_FRAMEWORK) */
45 * astobj2 objects are always preceded by this data structure,
46 * which contains a reference counter,
47 * option flags and a pointer to a destructor.
48 * The refcount is used to decide when it is time to
49 * invoke the destructor.
50 * The magic number is used for consistency check.
54 ao2_destructor_fn destructor_fn;
55 /*! User data size for stats */
57 /*! The ao2 object option flags */
59 /*! magic number. This is used to verify that a pointer passed in is a
64 #define AO2_MAGIC 0xa570b123
67 * What an astobj2 object looks like: fixed-size private data
68 * followed by variable-size user data.
71 struct __priv_data priv_data;
75 struct ao2_lock_priv {
79 /* AstObj2 with recursive lock. */
81 struct ao2_lock_priv mutex;
82 struct __priv_data priv_data;
86 struct ao2_rwlock_priv {
88 /*! Count of the number of threads holding a lock on this object. -1 if it is the write lock. */
92 /* AstObj2 with RW lock. */
93 struct astobj2_rwlock {
94 struct ao2_rwlock_priv rwlock;
95 struct __priv_data priv_data;
99 #if defined(AST_DEVMODE)
100 #define AO2_DEVMODE_STAT(stat) stat
102 #define AO2_DEVMODE_STAT(stat)
103 #endif /* defined(AST_DEVMODE) */
107 volatile int total_objects;
108 volatile int total_mem;
109 volatile int total_containers;
110 volatile int total_refs;
111 volatile int total_locked;
114 static struct ao2_stats ao2;
117 #ifndef HAVE_BKTR /* backtrace support */
120 #include <execinfo.h> /* for backtrace */
129 c = backtrace(addresses, N1);
130 strings = ast_bt_get_symbols(addresses,c);
131 ast_verbose("backtrace returned: %d\n", c);
132 for(i = 0; i < c; i++) {
133 ast_verbose("%d: %p %s\n", i, addresses[i], strings[i]);
135 ast_std_free(strings);
139 #define INTERNAL_OBJ_MUTEX(user_data) \
140 ((struct astobj2_lock *) (((char *) (user_data)) - sizeof(struct astobj2_lock)))
142 #define INTERNAL_OBJ_RWLOCK(user_data) \
143 ((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))
146 * \brief convert from a pointer _p to a user-defined object
148 * \return the pointer to the astobj2 structure
150 static inline struct astobj2 *INTERNAL_OBJ(void *user_data)
155 ast_log(LOG_ERROR, "user_data is NULL\n");
159 p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
160 if (AO2_MAGIC != p->priv_data.magic) {
161 if (p->priv_data.magic) {
162 ast_log(LOG_ERROR, "bad magic number 0x%x for object %p\n",
163 p->priv_data.magic, user_data);
166 "bad magic number for object %p. Object is likely destroyed.\n",
176 * \brief convert from a pointer _p to an astobj2 object
178 * \return the pointer to the user-defined portion.
180 #define EXTERNAL_OBJ(_p) ((_p) == NULL ? NULL : (_p)->user_data)
182 int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
184 struct astobj2 *obj = INTERNAL_OBJ(user_data);
185 struct astobj2_lock *obj_mutex;
186 struct astobj2_rwlock *obj_rwlock;
194 switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
195 case AO2_ALLOC_OPT_LOCK_MUTEX:
196 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
197 res = __ast_pthread_mutex_lock(file, line, func, var, &obj_mutex->mutex.lock);
200 ast_atomic_fetchadd_int(&ao2.total_locked, 1);
204 case AO2_ALLOC_OPT_LOCK_RWLOCK:
205 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
207 case AO2_LOCK_REQ_MUTEX:
208 case AO2_LOCK_REQ_WRLOCK:
209 res = __ast_rwlock_wrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
211 ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
213 ast_atomic_fetchadd_int(&ao2.total_locked, 1);
217 case AO2_LOCK_REQ_RDLOCK:
218 res = __ast_rwlock_rdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
220 ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
222 ast_atomic_fetchadd_int(&ao2.total_locked, 1);
228 case AO2_ALLOC_OPT_LOCK_NOLOCK:
229 /* The ao2 object has no lock. */
232 ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
240 int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
242 struct astobj2 *obj = INTERNAL_OBJ(user_data);
243 struct astobj2_lock *obj_mutex;
244 struct astobj2_rwlock *obj_rwlock;
253 switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
254 case AO2_ALLOC_OPT_LOCK_MUTEX:
255 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
256 res = __ast_pthread_mutex_unlock(file, line, func, var, &obj_mutex->mutex.lock);
259 ast_atomic_fetchadd_int(&ao2.total_locked, -1);
263 case AO2_ALLOC_OPT_LOCK_RWLOCK:
264 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
266 current_value = ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1) - 1;
267 if (current_value < 0) {
268 /* It was a WRLOCK that we are unlocking. Fix the count. */
269 ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -current_value);
271 res = __ast_rwlock_unlock(file, line, func, &obj_rwlock->rwlock.lock, var);
274 ast_atomic_fetchadd_int(&ao2.total_locked, -1);
278 case AO2_ALLOC_OPT_LOCK_NOLOCK:
279 /* The ao2 object has no lock. */
282 ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
290 int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
292 struct astobj2 *obj = INTERNAL_OBJ(user_data);
293 struct astobj2_lock *obj_mutex;
294 struct astobj2_rwlock *obj_rwlock;
302 switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
303 case AO2_ALLOC_OPT_LOCK_MUTEX:
304 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
305 res = __ast_pthread_mutex_trylock(file, line, func, var, &obj_mutex->mutex.lock);
308 ast_atomic_fetchadd_int(&ao2.total_locked, 1);
312 case AO2_ALLOC_OPT_LOCK_RWLOCK:
313 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
315 case AO2_LOCK_REQ_MUTEX:
316 case AO2_LOCK_REQ_WRLOCK:
317 res = __ast_rwlock_trywrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
319 ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
321 ast_atomic_fetchadd_int(&ao2.total_locked, 1);
325 case AO2_LOCK_REQ_RDLOCK:
326 res = __ast_rwlock_tryrdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
328 ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
330 ast_atomic_fetchadd_int(&ao2.total_locked, 1);
336 case AO2_ALLOC_OPT_LOCK_NOLOCK:
337 /* The ao2 object has no lock. */
340 ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
351 * \brief Adjust an object's lock to the requested level.
353 * \param user_data An ao2 object to adjust lock level.
354 * \param lock_how What level to adjust lock.
355 * \param keep_stronger TRUE if keep original lock level if it is stronger.
357 * \pre The ao2 object is already locked.
360 * An ao2 object with a RWLOCK will have its lock level adjusted
361 * to the specified level if it is not already there. An ao2
362 * object with a different type of lock is not affected.
364 * \return Original lock level.
366 static enum ao2_lock_req adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
368 struct astobj2 *obj = INTERNAL_OBJ(user_data);
369 struct astobj2_rwlock *obj_rwlock;
370 enum ao2_lock_req orig_lock;
372 switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
373 case AO2_ALLOC_OPT_LOCK_RWLOCK:
374 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
375 if (obj_rwlock->rwlock.num_lockers < 0) {
376 orig_lock = AO2_LOCK_REQ_WRLOCK;
378 orig_lock = AO2_LOCK_REQ_RDLOCK;
381 case AO2_LOCK_REQ_MUTEX:
382 lock_how = AO2_LOCK_REQ_WRLOCK;
384 case AO2_LOCK_REQ_WRLOCK:
385 if (lock_how != orig_lock) {
386 /* Switch from read lock to write lock. */
387 ao2_unlock(user_data);
388 ao2_wrlock(user_data);
391 case AO2_LOCK_REQ_RDLOCK:
392 if (!keep_stronger && lock_how != orig_lock) {
393 /* Switch from write lock to read lock. */
394 ao2_unlock(user_data);
395 ao2_rdlock(user_data);
401 ast_log(LOG_ERROR, "Invalid lock option on ao2 object %p\n", user_data);
403 case AO2_ALLOC_OPT_LOCK_NOLOCK:
404 case AO2_ALLOC_OPT_LOCK_MUTEX:
405 orig_lock = AO2_LOCK_REQ_MUTEX;
412 void *ao2_object_get_lockaddr(void *user_data)
414 struct astobj2 *obj = INTERNAL_OBJ(user_data);
415 struct astobj2_lock *obj_mutex;
422 switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
423 case AO2_ALLOC_OPT_LOCK_MUTEX:
424 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
425 return &obj_mutex->mutex.lock;
433 static int internal_ao2_ref(void *user_data, int delta, const char *file, int line, const char *func)
435 struct astobj2 *obj = INTERNAL_OBJ(user_data);
436 struct astobj2_lock *obj_mutex;
437 struct astobj2_rwlock *obj_rwlock;
446 /* if delta is 0, just return the refcount */
448 return obj->priv_data.ref_counter;
451 /* we modify with an atomic operation the reference counter */
452 ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta);
453 current_value = ret + delta;
456 ast_atomic_fetchadd_int(&ao2.total_refs, delta);
459 if (0 < current_value) {
460 /* The object still lives. */
464 /* this case must never happen */
465 if (current_value < 0) {
466 ast_log(__LOG_ERROR, file, line, func,
467 "Invalid refcount %d on ao2 object %p\n", current_value, user_data);
470 /* last reference, destroy the object */
471 if (obj->priv_data.destructor_fn != NULL) {
472 obj->priv_data.destructor_fn(user_data);
476 ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
477 ast_atomic_fetchadd_int(&ao2.total_objects, -1);
480 switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
481 case AO2_ALLOC_OPT_LOCK_MUTEX:
482 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
483 ast_mutex_destroy(&obj_mutex->mutex.lock);
486 * For safety, zero-out the astobj2_lock header and also the
487 * first word of the user-data, which we make sure is always
490 memset(obj_mutex, '\0', sizeof(*obj_mutex) + sizeof(void *) );
493 case AO2_ALLOC_OPT_LOCK_RWLOCK:
494 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
495 ast_rwlock_destroy(&obj_rwlock->rwlock.lock);
498 * For safety, zero-out the astobj2_rwlock header and also the
499 * first word of the user-data, which we make sure is always
502 memset(obj_rwlock, '\0', sizeof(*obj_rwlock) + sizeof(void *) );
503 ast_free(obj_rwlock);
505 case AO2_ALLOC_OPT_LOCK_NOLOCK:
507 * For safety, zero-out the astobj2 header and also the first
508 * word of the user-data, which we make sure is always
511 memset(obj, '\0', sizeof(*obj) + sizeof(void *) );
515 ast_log(__LOG_ERROR, file, line, func,
516 "Invalid lock option on ao2 object %p\n", user_data);
523 int __ao2_ref_debug(void *user_data, int delta, const char *tag, const char *file, int line, const char *func)
525 struct astobj2 *obj = INTERNAL_OBJ(user_data);
534 FILE *refo = fopen(REF_FILE, "a");
536 fprintf(refo, "%p %s%d %s:%d:%s (%s) [@%d]\n", user_data, (delta < 0 ? "" : "+"),
537 delta, file, line, func, tag, obj->priv_data.ref_counter);
541 if (obj->priv_data.ref_counter + delta == 0 && obj->priv_data.destructor_fn != NULL) { /* this isn't protected with lock; just for o/p */
542 FILE *refo = fopen(REF_FILE, "a");
544 fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, func, tag);
548 return internal_ao2_ref(user_data, delta, file, line, func);
551 int __ao2_ref(void *user_data, int delta)
553 return internal_ao2_ref(user_data, delta, __FILE__, __LINE__, __FUNCTION__);
556 void __ao2_cleanup_debug(void *obj, const char *file, int line, const char *function)
559 __ao2_ref_debug(obj, -1, "ao2_cleanup", file, line, function);
563 void __ao2_cleanup(void *obj)
570 static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *file, int line, const char *func)
574 struct astobj2_lock *obj_mutex;
575 struct astobj2_rwlock *obj_rwlock;
577 if (data_size < sizeof(void *)) {
579 * We always alloc at least the size of a void *,
580 * for debugging purposes.
582 data_size = sizeof(void *);
585 switch (options & AO2_ALLOC_OPT_LOCK_MASK) {
586 case AO2_ALLOC_OPT_LOCK_MUTEX:
587 #if defined(__AST_DEBUG_MALLOC)
588 obj_mutex = __ast_calloc(1, sizeof(*obj_mutex) + data_size, file, line, func);
590 obj_mutex = ast_calloc(1, sizeof(*obj_mutex) + data_size);
592 if (obj_mutex == NULL) {
596 ast_mutex_init(&obj_mutex->mutex.lock);
597 obj = (struct astobj2 *) &obj_mutex->priv_data;
599 case AO2_ALLOC_OPT_LOCK_RWLOCK:
600 #if defined(__AST_DEBUG_MALLOC)
601 obj_rwlock = __ast_calloc(1, sizeof(*obj_rwlock) + data_size, file, line, func);
603 obj_rwlock = ast_calloc(1, sizeof(*obj_rwlock) + data_size);
605 if (obj_rwlock == NULL) {
609 ast_rwlock_init(&obj_rwlock->rwlock.lock);
610 obj = (struct astobj2 *) &obj_rwlock->priv_data;
612 case AO2_ALLOC_OPT_LOCK_NOLOCK:
613 #if defined(__AST_DEBUG_MALLOC)
614 obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, func);
616 obj = ast_calloc(1, sizeof(*obj) + data_size);
623 /* Invalid option value. */
624 ast_log(__LOG_DEBUG, file, line, func, "Invalid lock option requested\n");
628 /* Initialize common ao2 values. */
629 obj->priv_data.ref_counter = 1;
630 obj->priv_data.destructor_fn = destructor_fn; /* can be NULL */
631 obj->priv_data.data_size = data_size;
632 obj->priv_data.options = options;
633 obj->priv_data.magic = AO2_MAGIC;
636 ast_atomic_fetchadd_int(&ao2.total_objects, 1);
637 ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
638 ast_atomic_fetchadd_int(&ao2.total_refs, 1);
641 /* return a pointer to the user data */
642 return EXTERNAL_OBJ(obj);
645 void *__ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag,
646 const char *file, int line, const char *func, int ref_debug)
652 if ((obj = internal_ao2_alloc(data_size, destructor_fn, options, file, line, func)) == NULL) {
656 if (ref_debug && (refo = fopen(REF_FILE, "a"))) {
657 fprintf(refo, "%p =1 %s:%d:%s (%s)\n", obj, file, line, func, tag);
661 /* return a pointer to the user data */
665 void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options)
667 return internal_ao2_alloc(data_size, destructor_fn, options, __FILE__, __LINE__, __FUNCTION__);
671 void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name)
675 ast_log(LOG_ERROR, "Must be called with a global object!\n");
679 if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
680 /* Could not get the write lock. */
685 /* Release the held ao2 object. */
688 __ao2_ref_debug(holder->obj, -1, tag, file, line, func);
690 __ao2_ref(holder->obj, -1);
695 __ast_rwlock_unlock(file, line, func, &holder->lock, name);
698 void *__ao2_global_obj_replace(struct ao2_global_obj *holder, void *obj, const char *tag, const char *file, int line, const char *func, const char *name)
704 ast_log(LOG_ERROR, "Must be called with a global object!\n");
708 if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
709 /* Could not get the write lock. */
716 __ao2_ref_debug(obj, +1, tag, file, line, func);
721 obj_old = holder->obj;
724 __ast_rwlock_unlock(file, line, func, &holder->lock, name);
729 int __ao2_global_obj_replace_unref(struct ao2_global_obj *holder, void *obj, const char *tag, const char *file, int line, const char *func, const char *name)
733 obj_old = __ao2_global_obj_replace(holder, obj, tag, file, line, func, name);
736 __ao2_ref_debug(obj_old, -1, tag, file, line, func);
738 __ao2_ref(obj_old, -1);
745 void *__ao2_global_obj_ref(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name)
751 ast_log(LOG_ERROR, "Must be called with a global object!\n");
756 if (__ast_rwlock_rdlock(file, line, func, &holder->lock, name)) {
757 /* Could not get the read lock. */
765 __ao2_ref_debug(obj, +1, tag, file, line, func);
771 __ast_rwlock_unlock(file, line, func, &holder->lock, name);
776 enum ao2_callback_type {
777 AO2_CALLBACK_DEFAULT,
778 AO2_CALLBACK_WITH_DATA,
781 enum ao2_container_insert {
782 /*! The node was inserted into the container. */
783 AO2_CONTAINER_INSERT_NODE_INSERTED,
784 /*! The node object replaced an existing node object. */
785 AO2_CONTAINER_INSERT_NODE_OBJ_REPLACED,
786 /*! The node was rejected (duplicate). */
787 AO2_CONTAINER_INSERT_NODE_REJECTED,
790 enum ao2_container_rtti {
791 /*! This is a hash container */
792 AO2_CONTAINER_RTTI_HASH,
793 /*! This is a red-black tree container */
794 AO2_CONTAINER_RTTI_RBTREE,
798 * \brief Generic container node.
800 * \details This is the base container node type that contains
801 * values common to all container nodes.
803 struct ao2_container_node {
804 /*! Stored object in node. */
806 /*! Container holding the node. (Does not hold a reference.) */
807 struct ao2_container *my_container;
808 /*! TRUE if the node is linked into the container. */
809 unsigned int is_linked:1;
813 * \brief Destroy this container.
815 * \param self Container to operate upon.
819 typedef void (*ao2_container_destroy_fn)(struct ao2_container *self);
822 * \brief Create an empty copy of this container.
824 * \param self Container to operate upon.
826 * \retval empty-container on success.
827 * \retval NULL on error.
829 typedef struct ao2_container *(*ao2_container_alloc_empty_clone_fn)(struct ao2_container *self);
832 * \brief Create an empty copy of this container. (Debug version)
834 * \param self Container to operate upon.
835 * \param tag used for debugging.
836 * \param file Debug file name invoked from
837 * \param line Debug line invoked from
838 * \param func Debug function name invoked from
839 * \param ref_debug TRUE if to output a debug reference message.
841 * \retval empty-container on success.
842 * \retval NULL on error.
844 typedef struct ao2_container *(*ao2_container_alloc_empty_clone_debug_fn)(struct ao2_container *self, const char *tag, const char *file, int line, const char *func, int ref_debug);
847 * \brief Create a new container node.
849 * \param self Container to operate upon.
850 * \param obj_new Object to put into the node.
851 * \param tag used for debugging.
852 * \param file Debug file name invoked from
853 * \param line Debug line invoked from
854 * \param func Debug function name invoked from
856 * \retval initialized-node on success.
857 * \retval NULL on error.
859 typedef struct ao2_container_node *(*ao2_container_new_node_fn)(struct ao2_container *self, void *obj_new, const char *tag, const char *file, int line, const char *func);
862 * \brief Insert a node into this container.
864 * \param self Container to operate upon.
865 * \param node Container node to insert into the container.
867 * \return enum ao2_container_insert value.
869 typedef enum ao2_container_insert (*ao2_container_insert_fn)(struct ao2_container *self, struct ao2_container_node *node);
872 * \brief Find the first container node in a traversal.
874 * \param self Container to operate upon.
875 * \param flags search_flags to control traversing the container
876 * \param arg Comparison callback arg parameter.
877 * \param v_state Traversal state to restart container traversal.
879 * \retval node-ptr of found node (Reffed).
880 * \retval NULL when no node found.
882 typedef struct ao2_container_node *(*ao2_container_find_first_fn)(struct ao2_container *self, enum search_flags flags, void *arg, void *v_state);
885 * \brief Find the next container node in a traversal.
887 * \param self Container to operate upon.
888 * \param v_state Traversal state to restart container traversal.
889 * \param prev Previous node returned by the traversal search functions.
890 * The ref ownership is passed back to this function.
892 * \retval node-ptr of found node (Reffed).
893 * \retval NULL when no node found.
895 typedef struct ao2_container_node *(*ao2_container_find_next_fn)(struct ao2_container *self, void *v_state, struct ao2_container_node *prev);
898 * \brief Cleanup the container traversal state.
900 * \param v_state Traversal state to cleanup.
904 typedef void (*ao2_container_find_cleanup_fn)(void *v_state);
907 * \brief Find the next non-empty iteration node in the container.
909 * \param self Container to operate upon.
910 * \param prev Previous node returned by the iterator.
911 * \param flags search_flags to control iterating the container.
912 * Only AO2_ITERATOR_DESCENDING is useful by the method.
914 * \note The container is already locked.
916 * \retval node on success.
917 * \retval NULL on error or no more nodes in the container.
919 typedef struct ao2_container_node *(*ao2_iterator_next_fn)(struct ao2_container *self, struct ao2_container_node *prev, enum ao2_iterator_flags flags);
922 * \brief Display contents of the specified container.
924 * \param self Container to dump.
925 * \param where User data needed by prnt to determine where to put output.
926 * \param prnt Print output callback function to use.
927 * \param prnt_obj Callback function to print the given object's key. (NULL if not available)
931 typedef void (*ao2_container_display)(struct ao2_container *self, void *where, ao2_prnt_fn *prnt, ao2_prnt_obj_fn *prnt_obj);
934 * \brief Display statistics of the specified container.
936 * \param self Container to display statistics.
937 * \param where User data needed by prnt to determine where to put output.
938 * \param prnt Print output callback function to use.
940 * \note The container is already locked for reading.
944 typedef void (*ao2_container_statistics)(struct ao2_container *self, void *where, ao2_prnt_fn *prnt);
947 * \brief Perform an integrity check on the specified container.
949 * \param self Container to check integrity.
951 * \note The container is already locked for reading.
953 * \retval 0 on success.
954 * \retval -1 on error.
956 typedef int (*ao2_container_integrity)(struct ao2_container *self);
958 /*! Container virtual methods template. */
959 struct ao2_container_methods {
960 /*! Run Time Type Identification */
961 enum ao2_container_rtti type;
962 /*! Destroy this container. */
963 ao2_container_destroy_fn destroy;
964 /*! \brief Create an empty copy of this container. */
965 ao2_container_alloc_empty_clone_fn alloc_empty_clone;
966 /*! \brief Create an empty copy of this container. (Debug version) */
967 ao2_container_alloc_empty_clone_debug_fn alloc_empty_clone_debug;
968 /*! Create a new container node. */
969 ao2_container_new_node_fn new_node;
970 /*! Insert a node into this container. */
971 ao2_container_insert_fn insert;
972 /*! Traverse the container, find the first node. */
973 ao2_container_find_first_fn traverse_first;
974 /*! Traverse the container, find the next node. */
975 ao2_container_find_next_fn traverse_next;
976 /*! Traverse the container, cleanup state. */
977 ao2_container_find_cleanup_fn traverse_cleanup;
978 /*! Find the next iteration element in the container. */
979 ao2_iterator_next_fn iterator_next;
980 #if defined(AST_DEVMODE)
981 /*! Display container contents. (Method for debug purposes) */
982 ao2_container_display dump;
983 /*! Display container debug statistics. (Method for debug purposes) */
984 ao2_container_statistics stats;
985 /*! Perform an integrity check on the container. (Method for debug purposes) */
986 ao2_container_integrity integrity;
987 #endif /* defined(AST_DEVMODE) */
991 * \brief Generic container type.
993 * \details This is the base container type that contains values
994 * common to all container types.
996 * \todo Linking and unlinking container objects is typically
997 * expensive, as it involves a malloc()/free() of a small object
998 * which is very inefficient. To optimize this, we can allocate
999 * larger arrays of container nodes when we run out of them, and
1000 * then manage our own freelist. This will be more efficient as
1001 * we can do the freelist management while we hold the lock
1002 * (that we need anyway).
1004 struct ao2_container {
1005 /*! Container virtual method table. */
1006 const struct ao2_container_methods *v_table;
1007 /*! Container sort function if the container is sorted. */
1008 ao2_sort_fn *sort_fn;
1009 /*! Container traversal matching function for ao2_find. */
1010 ao2_callback_fn *cmp_fn;
1011 /*! The container option flags */
1013 /*! Number of elements in the container. */
1015 #if defined(AST_DEVMODE)
1016 /*! Number of nodes in the container. */
1018 /*! Maximum number of empty nodes in the container. (nodes - elements) */
1019 int max_empty_nodes;
1020 #endif /* defined(AST_DEVMODE) */
1022 * \brief TRUE if the container is being destroyed.
1024 * \note The destruction traversal should override any requested
1025 * search order to do the most efficient order for destruction.
1027 * \note There should not be any empty nodes in the container
1028 * during destruction. If there are then an error needs to be
1029 * issued about container node reference leaks.
1031 unsigned int destroying:1;
1035 * return the number of elements in the container
1037 int ao2_container_count(struct ao2_container *c)
1039 return ast_atomic_fetchadd_int(&c->elements, 0);
1042 #if defined(AST_DEVMODE)
1043 static void hash_ao2_link_node_stat(struct ao2_container *hash, struct ao2_container_node *hash_node);
1044 static void hash_ao2_unlink_node_stat(struct ao2_container *hash, struct ao2_container_node *hash_node);
1045 #endif /* defined(AST_DEVMODE) */
1049 * \brief Link an object into this container. (internal)
1051 * \param self Container to operate upon.
1052 * \param obj_new Object to insert into the container.
1053 * \param flags search_flags to control linking the object. (OBJ_NOLOCK)
1054 * \param tag used for debugging.
1055 * \param file Debug file name invoked from
1056 * \param line Debug line invoked from
1057 * \param func Debug function name invoked from
1059 * \retval 0 on errors.
1060 * \retval 1 on success.
1062 static int internal_ao2_link(struct ao2_container *self, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
1065 enum ao2_lock_req orig_lock;
1066 struct ao2_container_node *node;
1068 if (!INTERNAL_OBJ(obj_new) || !INTERNAL_OBJ(self)
1069 || !self->v_table || !self->v_table->new_node || !self->v_table->insert) {
1070 /* Sanity checks. */
1075 if (flags & OBJ_NOLOCK) {
1076 orig_lock = adjust_lock(self, AO2_LOCK_REQ_WRLOCK, 1);
1079 orig_lock = AO2_LOCK_REQ_MUTEX;
1083 node = self->v_table->new_node(self, obj_new, tag, file, line, func);
1085 #if defined(AO2_DEBUG) && defined(AST_DEVMODE)
1086 switch (self->v_table->type) {
1087 case AO2_CONTAINER_RTTI_HASH:
1088 if (!self->sort_fn) {
1090 * XXX chan_iax2 plays games with the hash function so we cannot
1091 * routinely do an integrity check on this type of container.
1092 * chan_iax2 should be changed to not abuse the hash function.
1097 case AO2_CONTAINER_RTTI_RBTREE:
1098 if (ao2_container_check(self, OBJ_NOLOCK)) {
1099 ast_log(LOG_ERROR, "Container integrity failed before insert.\n");
1103 #endif /* defined(AO2_DEBUG) && defined(AST_DEVMODE) */
1104 /* Insert the new node. */
1105 switch (self->v_table->insert(self, node)) {
1106 case AO2_CONTAINER_INSERT_NODE_INSERTED:
1107 node->is_linked = 1;
1108 ast_atomic_fetchadd_int(&self->elements, 1);
1109 #if defined(AST_DEVMODE)
1110 AO2_DEVMODE_STAT(++self->nodes);
1111 switch (self->v_table->type) {
1112 case AO2_CONTAINER_RTTI_HASH:
1113 hash_ao2_link_node_stat(self, node);
1115 case AO2_CONTAINER_RTTI_RBTREE:
1118 #endif /* defined(AST_DEVMODE) */
1122 case AO2_CONTAINER_INSERT_NODE_OBJ_REPLACED:
1125 case AO2_CONTAINER_INSERT_NODE_REJECTED:
1126 __ao2_ref(node, -1);
1129 #if defined(AO2_DEBUG) && defined(AST_DEVMODE)
1131 switch (self->v_table->type) {
1132 case AO2_CONTAINER_RTTI_HASH:
1133 if (!self->sort_fn) {
1135 * XXX chan_iax2 plays games with the hash function so we cannot
1136 * routinely do an integrity check on this type of container.
1137 * chan_iax2 should be changed to not abuse the hash function.
1142 case AO2_CONTAINER_RTTI_RBTREE:
1143 if (ao2_container_check(self, OBJ_NOLOCK)) {
1144 ast_log(LOG_ERROR, "Container integrity failed after insert.\n");
1149 #endif /* defined(AO2_DEBUG) && defined(AST_DEVMODE) */
1152 if (flags & OBJ_NOLOCK) {
1153 adjust_lock(self, orig_lock, 0);
1161 int __ao2_link_debug(struct ao2_container *c, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
1163 return internal_ao2_link(c, obj_new, flags, tag, file, line, func);
1166 int __ao2_link(struct ao2_container *c, void *obj_new, int flags)
1168 return internal_ao2_link(c, obj_new, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
1172 * \brief another convenience function is a callback that matches on address
1174 int ao2_match_by_addr(void *user_data, void *arg, int flags)
1176 return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
1180 * Unlink an object from the container
1181 * and destroy the associated * bucket_entry structure.
1183 void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags,
1184 const char *tag, const char *file, int line, const char *func)
1186 if (!INTERNAL_OBJ(user_data)) {
1187 /* Sanity checks. */
1192 flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
1193 __ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
1198 void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags)
1200 if (!INTERNAL_OBJ(user_data)) {
1201 /* Sanity checks. */
1206 flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
1207 __ao2_callback(c, flags, ao2_match_by_addr, user_data);
1213 * \brief special callback that matches all
1215 static int cb_true(void *user_data, void *arg, int flags)
1221 * \brief similar to cb_true, but is an ao2_callback_data_fn instead
1223 static int cb_true_data(void *user_data, void *arg, void *data, int flags)
1228 /*! Allow enough room for container specific traversal state structs */
1229 #define AO2_TRAVERSAL_STATE_SIZE 100
1233 * \brief Traverse the container. (internal)
1235 * \param self Container to operate upon.
1236 * \param flags search_flags to control traversing the container
1237 * \param cb_fn Comparison callback function.
1238 * \param arg Comparison callback arg parameter.
1239 * \param data Data comparison callback data parameter.
1240 * \param type Type of comparison callback cb_fn.
1241 * \param tag used for debugging.
1242 * \param file Debug file name invoked from
1243 * \param line Debug line invoked from
1244 * \param func Debug function name invoked from
1246 * \retval NULL on failure or no matching object found.
1248 * \retval object found if OBJ_MULTIPLE is not set in the flags
1251 * \retval ao2_iterator pointer if OBJ_MULTIPLE is set in the
1252 * flags parameter. The iterator must be destroyed with
1253 * ao2_iterator_destroy() when the caller no longer needs it.
1255 static void *internal_ao2_traverse(struct ao2_container *self, enum search_flags flags,
1256 void *cb_fn, void *arg, void *data, enum ao2_callback_type type,
1257 const char *tag, const char *file, int line, const char *func)
1260 ao2_callback_fn *cb_default = NULL;
1261 ao2_callback_data_fn *cb_withdata = NULL;
1262 struct ao2_container_node *node;
1263 void *traversal_state;
1265 enum ao2_lock_req orig_lock;
1266 struct ao2_container *multi_container = NULL;
1267 struct ao2_iterator *multi_iterator = NULL;
1269 if (!INTERNAL_OBJ(self) || !self->v_table || !self->v_table->traverse_first
1270 || !self->v_table->traverse_next) {
1271 /* Sanity checks. */
1277 * This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA
1278 * turned off. This if statement checks for the special condition
1279 * where multiple items may need to be returned.
1281 if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
1282 /* we need to return an ao2_iterator with the results,
1283 * as there could be more than one. the iterator will
1284 * hold the only reference to a container that has all the
1285 * matching objects linked into it, so when the iterator
1286 * is destroyed, the container will be automatically
1287 * destroyed as well.
1289 multi_container = ao2_t_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL,
1290 NULL, "OBJ_MULTIPLE return container creation");
1291 if (!multi_container) {
1294 if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) {
1295 ao2_t_ref(multi_container, -1, "OBJ_MULTIPLE interator creation failed.");
1301 /* Match everything if no callback match function provided. */
1302 if (type == AO2_CALLBACK_WITH_DATA) {
1303 cb_withdata = cb_true_data;
1305 cb_default = cb_true;
1309 * We do this here to avoid the per object casting penalty (even
1310 * though that is probably optimized away anyway).
1312 if (type == AO2_CALLBACK_WITH_DATA) {
1313 cb_withdata = cb_fn;
1319 /* avoid modifications to the content */
1320 if (flags & OBJ_NOLOCK) {
1321 if (flags & OBJ_UNLINK) {
1322 orig_lock = adjust_lock(self, AO2_LOCK_REQ_WRLOCK, 1);
1324 orig_lock = adjust_lock(self, AO2_LOCK_REQ_RDLOCK, 1);
1327 orig_lock = AO2_LOCK_REQ_MUTEX;
1328 if (flags & OBJ_UNLINK) {
1335 /* Create a buffer for the traversal state. */
1336 traversal_state = alloca(AO2_TRAVERSAL_STATE_SIZE);
1339 for (node = self->v_table->traverse_first(self, flags, arg, traversal_state);
1341 node = self->v_table->traverse_next(self, traversal_state, node)) {
1344 /* Visit the current node. */
1345 match = (CMP_MATCH | CMP_STOP);
1346 if (type == AO2_CALLBACK_WITH_DATA) {
1347 match &= cb_withdata(node->obj, arg, data, flags);
1349 match &= cb_default(node->obj, arg, flags);
1352 /* no match, no stop, continue */
1355 if (match == CMP_STOP) {
1356 /* no match but stop, we are done */
1361 * CMP_MATCH is set here
1363 * we found the object, performing operations according to flags
1366 /* The object is still in the container. */
1367 if (!(flags & OBJ_NODATA)) {
1369 * We are returning the object, record the value. It is
1370 * important to handle this case before the unlink.
1372 if (multi_container) {
1374 * Link the object into the container that will hold the
1378 __ao2_link_debug(multi_container, node->obj, flags,
1379 tag, file, line, func);
1381 __ao2_link(multi_container, node->obj, flags);
1385 /* Returning a single object. */
1386 if (!(flags & OBJ_UNLINK)) {
1388 * Bump the ref count since we are not going to unlink and
1389 * transfer the container's object ref to the returned object.
1392 __ao2_ref_debug(ret, 1, tag, file, line, func);
1394 ao2_t_ref(ret, 1, "Traversal found object");
1400 if (flags & OBJ_UNLINK) {
1401 /* update number of elements */
1402 ast_atomic_fetchadd_int(&self->elements, -1);
1403 #if defined(AST_DEVMODE)
1405 int empty = self->nodes - self->elements;
1407 if (self->max_empty_nodes < empty) {
1408 self->max_empty_nodes = empty;
1411 switch (self->v_table->type) {
1412 case AO2_CONTAINER_RTTI_HASH:
1413 hash_ao2_unlink_node_stat(self, node);
1415 case AO2_CONTAINER_RTTI_RBTREE:
1418 #endif /* defined(AST_DEVMODE) */
1421 * - When unlinking and not returning the result, OBJ_NODATA is
1422 * set, the ref from the container must be decremented.
1424 * - When unlinking with a multi_container the ref from the
1425 * original container must be decremented. This is because the
1426 * result is returned in a new container that already holds its
1427 * own ref for the object.
1429 * If the ref from the original container is not accounted for
1430 * here a memory leak occurs.
1432 if (multi_container || (flags & OBJ_NODATA)) {
1434 __ao2_ref_debug(node->obj, -1, tag, file, line, func);
1436 ao2_t_ref(node->obj, -1, "Unlink container obj reference.");
1441 /* Unref the node from the container. */
1442 __ao2_ref(node, -1);
1446 if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) {
1447 /* We found our only (or last) match, so we are done */
1451 if (self->v_table->traverse_cleanup) {
1452 self->v_table->traverse_cleanup(traversal_state);
1455 /* Unref the node from self->v_table->traverse_first/traverse_next() */
1456 __ao2_ref(node, -1);
1459 if (flags & OBJ_NOLOCK) {
1460 adjust_lock(self, orig_lock, 0);
1465 /* if multi_container was created, we are returning multiple objects */
1466 if (multi_container) {
1467 *multi_iterator = ao2_iterator_init(multi_container,
1468 AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD);
1469 ao2_t_ref(multi_container, -1,
1470 "OBJ_MULTIPLE for multiple objects traversal complete.");
1471 return multi_iterator;
1477 void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
1478 ao2_callback_fn *cb_fn, void *arg, const char *tag, const char *file, int line,
1481 return internal_ao2_traverse(c, flags, cb_fn, arg, NULL, AO2_CALLBACK_DEFAULT, tag, file, line, func);
1484 void *__ao2_callback(struct ao2_container *c, enum search_flags flags,
1485 ao2_callback_fn *cb_fn, void *arg)
1487 return internal_ao2_traverse(c, flags, cb_fn, arg, NULL, AO2_CALLBACK_DEFAULT, NULL, NULL, 0, NULL);
1490 void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
1491 ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, const char *file,
1492 int line, const char *func)
1494 return internal_ao2_traverse(c, flags, cb_fn, arg, data, AO2_CALLBACK_WITH_DATA, tag, file, line, func);
1497 void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
1498 ao2_callback_data_fn *cb_fn, void *arg, void *data)
1500 return internal_ao2_traverse(c, flags, cb_fn, arg, data, AO2_CALLBACK_WITH_DATA, NULL, NULL, 0, NULL);
1504 * the find function just invokes the default callback with some reasonable flags.
1506 void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags,
1507 const char *tag, const char *file, int line, const char *func)
1509 void *arged = (void *) arg;/* Done to avoid compiler const warning */
1512 /* Sanity checks. */
1516 return __ao2_callback_debug(c, flags, c->cmp_fn, arged, tag, file, line, func);
1519 void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags)
1521 void *arged = (void *) arg;/* Done to avoid compiler const warning */
1524 /* Sanity checks. */
1528 return __ao2_callback(c, flags, c->cmp_fn, arged);
1532 * initialize an iterator so we start from the first object
1534 struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
1536 struct ao2_iterator a = {
1541 ao2_t_ref(c, +1, "Init iterator with container.");
1546 void ao2_iterator_restart(struct ao2_iterator *iter)
1548 /* Release the last container node reference if we have one. */
1549 if (iter->last_node) {
1550 enum ao2_lock_req orig_lock;
1553 * Do a read lock in case the container node unref does not
1554 * destroy the node. If the container node is destroyed then
1555 * the lock will be upgraded to a write lock.
1557 if (iter->flags & AO2_ITERATOR_DONTLOCK) {
1558 orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_RDLOCK, 1);
1560 orig_lock = AO2_LOCK_REQ_MUTEX;
1561 ao2_rdlock(iter->c);
1564 __ao2_ref(iter->last_node, -1);
1565 iter->last_node = NULL;
1567 if (iter->flags & AO2_ITERATOR_DONTLOCK) {
1568 adjust_lock(iter->c, orig_lock, 0);
1570 ao2_unlock(iter->c);
1574 /* The iteration is no longer complete. */
1578 void ao2_iterator_destroy(struct ao2_iterator *iter)
1580 /* Release any last container node reference. */
1581 ao2_iterator_restart(iter);
1583 /* Release the iterated container reference. */
1584 ao2_t_ref(iter->c, -1, "Unref iterator in ao2_iterator_destroy");
1587 /* Free the malloced iterator. */
1588 if (iter->flags & AO2_ITERATOR_MALLOCD) {
1593 void ao2_iterator_cleanup(struct ao2_iterator *iter)
1596 ao2_iterator_destroy(iter);
1601 * move to the next element in the container.
1603 static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
1605 enum ao2_lock_req orig_lock;
1606 struct ao2_container_node *node;
1609 if (!INTERNAL_OBJ(iter->c) || !iter->c->v_table || !iter->c->v_table->iterator_next) {
1610 /* Sanity checks. */
1615 if (iter->complete) {
1616 /* Don't return any more objects. */
1620 if (iter->flags & AO2_ITERATOR_DONTLOCK) {
1621 if (iter->flags & AO2_ITERATOR_UNLINK) {
1622 orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_WRLOCK, 1);
1624 orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_RDLOCK, 1);
1627 orig_lock = AO2_LOCK_REQ_MUTEX;
1628 if (iter->flags & AO2_ITERATOR_UNLINK) {
1629 ao2_wrlock(iter->c);
1631 ao2_rdlock(iter->c);
1635 node = iter->c->v_table->iterator_next(iter->c, iter->last_node, iter->flags);
1639 if (iter->flags & AO2_ITERATOR_UNLINK) {
1640 /* update number of elements */
1641 ast_atomic_fetchadd_int(&iter->c->elements, -1);
1642 #if defined(AST_DEVMODE)
1644 int empty = iter->c->nodes - iter->c->elements;
1646 if (iter->c->max_empty_nodes < empty) {
1647 iter->c->max_empty_nodes = empty;
1650 switch (iter->c->v_table->type) {
1651 case AO2_CONTAINER_RTTI_HASH:
1652 hash_ao2_unlink_node_stat(iter->c, node);
1654 case AO2_CONTAINER_RTTI_RBTREE:
1657 #endif /* defined(AST_DEVMODE) */
1659 /* Transfer the object ref from the container to the returned object. */
1662 /* Transfer the container's node ref to the iterator. */
1664 /* Bump ref of returned object */
1666 __ao2_ref_debug(ret, +1, tag, file, line, func);
1668 ao2_t_ref(ret, +1, "Next iterator object.");
1671 /* Bump the container's node ref for the iterator. */
1672 __ao2_ref(node, +1);
1675 /* The iteration has completed. */
1680 /* Replace the iterator's node */
1681 if (iter->last_node) {
1682 __ao2_ref(iter->last_node, -1);
1684 iter->last_node = node;
1686 if (iter->flags & AO2_ITERATOR_DONTLOCK) {
1687 adjust_lock(iter->c, orig_lock, 0);
1689 ao2_unlock(iter->c);
1695 void *__ao2_iterator_next_debug(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
1697 return internal_ao2_iterator_next(iter, tag, file, line, func);
1700 void *__ao2_iterator_next(struct ao2_iterator *iter)
1702 return internal_ao2_iterator_next(iter, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
1705 static void container_destruct(void *_c)
1707 struct ao2_container *c = _c;
1709 /* Unlink any stored objects in the container. */
1711 __ao2_callback(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL);
1713 /* Perform any extra container cleanup. */
1714 if (c->v_table && c->v_table->destroy) {
1715 c->v_table->destroy(c);
1719 ast_atomic_fetchadd_int(&ao2.total_containers, -1);
1723 static void container_destruct_debug(void *_c)
1725 struct ao2_container *c = _c;
1727 /* Unlink any stored objects in the container. */
1729 __ao2_callback_debug(c, OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL, NULL,
1730 "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
1732 /* Perform any extra container cleanup. */
1733 if (c->v_table && c->v_table->destroy) {
1734 c->v_table->destroy(c);
1738 ast_atomic_fetchadd_int(&ao2.total_containers, -1);
1744 * \brief Put obj into the arg container.
1747 * \param obj pointer to the (user-defined part) of an object.
1748 * \param arg callback argument from ao2_callback()
1749 * \param flags flags from ao2_callback()
1751 * \retval 0 on success.
1752 * \retval CMP_STOP|CMP_MATCH on error.
1754 static int dup_obj_cb(void *obj, void *arg, int flags)
1756 struct ao2_container *dest = arg;
1758 return __ao2_link(dest, obj, OBJ_NOLOCK) ? 0 : (CMP_MATCH | CMP_STOP);
1761 int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
1766 if (!(flags & OBJ_NOLOCK)) {
1770 obj = __ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest);
1772 /* Failed to put this obj into the dest container. */
1773 ao2_t_ref(obj, -1, "Failed to put this object into the dest container.");
1775 /* Remove all items from the dest container. */
1776 __ao2_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL,
1780 if (!(flags & OBJ_NOLOCK)) {
1788 struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags)
1790 struct ao2_container *clone;
1793 /* Create the clone container with the same properties as the original. */
1794 if (!INTERNAL_OBJ(orig) || !orig->v_table || !orig->v_table->alloc_empty_clone) {
1795 /* Sanity checks. */
1799 clone = orig->v_table->alloc_empty_clone(orig);
1804 if (flags & OBJ_NOLOCK) {
1807 failed = ao2_container_dup(clone, orig, flags);
1808 if (flags & OBJ_NOLOCK) {
1812 /* Object copy into the clone container failed. */
1813 ao2_t_ref(clone, -1, "Clone creation failed.");
1819 struct ao2_container *__ao2_container_clone_debug(struct ao2_container *orig, enum search_flags flags, const char *tag, const char *file, int line, const char *func, int ref_debug)
1821 struct ao2_container *clone;
1824 /* Create the clone container with the same properties as the original. */
1825 if (!INTERNAL_OBJ(orig) || !orig->v_table || !orig->v_table->alloc_empty_clone_debug) {
1826 /* Sanity checks. */
1830 clone = orig->v_table->alloc_empty_clone_debug(orig, tag, file, line, func, ref_debug);
1835 if (flags & OBJ_NOLOCK) {
1838 failed = ao2_container_dup(clone, orig, flags);
1839 if (flags & OBJ_NOLOCK) {
1843 /* Object copy into the clone container failed. */
1845 __ao2_ref_debug(clone, -1, tag, file, line, func);
1847 ao2_t_ref(clone, -1, "Clone creation failed.");
1854 void ao2_container_dump(struct ao2_container *self, enum search_flags flags, const char *name, void *where, ao2_prnt_fn *prnt, ao2_prnt_obj_fn *prnt_obj)
1856 if (!INTERNAL_OBJ(self) || !self->v_table) {
1857 prnt(where, "Invalid container\n");
1862 if (!(flags & OBJ_NOLOCK)) {
1866 prnt(where, "Container name: %s\n", name);
1868 #if defined(AST_DEVMODE)
1869 if (self->v_table->dump) {
1870 self->v_table->dump(self, where, prnt, prnt_obj);
1872 #endif /* defined(AST_DEVMODE) */
1874 prnt(where, "Container dump not available.\n");
1876 if (!(flags & OBJ_NOLOCK)) {
1881 void ao2_container_stats(struct ao2_container *self, enum search_flags flags, const char *name, void *where, ao2_prnt_fn *prnt)
1883 if (!INTERNAL_OBJ(self) || !self->v_table) {
1884 prnt(where, "Invalid container\n");
1889 if (!(flags & OBJ_NOLOCK)) {
1893 prnt(where, "Container name: %s\n", name);
1895 prnt(where, "Number of objects: %d\n", self->elements);
1896 #if defined(AST_DEVMODE)
1897 prnt(where, "Number of nodes: %d\n", self->nodes);
1898 prnt(where, "Number of empty nodes: %d\n", self->nodes - self->elements);
1901 * If the max_empty_nodes count gets out of single digits you
1902 * likely have a code path where ao2_iterator_destroy() is not
1905 * Empty nodes do not harm the container but they do make
1906 * container operations less efficient.
1908 prnt(where, "Maximum empty nodes: %d\n", self->max_empty_nodes);
1909 if (self->v_table->stats) {
1910 self->v_table->stats(self, where, prnt);
1912 #endif /* defined(AST_DEVMODE) */
1913 if (!(flags & OBJ_NOLOCK)) {
1918 int ao2_container_check(struct ao2_container *self, enum search_flags flags)
1922 if (!INTERNAL_OBJ(self) || !self->v_table) {
1923 /* Sanity checks. */
1927 #if defined(AST_DEVMODE)
1928 if (!self->v_table->integrity) {
1929 /* No ingetrigy check available. Assume container is ok. */
1933 if (!(flags & OBJ_NOLOCK)) {
1936 res = self->v_table->integrity(self);
1937 if (!(flags & OBJ_NOLOCK)) {
1940 #endif /* defined(AST_DEVMODE) */
1945 * A structure to create a linked list of entries,
1946 * used within a bucket.
1948 struct hash_bucket_node {
1950 * \brief Items common to all container nodes.
1951 * \note Must be first in the specific node struct.
1953 struct ao2_container_node common;
1954 /*! Next node links in the list. */
1955 AST_DLLIST_ENTRY(hash_bucket_node) links;
1956 /*! Hash bucket holding the node. */
1960 struct hash_bucket {
1961 /*! List of objects held in the bucket. */
1962 AST_DLLIST_HEAD_NOLOCK(, hash_bucket_node) list;
1963 #if defined(AST_DEVMODE)
1964 /*! Number of elements currently in the bucket. */
1966 /*! Maximum number of elements in the bucket. */
1968 #endif /* defined(AST_DEVMODE) */
1972 * A hash container in addition to values common to all
1973 * container types, stores the hash callback function, the
1974 * number of hash buckets, and the hash bucket heads.
1976 struct ao2_container_hash {
1978 * \brief Items common to all containers.
1979 * \note Must be first in the specific container struct.
1981 struct ao2_container common;
1982 ao2_hash_fn *hash_fn;
1983 /*! Number of hash buckets in this container. */
1985 /*! Hash bucket array of n_buckets. Variable size. */
1986 struct hash_bucket buckets[0];
1991 * \brief Create an empty copy of this container.
1994 * \param self Container to operate upon.
1996 * \retval empty-clone-container on success.
1997 * \retval NULL on error.
1999 static struct ao2_container *hash_ao2_alloc_empty_clone(struct ao2_container_hash *self)
2001 struct astobj2 *orig_obj;
2002 unsigned int ao2_options;
2004 /* Get container ao2 options. */
2005 orig_obj = INTERNAL_OBJ(self);
2009 ao2_options = orig_obj->priv_data.options;
2011 return ao2_t_container_alloc_hash(ao2_options, self->common.options, self->n_buckets,
2012 self->hash_fn, self->common.sort_fn, self->common.cmp_fn, "Clone hash container");
2017 * \brief Create an empty copy of this container. (Debug version)
2020 * \param self Container to operate upon.
2021 * \param tag used for debugging.
2022 * \param file Debug file name invoked from
2023 * \param line Debug line invoked from
2024 * \param func Debug function name invoked from
2025 * \param ref_debug TRUE if to output a debug reference message.
2027 * \retval empty-clone-container on success.
2028 * \retval NULL on error.
2030 static struct ao2_container *hash_ao2_alloc_empty_clone_debug(struct ao2_container_hash *self, const char *tag, const char *file, int line, const char *func, int ref_debug)
2032 struct astobj2 *orig_obj;
2033 unsigned int ao2_options;
2035 /* Get container ao2 options. */
2036 orig_obj = INTERNAL_OBJ(self);
2040 ao2_options = orig_obj->priv_data.options;
2042 return __ao2_container_alloc_hash_debug(ao2_options, self->common.options,
2043 self->n_buckets, self->hash_fn, self->common.sort_fn, self->common.cmp_fn,
2044 tag, file, line, func, ref_debug);
2049 * \brief Destroy a hash container list node.
2052 * \param v_doomed Container node to destroy.
2055 * The container node unlinks itself from the container as part
2056 * of its destruction. The node must be destroyed while the
2057 * container is already locked.
2059 * \note The container must be locked when the node is
2064 static void hash_ao2_node_destructor(void *v_doomed)
2066 struct hash_bucket_node *doomed = v_doomed;
2068 if (doomed->common.is_linked) {
2069 struct ao2_container_hash *my_container;
2070 struct hash_bucket *bucket;
2073 * Promote to write lock if not already there. Since
2074 * adjust_lock() can potentially release and block waiting for a
2075 * write lock, care must be taken to ensure that node references
2076 * are released before releasing the container references.
2078 * Node references held by an iterator can only be held while
2079 * the iterator also holds a reference to the container. These
2080 * node references must be unreferenced before the container can
2081 * be unreferenced to ensure that the node will not get a
2082 * negative reference and the destructor called twice for the
2085 my_container = (struct ao2_container_hash *) doomed->common.my_container;
2086 adjust_lock(my_container, AO2_LOCK_REQ_WRLOCK, 1);
2088 #if defined(AO2_DEBUG) && defined(AST_DEVMODE)
2090 * XXX chan_iax2 plays games with the hash function so we cannot
2091 * routinely do an integrity check on this type of container.
2092 * chan_iax2 should be changed to not abuse the hash function.
2094 if (!my_container->common.destroying
2095 && my_container->common.sort_fn
2096 && ao2_container_check(doomed->common.my_container, OBJ_NOLOCK)) {
2097 ast_log(LOG_ERROR, "Container integrity failed before node deletion.\n");
2099 #endif /* defined(AO2_DEBUG) && defined(AST_DEVMODE) */
2100 bucket = &my_container->buckets[doomed->my_bucket];
2101 AST_DLLIST_REMOVE(&bucket->list, doomed, links);
2102 AO2_DEVMODE_STAT(--my_container->common.nodes);
2106 * We could have an object in the node if the container is being
2107 * destroyed or the node had not been linked in yet.
2109 if (doomed->common.obj) {
2110 ao2_t_ref(doomed->common.obj, -1, "Container node destruction");
2111 doomed->common.obj = NULL;
2117 * \brief Create a new container node.
2120 * \param self Container to operate upon.
2121 * \param obj_new Object to put into the node.
2122 * \param tag used for debugging.
2123 * \param file Debug file name invoked from
2124 * \param line Debug line invoked from
2125 * \param func Debug function name invoked from
2127 * \retval initialized-node on success.
2128 * \retval NULL on error.
2130 static struct hash_bucket_node *hash_ao2_new_node(struct ao2_container_hash *self, void *obj_new, const char *tag, const char *file, int line, const char *func)
2132 struct hash_bucket_node *node;
2135 node = __ao2_alloc(sizeof(*node), hash_ao2_node_destructor, AO2_ALLOC_OPT_LOCK_NOLOCK);
2140 i = abs(self->hash_fn(obj_new, OBJ_POINTER));
2141 i %= self->n_buckets;
2144 __ao2_ref_debug(obj_new, +1, tag, file, line, func);
2146 ao2_t_ref(obj_new, +1, "Container node creation");
2148 node->common.obj = obj_new;
2149 node->common.my_container = (struct ao2_container *) self;
2150 node->my_bucket = i;
2157 * \brief Insert a node into this container.
2160 * \param self Container to operate upon.
2161 * \param node Container node to insert into the container.
2163 * \return enum ao2_container_insert value.
2165 static enum ao2_container_insert hash_ao2_insert_node(struct ao2_container_hash *self, struct hash_bucket_node *node)
2168 struct hash_bucket *bucket;
2169 struct hash_bucket_node *cur;
2170 ao2_sort_fn *sort_fn;
2173 bucket = &self->buckets[node->my_bucket];
2174 sort_fn = self->common.sort_fn;
2175 options = self->common.options;
2177 if (options & AO2_CONTAINER_ALLOC_OPT_INSERT_BEGIN) {
2179 AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_BEGIN(&bucket->list, cur, links) {
2180 cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_POINTER);
2185 AST_DLLIST_INSERT_AFTER_CURRENT(node, links);
2186 return AO2_CONTAINER_INSERT_NODE_INSERTED;
2188 switch (options & AO2_CONTAINER_ALLOC_OPT_DUPS_MASK) {
2190 case AO2_CONTAINER_ALLOC_OPT_DUPS_ALLOW:
2192 case AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT:
2193 /* Reject all objects with the same key. */
2194 return AO2_CONTAINER_INSERT_NODE_REJECTED;
2195 case AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT:
2196 if (cur->common.obj == node->common.obj) {
2197 /* Reject inserting the same object */
2198 return AO2_CONTAINER_INSERT_NODE_REJECTED;
2201 case AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE:
2202 SWAP(cur->common.obj, node->common.obj);
2203 return AO2_CONTAINER_INSERT_NODE_OBJ_REPLACED;
2206 AST_DLLIST_TRAVERSE_BACKWARDS_SAFE_END;
2208 AST_DLLIST_INSERT_HEAD(&bucket->list, node, links);
2211 AST_DLLIST_TRAVERSE_SAFE_BEGIN(&bucket->list, cur, links) {
2212 cmp = sort_fn(cur->common.obj, node->common.obj, OBJ_POINTER);
2217 AST_DLLIST_INSERT_BEFORE_CURRENT(node, links);
2218 return AO2_CONTAINER_INSERT_NODE_INSERTED;
2220 switch (options & AO2_CONTAINER_ALLOC_OPT_DUPS_MASK) {
2222 case AO2_CONTAINER_ALLOC_OPT_DUPS_ALLOW:
2224 case AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT:
2225 /* Reject all objects with the same key. */
2226 return AO2_CONTAINER_INSERT_NODE_REJECTED;
2227 case AO2_CONTAINER_ALLOC_OPT_DUPS_OBJ_REJECT:
2228 if (cur->common.obj == node->common.obj) {
2229 /* Reject inserting the same object */
2230 return AO2_CONTAINER_INSERT_NODE_REJECTED;
2233 case AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE:
2234 SWAP(cur->common.obj, node->common.obj);
2235 return AO2_CONTAINER_INSERT_NODE_OBJ_REPLACED;
2238 AST_DLLIST_TRAVERSE_SAFE_END;
2240 AST_DLLIST_INSERT_TAIL(&bucket->list, node, links);
2242 return AO2_CONTAINER_INSERT_NODE_INSERTED;
2245 /*! Traversal state to restart a hash container traversal. */
2246 struct hash_traversal_state {
2247 /*! Active sort function in the traversal if not NULL. */
2248 ao2_sort_fn *sort_fn;
2249 /*! Node returned in the sorted starting hash bucket if OBJ_CONTINUE flag set. (Reffed) */
2250 struct hash_bucket_node *first_node;
2251 /*! Saved comparison callback arg pointer. */
2253 /*! Starting hash bucket */
2255 /*! Stopping hash bucket */
2257 /*! Saved search flags to control traversing the container. */
2258 enum search_flags flags;
2259 /*! TRUE if it is a descending search */
2260 unsigned int descending:1;
2261 /*! TRUE if the starting bucket needs to be rechecked because of sorting skips. */
2262 unsigned int recheck_starting_bucket:1;
2265 struct hash_traversal_state_check {
2267 * If we have a division by zero compile error here then there
2268 * is not enough room for the state. Increase AO2_TRAVERSAL_STATE_SIZE.
2270 char check[1 / (AO2_TRAVERSAL_STATE_SIZE / sizeof(struct hash_traversal_state))];
2275 * \brief Find the first hash container node in a traversal.
2278 * \param self Container to operate upon.
2279 * \param flags search_flags to control traversing the container
2280 * \param arg Comparison callback arg parameter.
2281 * \param state Traversal state to restart hash container traversal.
2283 * \retval node-ptr of found node (Reffed).
2284 * \retval NULL when no node found.
2286 static struct hash_bucket_node *hash_ao2_find_first(struct ao2_container_hash *self, enum search_flags flags, void *arg, struct hash_traversal_state *state)
2288 struct hash_bucket_node *node;
2292 memset(state, 0, sizeof(*state));
2294 state->flags = flags;
2296 /* Determine traversal order. */
2297 switch (flags & OBJ_ORDER_MASK) {
2298 case OBJ_ORDER_POST:
2299 case OBJ_ORDER_DESCENDING:
2300 state->descending = 1;
2303 case OBJ_ORDER_ASCENDING:
2309 * If lookup by pointer or search key, run the hash and optional
2310 * sort functions. Otherwise, traverse the whole container.
2312 if (flags & (OBJ_POINTER | OBJ_KEY)) {
2313 /* we know hash can handle this case */
2314 bucket_cur = abs(self->hash_fn(arg, flags & (OBJ_POINTER | OBJ_KEY)));
2315 bucket_cur %= self->n_buckets;
2316 state->sort_fn = self->common.sort_fn;
2318 /* don't know, let's scan all buckets */
2320 state->sort_fn = (flags & OBJ_PARTIAL_KEY) ? self->common.sort_fn : NULL;
2323 if (state->descending) {
2325 * Determine the search boundaries of a descending traversal.
2327 * bucket_cur downto state->bucket_last
2329 if (bucket_cur < 0) {
2330 bucket_cur = self->n_buckets - 1;
2331 state->bucket_last = 0;
2333 state->bucket_last = bucket_cur;
2335 if (flags & OBJ_CONTINUE) {
2336 state->bucket_last = 0;
2337 if (state->sort_fn) {
2338 state->recheck_starting_bucket = 1;
2341 state->bucket_start = bucket_cur;
2343 /* For each bucket */
2344 for (; state->bucket_last <= bucket_cur; --bucket_cur) {
2345 /* For each node in the bucket. */
2346 for (node = AST_DLLIST_LAST(&self->buckets[bucket_cur].list);
2348 node = AST_DLLIST_PREV(node, links)) {
2349 if (!node->common.obj) {
2354 if (state->sort_fn) {
2355 /* Filter node through the sort_fn */
2356 cmp = state->sort_fn(node->common.obj, arg,
2357 flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
2361 if (flags & OBJ_CONTINUE) {
2362 /* Remember first node when we wrap around. */
2363 __ao2_ref(node, +1);
2364 state->first_node = node;
2366 /* From now on all nodes are matching */
2367 state->sort_fn = NULL;
2368 } else if (cmp < 0) {
2369 /* No more nodes in this bucket are possible to match. */
2374 /* We have the first traversal node */
2375 __ao2_ref(node, +1);
2379 /* Was this the starting bucket? */
2380 if (bucket_cur == state->bucket_start
2381 && (flags & OBJ_CONTINUE)
2382 && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
2383 /* In case the bucket was empty or none of the nodes matched. */
2384 state->sort_fn = NULL;
2387 /* Was this the first container bucket? */
2389 && (flags & OBJ_CONTINUE)
2390 && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
2391 /* Move to the end to ensure we check every bucket */
2392 bucket_cur = self->n_buckets;
2393 state->bucket_last = state->bucket_start + 1;
2394 if (state->recheck_starting_bucket) {
2396 * We have to recheck the first part of the starting bucket
2397 * because of sorting skips.
2399 state->recheck_starting_bucket = 0;
2400 --state->bucket_last;
2406 * Determine the search boundaries of an ascending traversal.
2408 * bucket_cur to state->bucket_last-1
2410 if (bucket_cur < 0) {
2412 state->bucket_last = self->n_buckets;
2414 state->bucket_last = bucket_cur + 1;
2416 if (flags & OBJ_CONTINUE) {
2417 state->bucket_last = self->n_buckets;
2418 if (state->sort_fn) {
2419 state->recheck_starting_bucket = 1;
2422 state->bucket_start = bucket_cur;
2424 /* For each bucket */
2425 for (; bucket_cur < state->bucket_last; ++bucket_cur) {
2426 /* For each node in the bucket. */
2427 for (node = AST_DLLIST_FIRST(&self->buckets[bucket_cur].list);
2429 node = AST_DLLIST_NEXT(node, links)) {
2430 if (!node->common.obj) {
2435 if (state->sort_fn) {
2436 /* Filter node through the sort_fn */
2437 cmp = state->sort_fn(node->common.obj, arg,
2438 flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
2442 if (flags & OBJ_CONTINUE) {
2443 /* Remember first node when we wrap around. */
2444 __ao2_ref(node, +1);
2445 state->first_node = node;
2447 /* From now on all nodes are matching */
2448 state->sort_fn = NULL;
2449 } else if (cmp > 0) {
2450 /* No more nodes in this bucket are possible to match. */
2455 /* We have the first traversal node */
2456 __ao2_ref(node, +1);
2460 /* Was this the starting bucket? */
2461 if (bucket_cur == state->bucket_start
2462 && (flags & OBJ_CONTINUE)
2463 && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
2464 /* In case the bucket was empty or none of the nodes matched. */
2465 state->sort_fn = NULL;
2468 /* Was this the last container bucket? */
2469 if (bucket_cur == self->n_buckets - 1
2470 && (flags & OBJ_CONTINUE)
2471 && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
2472 /* Move to the beginning to ensure we check every bucket */
2474 state->bucket_last = state->bucket_start;
2475 if (state->recheck_starting_bucket) {
2477 * We have to recheck the first part of the starting bucket
2478 * because of sorting skips.
2480 state->recheck_starting_bucket = 0;
2481 ++state->bucket_last;
2492 * \brief Find the next hash container node in a traversal.
2495 * \param self Container to operate upon.
2496 * \param state Traversal state to restart hash container traversal.
2497 * \param prev Previous node returned by the traversal search functions.
2498 * The ref ownership is passed back to this function.
2500 * \retval node-ptr of found node (Reffed).
2501 * \retval NULL when no node found.
2503 static struct hash_bucket_node *hash_ao2_find_next(struct ao2_container_hash *self, struct hash_traversal_state *state, struct hash_bucket_node *prev)
2505 struct hash_bucket_node *node;
2507 enum search_flags flags;
2512 flags = state->flags;
2513 bucket_cur = prev->my_bucket;
2517 * This function is structured the same as hash_ao2_find_first()
2518 * intentionally. We are resuming the search loops from
2519 * hash_ao2_find_first() in order to find the next node. The
2520 * search loops must be resumed where hash_ao2_find_first()
2521 * returned with the first node.
2523 if (state->descending) {
2524 goto hash_descending_resume;
2526 /* For each bucket */
2527 for (; state->bucket_last <= bucket_cur; --bucket_cur) {
2528 /* For each node in the bucket. */
2529 for (node = AST_DLLIST_LAST(&self->buckets[bucket_cur].list);
2531 node = AST_DLLIST_PREV(node, links)) {
2532 if (node == state->first_node) {
2533 /* We have wrapped back to the starting point. */
2534 __ao2_ref(prev, -1);
2537 if (!node->common.obj) {
2542 if (state->sort_fn) {
2543 /* Filter node through the sort_fn */
2544 cmp = state->sort_fn(node->common.obj, arg,
2545 flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
2550 /* No more nodes in this bucket are possible to match. */
2555 /* We have the next traversal node */
2556 __ao2_ref(node, +1);
2559 * Dereferencing the prev node may result in our next node
2560 * object being removed by another thread. This could happen if
2561 * the container uses RW locks and the container was read
2564 __ao2_ref(prev, -1);
2565 if (node->common.obj) {
2570 hash_descending_resume:;
2573 /* Was this the first container bucket? */
2575 && (flags & OBJ_CONTINUE)
2576 && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
2577 /* Move to the end to ensure we check every bucket */
2578 bucket_cur = self->n_buckets;
2579 state->bucket_last = state->bucket_start + 1;
2580 if (state->recheck_starting_bucket) {
2582 * We have to recheck the first part of the starting bucket
2583 * because of sorting skips.
2585 state->recheck_starting_bucket = 0;
2586 --state->bucket_last;
2591 goto hash_ascending_resume;
2593 /* For each bucket */
2594 for (; bucket_cur < state->bucket_last; ++bucket_cur) {
2595 /* For each node in the bucket. */
2596 for (node = AST_DLLIST_FIRST(&self->buckets[bucket_cur].list);
2598 node = AST_DLLIST_NEXT(node, links)) {
2599 if (node == state->first_node) {
2600 /* We have wrapped back to the starting point. */
2601 __ao2_ref(prev, -1);
2604 if (!node->common.obj) {
2609 if (state->sort_fn) {
2610 /* Filter node through the sort_fn */
2611 cmp = state->sort_fn(node->common.obj, arg,
2612 flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY));
2617 /* No more nodes in this bucket are possible to match. */
2622 /* We have the next traversal node */
2623 __ao2_ref(node, +1);
2626 * Dereferencing the prev node may result in our next node
2627 * object being removed by another thread. This could happen if
2628 * the container uses RW locks and the container was read
2631 __ao2_ref(prev, -1);
2632 if (node->common.obj) {
2637 hash_ascending_resume:;
2640 /* Was this the last container bucket? */
2641 if (bucket_cur == self->n_buckets - 1
2642 && (flags & OBJ_CONTINUE)
2643 && (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY))) {
2644 /* Move to the beginning to ensure we check every bucket */
2646 state->bucket_last = state->bucket_start;
2647 if (state->recheck_starting_bucket) {
2649 * We have to recheck the first part of the starting bucket
2650 * because of sorting skips.
2652 state->recheck_starting_bucket = 0;
2653 ++state->bucket_last;
2659 /* No more nodes in the container left to traverse. */
2660 __ao2_ref(prev, -1);
2666 * \brief Cleanup the hash container traversal state.
2669 * \param state Traversal state to cleanup.
2673 static void hash_ao2_find_cleanup(struct hash_traversal_state *state)
2675 if (state->first_node) {
2676 __ao2_ref(state->first_node, -1);
2682 * \brief Find the next non-empty iteration node in the container.
2685 * \param self Container to operate upon.
2686 * \param node Previous node returned by the iterator.
2687 * \param flags search_flags to control iterating the container.
2688 * Only AO2_ITERATOR_DESCENDING is useful by the method.
2690 * \note The container is already locked.
2692 * \retval node on success.
2693 * \retval NULL on error or no more nodes in the container.
2695 static struct hash_bucket_node *hash_ao2_iterator_next(struct ao2_container_hash *self, struct hash_bucket_node *node, enum ao2_iterator_flags flags)
2699 if (flags & AO2_ITERATOR_DESCENDING) {
2701 cur_bucket = node->my_bucket;
2703 /* Find next non-empty node. */
2705 node = AST_DLLIST_PREV(node, links);
2709 if (node->common.obj) {
2710 /* Found a non-empty node. */
2715 /* Find first non-empty node. */
2716 cur_bucket = self->n_buckets;
2719 /* Find a non-empty node in the remaining buckets */
2720 while (0 <= --cur_bucket) {
2721 node = AST_DLLIST_LAST(&self->buckets[cur_bucket].list);
2723 if (node->common.obj) {
2724 /* Found a non-empty node. */
2727 node = AST_DLLIST_PREV(node, links);
2732 cur_bucket = node->my_bucket;
2734 /* Find next non-empty node. */
2736 node = AST_DLLIST_NEXT(node, links);
2740 if (node->common.obj) {
2741 /* Found a non-empty node. */
2746 /* Find first non-empty node. */
2750 /* Find a non-empty node in the remaining buckets */
2751 while (++cur_bucket < self->n_buckets) {
2752 node = AST_DLLIST_FIRST(&self->buckets[cur_bucket].list);
2754 if (node->common.obj) {
2755 /* Found a non-empty node. */
2758 node = AST_DLLIST_NEXT(node, links);
2763 /* No more nodes to visit in the container. */
2767 #if defined(AST_DEVMODE)
2770 * \brief Increment the hash container linked object statistic.
2773 * \param hash Container to operate upon.
2774 * \param hash_node Container node linking object to.
2778 static void hash_ao2_link_node_stat(struct ao2_container *hash, struct ao2_container_node *hash_node)
2780 struct ao2_container_hash *self = (struct ao2_container_hash *) hash;
2781 struct hash_bucket_node *node = (struct hash_bucket_node *) hash_node;
2782 int i = node->my_bucket;
2784 ++self->buckets[i].elements;
2785 if (self->buckets[i].max_elements < self->buckets[i].elements) {
2786 self->buckets[i].max_elements = self->buckets[i].elements;
2789 #endif /* defined(AST_DEVMODE) */
2791 #if defined(AST_DEVMODE)
2794 * \brief Decrement the hash container linked object statistic.
2797 * \param hash Container to operate upon.
2798 * \param hash_node Container node unlinking object from.
2802 static void hash_ao2_unlink_node_stat(struct ao2_container *hash, struct ao2_container_node *hash_node)
2804 struct ao2_container_hash *self = (struct ao2_container_hash *) hash;
2805 struct hash_bucket_node *node = (struct hash_bucket_node *) hash_node;
2807 --self->buckets[node->my_bucket].elements;
2809 #endif /* defined(AST_DEVMODE) */
2814 * \brief Destroy this container.
2817 * \param self Container to operate upon.
2821 static void hash_ao2_destroy(struct ao2_container_hash *self)
2825 /* Check that the container no longer has any nodes */
2826 for (idx = self->n_buckets; idx--;) {
2827 if (!AST_DLLIST_EMPTY(&self->buckets[idx].list)) {
2828 ast_log(LOG_ERROR, "Node ref leak. Hash container still has nodes!\n");
2835 #if defined(AST_DEVMODE)
2838 * \brief Display contents of the specified container.
2841 * \param self Container to dump.
2842 * \param where User data needed by prnt to determine where to put output.
2843 * \param prnt Print output callback function to use.
2844 * \param prnt_obj Callback function to print the given object's key. (NULL if not available)
2848 static void hash_ao2_dump(struct ao2_container_hash *self, void *where, ao2_prnt_fn *prnt, ao2_prnt_obj_fn *prnt_obj)
2850 #define FORMAT "%6s, %16s, %16s, %16s, %16s, %s\n"
2851 #define FORMAT2 "%6d, %16p, %16p, %16p, %16p, "
2854 int suppressed_buckets = 0;
2855 struct hash_bucket_node *node;
2857 prnt(where, "Number of buckets: %d\n\n", self->n_buckets);
2859 prnt(where, FORMAT, "Bucket", "Node", "Prev", "Next", "Obj", "Key");
2860 for (bucket = 0; bucket < self->n_buckets; ++bucket) {
2861 node = AST_DLLIST_FIRST(&self->buckets[bucket].list);
2863 suppressed_buckets = 0;
2865 prnt(where, FORMAT2,
2868 AST_DLLIST_PREV(node, links),
2869 AST_DLLIST_NEXT(node, links),
2871 if (node->common.obj && prnt_obj) {
2872 prnt_obj(node->common.obj, where, prnt);
2876 node = AST_DLLIST_NEXT(node, links);
2878 } else if (!suppressed_buckets) {
2879 suppressed_buckets = 1;
2880 prnt(where, "...\n");
2887 #endif /* defined(AST_DEVMODE) */
2889 #if defined(AST_DEVMODE)
2892 * \brief Display statistics of the specified container.
2895 * \param self Container to display statistics.
2896 * \param where User data needed by prnt to determine where to put output.
2897 * \param prnt Print output callback function to use.
2899 * \note The container is already locked for reading.
2903 static void hash_ao2_stats(struct ao2_container_hash *self, void *where, ao2_prnt_fn *prnt)
2905 #define FORMAT "%10.10s %10.10s %10.10s\n"
2906 #define FORMAT2 "%10d %10d %10d\n"
2909 int suppressed_buckets = 0;
2911 prnt(where, "Number of buckets: %d\n\n", self->n_buckets);
2913 prnt(where, FORMAT, "Bucket", "Objects", "Max");
2914 for (bucket = 0; bucket < self->n_buckets; ++bucket) {
2915 if (self->buckets[bucket].max_elements) {
2916 suppressed_buckets = 0;
2917 prnt(where, FORMAT2, bucket, self->buckets[bucket].elements,
2918 self->buckets[bucket].max_elements);
2919 } else if (!suppressed_buckets) {
2920 suppressed_buckets = 1;
2921 prnt(where, "...\n");
2928 #endif /* defined(AST_DEVMODE) */
2930 #if defined(AST_DEVMODE)
2933 * \brief Perform an integrity check on the specified container.
2936 * \param self Container to check integrity.
2938 * \note The container is already locked for reading.
2940 * \retval 0 on success.
2941 * \retval -1 on error.
2943 static int hash_ao2_integrity(struct ao2_container_hash *self)
2948 int count_total_obj;
2949 int count_total_node;
2951 struct hash_bucket_node *node;
2952 struct hash_bucket_node *prev;
2953 struct hash_bucket_node *next;
2955 count_total_obj = 0;
2956 count_total_node = 0;
2958 /* For each bucket in the container. */
2959 for (bucket = 0; bucket < self->n_buckets; ++bucket) {
2960 if (!AST_DLLIST_FIRST(&self->buckets[bucket].list)
2961 && !AST_DLLIST_LAST(&self->buckets[bucket].list)) {
2962 /* The bucket list is empty. */
2969 /* Check bucket list links and nodes. */
2970 node = AST_DLLIST_LAST(&self->buckets[bucket].list);
2972 ast_log(LOG_ERROR, "Bucket %d list tail is NULL when it should not be!\n",
2976 if (AST_DLLIST_NEXT(node, links)) {
2977 ast_log(LOG_ERROR, "Bucket %d list tail node is not the last node!\n",
2981 node = AST_DLLIST_FIRST(&self->buckets[bucket].list);
2983 ast_log(LOG_ERROR, "Bucket %d list head is NULL when it should not be!\n",
2987 if (AST_DLLIST_PREV(node, links)) {
2988 ast_log(LOG_ERROR, "Bucket %d list head node is not the first node!\n",
2992 for (; node; node = next) {
2993 /* Check backward link. */
2994 prev = AST_DLLIST_PREV(node, links);
2997 ast_log(LOG_ERROR, "Bucket %d list node's prev pointer points to itself!\n",
3001 if (node != AST_DLLIST_NEXT(prev, links)) {
3002 ast_log(LOG_ERROR, "Bucket %d list node's prev node does not link back!\n",
3006 } else if (node != AST_DLLIST_FIRST(&self->buckets[bucket].list)) {
3007 ast_log(LOG_ERROR, "Bucket %d backward list chain is broken!\n",
3012 /* Check forward link. */
3013 next = AST_DLLIST_NEXT(node, links);
3016 ast_log(LOG_ERROR, "Bucket %d list node's next pointer points to itself!\n",
3020 if (node != AST_DLLIST_PREV(next, links)) {
3021 ast_log(LOG_ERROR, "Bucket %d list node's next node does not link back!\n",
3025 } else if (node != AST_DLLIST_LAST(&self->buckets[bucket].list)) {
3026 ast_log(LOG_ERROR, "Bucket %d forward list chain is broken!\n",
3031 if (bucket != node->my_bucket) {
3032 ast_log(LOG_ERROR, "Bucket %d node claims to be in bucket %d!\n",
3033 bucket, node->my_bucket);
3038 if (!node->common.obj) {
3039 /* Node is empty. */
3044 /* Check container hash key for expected bucket. */
3045 bucket_exp = abs(self->hash_fn(node->common.obj, OBJ_POINTER));
3046 bucket_exp %= self->n_buckets;
3047 if (bucket != bucket_exp) {
3048 ast_log(LOG_ERROR, "Bucket %d node hashes to bucket %d!\n",
3049 bucket, bucket_exp);
3053 /* Check sort if configured. */
3054 if (self->common.sort_fn) {
3056 && self->common.sort_fn(obj_last, node->common.obj, OBJ_POINTER) > 0) {
3057 ast_log(LOG_ERROR, "Bucket %d nodes out of sorted order!\n",
3061 obj_last = node->common.obj;
3065 /* Check bucket obj count statistic. */
3066 if (count_obj != self->buckets[bucket].elements) {
3067 ast_log(LOG_ERROR, "Bucket %d object count of %d does not match stat of %d!\n",
3068 bucket, count_obj, self->buckets[bucket].elements);
3072 /* Accumulate found object counts. */
3073 count_total_obj += count_obj;
3076 /* Check total obj count. */
3077 if (count_total_obj != ao2_container_count(&self->common)) {
3079 "Total object count of %d does not match ao2_container_count() of %d!\n",
3080 count_total_obj, ao2_container_count(&self->common));
3084 /* Check total node count. */
3085 if (count_total_node != self->common.nodes) {
3086 ast_log(LOG_ERROR, "Total node count of %d does not match stat of %d!\n",
3087 count_total_node, self->common.nodes);
3093 #endif /* defined(AST_DEVMODE) */
3095 /*! Hash container virtual method table. */
3096 static const struct ao2_container_methods v_table_hash = {
3097 .type = AO2_CONTAINER_RTTI_HASH,
3098 .alloc_empty_clone = (ao2_container_alloc_empty_clone_fn) hash_ao2_alloc_empty_clone,
3099 .alloc_empty_clone_debug =
3100 (ao2_container_alloc_empty_clone_debug_fn) hash_ao2_alloc_empty_clone_debug,
3101 .new_node = (ao2_container_new_node_fn) hash_ao2_new_node,
3102 .insert = (ao2_container_insert_fn) hash_ao2_insert_node,
3103 .traverse_first = (ao2_container_find_first_fn) hash_ao2_find_first,
3104 .traverse_next = (ao2_container_find_next_fn) hash_ao2_find_next,
3105 .traverse_cleanup = (ao2_container_find_cleanup_fn) hash_ao2_find_cleanup,
3106 .iterator_next = (ao2_iterator_next_fn) hash_ao2_iterator_next,
3107 .destroy = (ao2_container_destroy_fn) hash_ao2_destroy,
3108 #if defined(AST_DEVMODE)
3109 .dump = (ao2_container_display) hash_ao2_dump,
3110 .stats = (ao2_container_statistics) hash_ao2_stats,
3111 .integrity = (ao2_container_integrity) hash_ao2_integrity,
3112 #endif /* defined(AST_DEVMODE) */
3116 * \brief always zero hash function
3118 * it is convenient to have a hash function that always returns 0.
3119 * This is basically used when we want to have a container that is
3120 * a simple linked list.
3124 static int hash_zero(const void *user_obj, const int flags)
3130 * \brief Initialize a hash container with the desired number of buckets.
3132 * \param self Container to initialize.
3133 * \param options Container behaviour options (See enum ao2_container_opts)
3134 * \param n_buckets Number of buckets for hash
3135 * \param hash_fn Pointer to a function computing a hash value.
3136 * \param sort_fn Pointer to a sort function.
3137 * \param cmp_fn Pointer to a compare function used by ao2_find.
3139 * \return A pointer to a struct container.
3141 static struct ao2_container *hash_ao2_container_init(
3142 struct ao2_container_hash *self, unsigned int options, unsigned int n_buckets,
3143 ao2_hash_fn *hash_fn, ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn)
3149 self->common.v_table = &v_table_hash;
3150 self->common.sort_fn = sort_fn;
3151 self->common.cmp_fn = cmp_fn;
3152 self->common.options = options;
3153 self->hash_fn = hash_fn ? hash_fn : hash_zero;
3154 self->n_buckets = n_buckets;
3157 ast_atomic_fetchadd_int(&ao2.total_containers, 1);
3160 return (struct ao2_container *) self;
3163 struct ao2_container *__ao2_container_alloc_hash(unsigned int ao2_options,
3164 unsigned int container_options, unsigned int n_buckets, ao2_hash_fn *hash_fn,
3165 ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn)
3167 unsigned int num_buckets;
3168 size_t container_size;
3169 struct ao2_container_hash *self;
3171 num_buckets = hash_fn ? n_buckets : 1;
3172 container_size = sizeof(struct ao2_container_hash) + num_buckets * sizeof(struct hash_bucket);
3174 self = ao2_t_alloc_options(container_size, container_destruct, ao2_options,
3175 "New hash container");
3176 return hash_ao2_container_init(self, container_options, num_buckets,
3177 hash_fn, sort_fn, cmp_fn);
3180 struct ao2_container *__ao2_container_alloc_hash_debug(unsigned int ao2_options,
3181 unsigned int container_options, unsigned int n_buckets, ao2_hash_fn *hash_fn,
3182 ao2_sort_fn *sort_fn, ao2_callback_fn *cmp_fn,
3183 const char *tag, const char *file, int line, const char *func, int ref_debug)