Sat Apr 26 2014 22:01:29

Asterisk developer's documentation


astobj2.c
Go to the documentation of this file.
00001 /*
00002  * astobj2 - replacement containers for asterisk data structures.
00003  *
00004  * Copyright (C) 2006 Marta Carbone, Luigi Rizzo - Univ. di Pisa, Italy
00005  *
00006  * See http://www.asterisk.org for more information about
00007  * the Asterisk project. Please do not directly contact
00008  * any of the maintainers of this project for assistance;
00009  * the project provides a web site, mailing lists and IRC
00010  * channels for your use.
00011  *
00012  * This program is free software, distributed under the terms of
00013  * the GNU General Public License Version 2. See the LICENSE file
00014  * at the top of the source tree.
00015  */
00016 
00017 /*
00018  * Function implementing astobj2 objects.
00019  */
00020 
00021 /*** MODULEINFO
00022    <support_level>core</support_level>
00023  ***/
00024 
00025 #include "asterisk.h"
00026 
00027 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409567 $")
00028 
00029 #include "asterisk/_private.h"
00030 #include "asterisk/astobj2.h"
00031 #include "asterisk/linkedlists.h"
00032 #include "asterisk/utils.h"
00033 #include "asterisk/cli.h"
00034 #define REF_FILE "/tmp/refs"
00035 
00036 #if defined(TEST_FRAMEWORK)
00037 /* We are building with the test framework enabled so enable AO2 debug tests as well. */
00038 #define AO2_DEBUG 1
00039 #endif   /* defined(TEST_FRAMEWORK) */
00040 
00041 /*!
00042  * astobj2 objects are always preceded by this data structure,
00043  * which contains a reference counter,
00044  * option flags and a pointer to a destructor.
00045  * The refcount is used to decide when it is time to
00046  * invoke the destructor.
00047  * The magic number is used for consistency check.
00048  */
00049 struct __priv_data {
00050    int ref_counter;
00051    ao2_destructor_fn destructor_fn;
00052    /*! User data size for stats */
00053    size_t data_size;
00054    /*! The ao2 object option flags */
00055    uint32_t options;
00056    /*! magic number.  This is used to verify that a pointer passed in is a
00057     *  valid astobj2 */
00058    uint32_t magic;
00059 };
00060 
00061 #define  AO2_MAGIC   0xa570b123
00062 
00063 /*!
00064  * What an astobj2 object looks like: fixed-size private data
00065  * followed by variable-size user data.
00066  */
00067 struct astobj2 {
00068    struct __priv_data priv_data;
00069    void *user_data[0];
00070 };
00071 
00072 struct ao2_lock_priv {
00073    ast_mutex_t lock;
00074 };
00075 
00076 /* AstObj2 with recursive lock. */
00077 struct astobj2_lock {
00078    struct ao2_lock_priv mutex;
00079    struct __priv_data priv_data;
00080    void *user_data[0];
00081 };
00082 
00083 struct ao2_rwlock_priv {
00084    ast_rwlock_t lock;
00085    /*! Count of the number of threads holding a lock on this object. -1 if it is the write lock. */
00086    int num_lockers;
00087 };
00088 
00089 /* AstObj2 with RW lock. */
00090 struct astobj2_rwlock {
00091    struct ao2_rwlock_priv rwlock;
00092    struct __priv_data priv_data;
00093    void *user_data[0];
00094 };
00095 
00096 #ifdef AO2_DEBUG
00097 struct ao2_stats {
00098    volatile int total_objects;
00099    volatile int total_mem;
00100    volatile int total_containers;
00101    volatile int total_refs;
00102    volatile int total_locked;
00103 };
00104 
00105 static struct ao2_stats ao2;
00106 #endif
00107 
00108 #ifndef HAVE_BKTR /* backtrace support */
00109 void ao2_bt(void) {}
00110 #else
00111 #include <execinfo.h>    /* for backtrace */
00112 
00113 void ao2_bt(void)
00114 {
00115    int c, i;
00116 #define N1  20
00117    void *addresses[N1];
00118    char **strings;
00119 
00120    c = backtrace(addresses, N1);
00121    strings = ast_bt_get_symbols(addresses,c);
00122    ast_verbose("backtrace returned: %d\n", c);
00123    for(i = 0; i < c; i++) {
00124       ast_verbose("%d: %p %s\n", i, addresses[i], strings[i]);
00125    }
00126    ast_std_free(strings);
00127 }
00128 #endif
00129 
00130 #define INTERNAL_OBJ_MUTEX(user_data) \
00131    ((struct astobj2_lock *) (((char *) (user_data)) - sizeof(struct astobj2_lock)))
00132 
00133 #define INTERNAL_OBJ_RWLOCK(user_data) \
00134    ((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))
00135 
00136 /*!
00137  * \brief convert from a pointer _p to a user-defined object
00138  *
00139  * \return the pointer to the astobj2 structure
00140  */
00141 static inline struct astobj2 *INTERNAL_OBJ(void *user_data)
00142 {
00143    struct astobj2 *p;
00144 
00145    if (!user_data) {
00146       ast_log(LOG_ERROR, "user_data is NULL\n");
00147       return NULL;
00148    }
00149 
00150    p = (struct astobj2 *) ((char *) user_data - sizeof(*p));
00151    if (AO2_MAGIC != p->priv_data.magic) {
00152       if (p->priv_data.magic) {
00153          ast_log(LOG_ERROR, "bad magic number 0x%x for object %p\n",
00154             p->priv_data.magic, user_data);
00155       } else {
00156          ast_log(LOG_ERROR,
00157             "bad magic number for object %p. Object is likely destroyed.\n",
00158             user_data);
00159       }
00160       ast_assert(0);
00161       return NULL;
00162    }
00163 
00164    return p;
00165 }
00166 
00167 enum ao2_callback_type {
00168    DEFAULT,
00169    WITH_DATA,
00170 };
00171 
00172 /*!
00173  * \brief convert from a pointer _p to an astobj2 object
00174  *
00175  * \return the pointer to the user-defined portion.
00176  */
00177 #define EXTERNAL_OBJ(_p)   ((_p) == NULL ? NULL : (_p)->user_data)
00178 
00179 int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
00180 {
00181    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00182    struct astobj2_lock *obj_mutex;
00183    struct astobj2_rwlock *obj_rwlock;
00184    int res = 0;
00185 
00186    if (obj == NULL) {
00187       return -1;
00188    }
00189 
00190    switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
00191    case AO2_ALLOC_OPT_LOCK_MUTEX:
00192       obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
00193       res = __ast_pthread_mutex_lock(file, line, func, var, &obj_mutex->mutex.lock);
00194 #ifdef AO2_DEBUG
00195       if (!res) {
00196          ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00197       }
00198 #endif
00199       break;
00200    case AO2_ALLOC_OPT_LOCK_RWLOCK:
00201       obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
00202       switch (lock_how) {
00203       case AO2_LOCK_REQ_MUTEX:
00204       case AO2_LOCK_REQ_WRLOCK:
00205          res = __ast_rwlock_wrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
00206          if (!res) {
00207             ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
00208 #ifdef AO2_DEBUG
00209             ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00210 #endif
00211          }
00212          break;
00213       case AO2_LOCK_REQ_RDLOCK:
00214          res = __ast_rwlock_rdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
00215          if (!res) {
00216             ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
00217 #ifdef AO2_DEBUG
00218             ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00219 #endif
00220          }
00221          break;
00222       }
00223       break;
00224    case AO2_ALLOC_OPT_LOCK_NOLOCK:
00225       /* The ao2 object has no lock. */
00226       break;
00227    default:
00228       ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
00229          user_data);
00230       return -1;
00231    }
00232 
00233    return res;
00234 }
00235 
00236 int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
00237 {
00238    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00239    struct astobj2_lock *obj_mutex;
00240    struct astobj2_rwlock *obj_rwlock;
00241    int res = 0;
00242    int current_value;
00243 
00244    if (obj == NULL) {
00245       return -1;
00246    }
00247 
00248    switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
00249    case AO2_ALLOC_OPT_LOCK_MUTEX:
00250       obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
00251       res = __ast_pthread_mutex_unlock(file, line, func, var, &obj_mutex->mutex.lock);
00252 #ifdef AO2_DEBUG
00253       if (!res) {
00254          ast_atomic_fetchadd_int(&ao2.total_locked, -1);
00255       }
00256 #endif
00257       break;
00258    case AO2_ALLOC_OPT_LOCK_RWLOCK:
00259       obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
00260 
00261       current_value = ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1) - 1;
00262       if (current_value < 0) {
00263          /* It was a WRLOCK that we are unlocking.  Fix the count. */
00264          ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -current_value);
00265       }
00266       res = __ast_rwlock_unlock(file, line, func, &obj_rwlock->rwlock.lock, var);
00267 #ifdef AO2_DEBUG
00268       if (!res) {
00269          ast_atomic_fetchadd_int(&ao2.total_locked, -1);
00270       }
00271 #endif
00272       break;
00273    case AO2_ALLOC_OPT_LOCK_NOLOCK:
00274       /* The ao2 object has no lock. */
00275       break;
00276    default:
00277       ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
00278          user_data);
00279       res = -1;
00280       break;
00281    }
00282    return res;
00283 }
00284 
00285 int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
00286 {
00287    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00288    struct astobj2_lock *obj_mutex;
00289    struct astobj2_rwlock *obj_rwlock;
00290    int res = 0;
00291 
00292    if (obj == NULL) {
00293       return -1;
00294    }
00295 
00296    switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
00297    case AO2_ALLOC_OPT_LOCK_MUTEX:
00298       obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
00299       res = __ast_pthread_mutex_trylock(file, line, func, var, &obj_mutex->mutex.lock);
00300 #ifdef AO2_DEBUG
00301       if (!res) {
00302          ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00303       }
00304 #endif
00305       break;
00306    case AO2_ALLOC_OPT_LOCK_RWLOCK:
00307       obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
00308       switch (lock_how) {
00309       case AO2_LOCK_REQ_MUTEX:
00310       case AO2_LOCK_REQ_WRLOCK:
00311          res = __ast_rwlock_trywrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
00312          if (!res) {
00313             ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
00314 #ifdef AO2_DEBUG
00315             ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00316 #endif
00317          }
00318          break;
00319       case AO2_LOCK_REQ_RDLOCK:
00320          res = __ast_rwlock_tryrdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
00321          if (!res) {
00322             ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
00323 #ifdef AO2_DEBUG
00324             ast_atomic_fetchadd_int(&ao2.total_locked, 1);
00325 #endif
00326          }
00327          break;
00328       }
00329       break;
00330    case AO2_ALLOC_OPT_LOCK_NOLOCK:
00331       /* The ao2 object has no lock. */
00332       return 0;
00333    default:
00334       ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
00335          user_data);
00336       return -1;
00337    }
00338 
00339 
00340    return res;
00341 }
00342 
00343 /*!
00344  * \internal
00345  * \brief Adjust an object's lock to the requested level.
00346  *
00347  * \param user_data An ao2 object to adjust lock level.
00348  * \param lock_how What level to adjust lock.
00349  * \param keep_stronger TRUE if keep original lock level if it is stronger.
00350  *
00351  * \pre The ao2 object is already locked.
00352  *
00353  * \details
00354  * An ao2 object with a RWLOCK will have its lock level adjusted
00355  * to the specified level if it is not already there.  An ao2
00356  * object with a different type of lock is not affected.
00357  *
00358  * \return Original lock level.
00359  */
00360 static enum ao2_lock_req adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
00361 {
00362    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00363    struct astobj2_rwlock *obj_rwlock;
00364    enum ao2_lock_req orig_lock;
00365 
00366    switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
00367    case AO2_ALLOC_OPT_LOCK_RWLOCK:
00368       obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
00369       if (obj_rwlock->rwlock.num_lockers < 0) {
00370          orig_lock = AO2_LOCK_REQ_WRLOCK;
00371       } else {
00372          orig_lock = AO2_LOCK_REQ_RDLOCK;
00373       }
00374       switch (lock_how) {
00375       case AO2_LOCK_REQ_MUTEX:
00376          lock_how = AO2_LOCK_REQ_WRLOCK;
00377          /* Fall through */
00378       case AO2_LOCK_REQ_WRLOCK:
00379          if (lock_how != orig_lock) {
00380             /* Switch from read lock to write lock. */
00381             ao2_unlock(user_data);
00382             ao2_wrlock(user_data);
00383          }
00384          break;
00385       case AO2_LOCK_REQ_RDLOCK:
00386          if (!keep_stronger && lock_how != orig_lock) {
00387             /* Switch from write lock to read lock. */
00388             ao2_unlock(user_data);
00389             ao2_rdlock(user_data);
00390          }
00391          break;
00392       }
00393       break;
00394    default:
00395       ast_log(LOG_ERROR, "Invalid lock option on ao2 object %p\n", user_data);
00396       /* Fall through */
00397    case AO2_ALLOC_OPT_LOCK_NOLOCK:
00398    case AO2_ALLOC_OPT_LOCK_MUTEX:
00399       orig_lock = AO2_LOCK_REQ_MUTEX;
00400       break;
00401    }
00402 
00403    return orig_lock;
00404 }
00405 
00406 void *ao2_object_get_lockaddr(void *user_data)
00407 {
00408    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00409    struct astobj2_lock *obj_mutex;
00410 
00411    if (obj == NULL) {
00412       return NULL;
00413    }
00414 
00415    switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
00416    case AO2_ALLOC_OPT_LOCK_MUTEX:
00417       obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
00418       return &obj_mutex->mutex.lock;
00419    default:
00420       break;
00421    }
00422 
00423    return NULL;
00424 }
00425 
00426 static int internal_ao2_ref(void *user_data, int delta, const char *file, int line, const char *func)
00427 {
00428    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00429    struct astobj2_lock *obj_mutex;
00430    struct astobj2_rwlock *obj_rwlock;
00431    int current_value;
00432    int ret;
00433 
00434    if (obj == NULL) {
00435       return -1;
00436    }
00437 
00438    /* if delta is 0, just return the refcount */
00439    if (delta == 0) {
00440       return obj->priv_data.ref_counter;
00441    }
00442 
00443    /* we modify with an atomic operation the reference counter */
00444    ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta);
00445    current_value = ret + delta;
00446 
00447 #ifdef AO2_DEBUG
00448    ast_atomic_fetchadd_int(&ao2.total_refs, delta);
00449 #endif
00450 
00451    if (0 < current_value) {
00452       /* The object still lives. */
00453       return ret;
00454    }
00455 
00456    /* this case must never happen */
00457    if (current_value < 0) {
00458       ast_log(__LOG_ERROR, file, line, func,
00459          "Invalid refcount %d on ao2 object %p\n", current_value, user_data);
00460    }
00461 
00462    /* last reference, destroy the object */
00463    if (obj->priv_data.destructor_fn != NULL) {
00464       obj->priv_data.destructor_fn(user_data);
00465    }
00466 
00467 #ifdef AO2_DEBUG
00468    ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
00469    ast_atomic_fetchadd_int(&ao2.total_objects, -1);
00470 #endif
00471 
00472    switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
00473    case AO2_ALLOC_OPT_LOCK_MUTEX:
00474       obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
00475       ast_mutex_destroy(&obj_mutex->mutex.lock);
00476 
00477       /*
00478        * For safety, zero-out the astobj2_lock header and also the
00479        * first word of the user-data, which we make sure is always
00480        * allocated.
00481        */
00482       memset(obj_mutex, '\0', sizeof(*obj_mutex) + sizeof(void *) );
00483       ast_free(obj_mutex);
00484       break;
00485    case AO2_ALLOC_OPT_LOCK_RWLOCK:
00486       obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
00487       ast_rwlock_destroy(&obj_rwlock->rwlock.lock);
00488 
00489       /*
00490        * For safety, zero-out the astobj2_rwlock header and also the
00491        * first word of the user-data, which we make sure is always
00492        * allocated.
00493        */
00494       memset(obj_rwlock, '\0', sizeof(*obj_rwlock) + sizeof(void *) );
00495       ast_free(obj_rwlock);
00496       break;
00497    case AO2_ALLOC_OPT_LOCK_NOLOCK:
00498       /*
00499        * For safety, zero-out the astobj2 header and also the first
00500        * word of the user-data, which we make sure is always
00501        * allocated.
00502        */
00503       memset(obj, '\0', sizeof(*obj) + sizeof(void *) );
00504       ast_free(obj);
00505       break;
00506    default:
00507       ast_log(__LOG_ERROR, file, line, func,
00508          "Invalid lock option on ao2 object %p\n", user_data);
00509       break;
00510    }
00511 
00512    return ret;
00513 }
00514 
00515 int __ao2_ref_debug(void *user_data, int delta, const char *tag, const char *file, int line, const char *func)
00516 {
00517    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00518 
00519    if (obj == NULL)
00520       return -1;
00521 
00522    if (delta != 0) {
00523       FILE *refo = fopen(REF_FILE, "a");
00524       if (refo) {
00525          fprintf(refo, "%p %s%d   %s:%d:%s (%s) [@%d]\n", user_data, (delta < 0 ? "" : "+"),
00526             delta, file, line, func, tag, obj->priv_data.ref_counter);
00527          fclose(refo);
00528       }
00529    }
00530    if (obj->priv_data.ref_counter + delta == 0 && obj->priv_data.destructor_fn != NULL) { /* this isn't protected with lock; just for o/p */
00531       FILE *refo = fopen(REF_FILE, "a");
00532       if (refo) {
00533          fprintf(refo, "%p **call destructor** %s:%d:%s (%s)\n", user_data, file, line, func, tag);
00534          fclose(refo);
00535       }
00536    }
00537    return internal_ao2_ref(user_data, delta, file, line, func);
00538 }
00539 
00540 int __ao2_ref(void *user_data, int delta)
00541 {
00542    return internal_ao2_ref(user_data, delta, __FILE__, __LINE__, __FUNCTION__);
00543 }
00544 
00545 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)
00546 {
00547    /* allocation */
00548    struct astobj2 *obj;
00549    struct astobj2_lock *obj_mutex;
00550    struct astobj2_rwlock *obj_rwlock;
00551 
00552    if (data_size < sizeof(void *)) {
00553       /*
00554        * We always alloc at least the size of a void *,
00555        * for debugging purposes.
00556        */
00557       data_size = sizeof(void *);
00558    }
00559 
00560    switch (options & AO2_ALLOC_OPT_LOCK_MASK) {
00561    case AO2_ALLOC_OPT_LOCK_MUTEX:
00562 #if defined(__AST_DEBUG_MALLOC)
00563       obj_mutex = __ast_calloc(1, sizeof(*obj_mutex) + data_size, file, line, func);
00564 #else
00565       obj_mutex = ast_calloc(1, sizeof(*obj_mutex) + data_size);
00566 #endif
00567       if (obj_mutex == NULL) {
00568          return NULL;
00569       }
00570 
00571       ast_mutex_init(&obj_mutex->mutex.lock);
00572       obj = (struct astobj2 *) &obj_mutex->priv_data;
00573       break;
00574    case AO2_ALLOC_OPT_LOCK_RWLOCK:
00575 #if defined(__AST_DEBUG_MALLOC)
00576       obj_rwlock = __ast_calloc(1, sizeof(*obj_rwlock) + data_size, file, line, func);
00577 #else
00578       obj_rwlock = ast_calloc(1, sizeof(*obj_rwlock) + data_size);
00579 #endif
00580       if (obj_rwlock == NULL) {
00581          return NULL;
00582       }
00583 
00584       ast_rwlock_init(&obj_rwlock->rwlock.lock);
00585       obj = (struct astobj2 *) &obj_rwlock->priv_data;
00586       break;
00587    case AO2_ALLOC_OPT_LOCK_NOLOCK:
00588 #if defined(__AST_DEBUG_MALLOC)
00589       obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, func);
00590 #else
00591       obj = ast_calloc(1, sizeof(*obj) + data_size);
00592 #endif
00593       if (obj == NULL) {
00594          return NULL;
00595       }
00596       break;
00597    default:
00598       /* Invalid option value. */
00599       ast_log(__LOG_DEBUG, file, line, func, "Invalid lock option requested\n");
00600       return NULL;
00601    }
00602 
00603    /* Initialize common ao2 values. */
00604    obj->priv_data.ref_counter = 1;
00605    obj->priv_data.destructor_fn = destructor_fn;   /* can be NULL */
00606    obj->priv_data.data_size = data_size;
00607    obj->priv_data.options = options;
00608    obj->priv_data.magic = AO2_MAGIC;
00609 
00610 #ifdef AO2_DEBUG
00611    ast_atomic_fetchadd_int(&ao2.total_objects, 1);
00612    ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
00613    ast_atomic_fetchadd_int(&ao2.total_refs, 1);
00614 #endif
00615 
00616    /* return a pointer to the user data */
00617    return EXTERNAL_OBJ(obj);
00618 }
00619 
00620 void *__ao2_alloc_debug(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options, const char *tag,
00621    const char *file, int line, const char *func, int ref_debug)
00622 {
00623    /* allocation */
00624    void *obj;
00625    FILE *refo;
00626 
00627    if ((obj = internal_ao2_alloc(data_size, destructor_fn, options, file, line, func)) == NULL) {
00628       return NULL;
00629    }
00630 
00631    if (ref_debug && (refo = fopen(REF_FILE, "a"))) {
00632       fprintf(refo, "%p =1   %s:%d:%s (%s)\n", obj, file, line, func, tag);
00633       fclose(refo);
00634    }
00635 
00636    /* return a pointer to the user data */
00637    return obj;
00638 }
00639 
00640 void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options)
00641 {
00642    return internal_ao2_alloc(data_size, destructor_fn, options, __FILE__, __LINE__, __FUNCTION__);
00643 }
00644 
00645 
00646 void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name)
00647 {
00648    if (!holder) {
00649       /* For sanity */
00650       ast_log(LOG_ERROR, "Must be called with a global object!\n");
00651       return;
00652    }
00653    if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
00654       /* Could not get the write lock. */
00655       return;
00656    }
00657 
00658    /* Release the held ao2 object. */
00659    if (holder->obj) {
00660       if (tag) {
00661          __ao2_ref_debug(holder->obj, -1, tag, file, line, func);
00662       } else {
00663          __ao2_ref(holder->obj, -1);
00664       }
00665       holder->obj = NULL;
00666    }
00667 
00668    __ast_rwlock_unlock(file, line, func, &holder->lock, name);
00669 }
00670 
00671 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)
00672 {
00673    void *obj_old;
00674 
00675    if (!holder) {
00676       /* For sanity */
00677       ast_log(LOG_ERROR, "Must be called with a global object!\n");
00678       return NULL;
00679    }
00680    if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
00681       /* Could not get the write lock. */
00682       return NULL;
00683    }
00684 
00685    if (obj) {
00686       if (tag) {
00687          __ao2_ref_debug(obj, +1, tag, file, line, func);
00688       } else {
00689          __ao2_ref(obj, +1);
00690       }
00691    }
00692    obj_old = holder->obj;
00693    holder->obj = obj;
00694 
00695    __ast_rwlock_unlock(file, line, func, &holder->lock, name);
00696 
00697    return obj_old;
00698 }
00699 
00700 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)
00701 {
00702    void *obj_old;
00703 
00704    obj_old = __ao2_global_obj_replace(holder, obj, tag, file, line, func, name);
00705    if (obj_old) {
00706       if (tag) {
00707          __ao2_ref_debug(obj_old, -1, tag, file, line, func);
00708       } else {
00709          __ao2_ref(obj_old, -1);
00710       }
00711       return 1;
00712    }
00713    return 0;
00714 }
00715 
00716 void *__ao2_global_obj_ref(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name)
00717 {
00718    void *obj;
00719 
00720    if (!holder) {
00721       /* For sanity */
00722       ast_log(LOG_ERROR, "Must be called with a global object!\n");
00723       return NULL;
00724    }
00725 
00726    if (__ast_rwlock_rdlock(file, line, func, &holder->lock, name)) {
00727       /* Could not get the read lock. */
00728       return NULL;
00729    }
00730 
00731    obj = holder->obj;
00732    if (obj) {
00733       if (tag) {
00734          __ao2_ref_debug(obj, +1, tag, file, line, func);
00735       } else {
00736          __ao2_ref(obj, +1);
00737       }
00738    }
00739 
00740    __ast_rwlock_unlock(file, line, func, &holder->lock, name);
00741 
00742    return obj;
00743 }
00744 
00745 /* internal callback to destroy a container. */
00746 static void container_destruct(void *c);
00747 
00748 /* internal callback to destroy a container. */
00749 static void container_destruct_debug(void *c);
00750 
00751 /*!
00752  * A structure to create a linked list of entries,
00753  * used within a bucket.
00754  * XXX \todo this should be private to the container code
00755  */
00756 struct bucket_entry {
00757    AST_LIST_ENTRY(bucket_entry) entry;
00758    int version;
00759    struct astobj2 *astobj;/* pointer to internal data */
00760 };
00761 
00762 /* each bucket in the container is a tailq. */
00763 AST_LIST_HEAD_NOLOCK(bucket, bucket_entry);
00764 
00765 /*!
00766  * A container; stores the hash and callback functions, information on
00767  * the size, the hash bucket heads, and a version number, starting at 0
00768  * (for a newly created, empty container)
00769  * and incremented every time an object is inserted or deleted.
00770  * The assumption is that an object is never moved in a container,
00771  * but removed and readded with the new number.
00772  * The version number is especially useful when implementing iterators.
00773  * In fact, we can associate a unique, monotonically increasing number to
00774  * each object, which means that, within an iterator, we can store the
00775  * version number of the current object, and easily look for the next one,
00776  * which is the next one in the list with a higher number.
00777  * Since all objects have a version >0, we can use 0 as a marker for
00778  * 'we need the first object in the bucket'.
00779  *
00780  * \todo Linking and unlink objects is typically expensive, as it
00781  * involves a malloc() of a small object which is very inefficient.
00782  * To optimize this, we allocate larger arrays of bucket_entry's
00783  * when we run out of them, and then manage our own freelist.
00784  * This will be more efficient as we can do the freelist management while
00785  * we hold the lock (that we need anyways).
00786  */
00787 struct ao2_container {
00788    ao2_hash_fn *hash_fn;
00789    ao2_callback_fn *cmp_fn;
00790    int n_buckets;
00791    /*! Number of elements in the container */
00792    int elements;
00793    /*! described above */
00794    int version;
00795    /*! variable size */
00796    struct bucket buckets[0];
00797 };
00798 
00799 /*!
00800  * \brief always zero hash function
00801  *
00802  * it is convenient to have a hash function that always returns 0.
00803  * This is basically used when we want to have a container that is
00804  * a simple linked list.
00805  *
00806  * \returns 0
00807  */
00808 static int hash_zero(const void *user_obj, const int flags)
00809 {
00810    return 0;
00811 }
00812 
00813 /*
00814  * A container is just an object, after all!
00815  */
00816 static struct ao2_container *internal_ao2_container_alloc(struct ao2_container *c,
00817    unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
00818 {
00819    /* XXX maybe consistency check on arguments ? */
00820    /* compute the container size */
00821 
00822    if (!c) {
00823       return NULL;
00824    }
00825 
00826    c->version = 1;   /* 0 is a reserved value here */
00827    c->n_buckets = hash_fn ? n_buckets : 1;
00828    c->hash_fn = hash_fn ? hash_fn : hash_zero;
00829    c->cmp_fn = cmp_fn;
00830 
00831 #ifdef AO2_DEBUG
00832    ast_atomic_fetchadd_int(&ao2.total_containers, 1);
00833 #endif
00834 
00835    return c;
00836 }
00837 
00838 struct ao2_container *__ao2_container_alloc_debug(unsigned int options,
00839    unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn,
00840    const char *tag, const char *file, int line, const char *func, int ref_debug)
00841 {
00842    /* XXX maybe consistency check on arguments ? */
00843    /* compute the container size */
00844    unsigned int num_buckets = hash_fn ? n_buckets : 1;
00845    size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
00846    struct ao2_container *c = __ao2_alloc_debug(container_size, ref_debug ? container_destruct_debug : container_destruct, options, tag, file, line, func, ref_debug);
00847 
00848    return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
00849 }
00850 
00851 struct ao2_container *__ao2_container_alloc(unsigned int options,
00852    unsigned int n_buckets, ao2_hash_fn *hash_fn, ao2_callback_fn *cmp_fn)
00853 {
00854    /* XXX maybe consistency check on arguments ? */
00855    /* compute the container size */
00856    const unsigned int num_buckets = hash_fn ? n_buckets : 1;
00857    size_t container_size = sizeof(struct ao2_container) + num_buckets * sizeof(struct bucket);
00858    struct ao2_container *c = __ao2_alloc(container_size, container_destruct, options);
00859 
00860    return internal_ao2_container_alloc(c, num_buckets, hash_fn, cmp_fn);
00861 }
00862 
00863 /*!
00864  * return the number of elements in the container
00865  */
00866 int ao2_container_count(struct ao2_container *c)
00867 {
00868    return c->elements;
00869 }
00870 
00871 /*
00872  * link an object to a container
00873  */
00874 static struct bucket_entry *internal_ao2_link(struct ao2_container *c, void *user_data, int flags, const char *tag, const char *file, int line, const char *func)
00875 {
00876    int i;
00877    enum ao2_lock_req orig_lock;
00878    /* create a new list entry */
00879    struct bucket_entry *p;
00880    struct astobj2 *obj = INTERNAL_OBJ(user_data);
00881 
00882    if (obj == NULL) {
00883       return NULL;
00884    }
00885 
00886    if (INTERNAL_OBJ(c) == NULL) {
00887       return NULL;
00888    }
00889 
00890    p = ast_calloc(1, sizeof(*p));
00891    if (!p) {
00892       return NULL;
00893    }
00894 
00895    i = abs(c->hash_fn(user_data, OBJ_POINTER));
00896 
00897    if (flags & OBJ_NOLOCK) {
00898       orig_lock = adjust_lock(c, AO2_LOCK_REQ_WRLOCK, 1);
00899    } else {
00900       ao2_wrlock(c);
00901       orig_lock = AO2_LOCK_REQ_MUTEX;
00902    }
00903 
00904    i %= c->n_buckets;
00905    p->astobj = obj;
00906    p->version = ast_atomic_fetchadd_int(&c->version, 1);
00907    AST_LIST_INSERT_TAIL(&c->buckets[i], p, entry);
00908    ast_atomic_fetchadd_int(&c->elements, 1);
00909 
00910    if (tag) {
00911       __ao2_ref_debug(user_data, +1, tag, file, line, func);
00912    } else {
00913       __ao2_ref(user_data, +1);
00914    }
00915 
00916    if (flags & OBJ_NOLOCK) {
00917       adjust_lock(c, orig_lock, 0);
00918    } else {
00919       ao2_unlock(c);
00920    }
00921 
00922    return p;
00923 }
00924 
00925 void *__ao2_link_debug(struct ao2_container *c, void *obj_new, int flags, const char *tag, const char *file, int line, const char *func)
00926 {
00927    return internal_ao2_link(c, obj_new, flags, tag, file, line, func);
00928 }
00929 
00930 void *__ao2_link(struct ao2_container *c, void *obj_new, int flags)
00931 {
00932    return internal_ao2_link(c, obj_new, flags, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
00933 }
00934 
00935 /*!
00936  * \brief another convenience function is a callback that matches on address
00937  */
00938 int ao2_match_by_addr(void *user_data, void *arg, int flags)
00939 {
00940    return (user_data == arg) ? (CMP_MATCH | CMP_STOP) : 0;
00941 }
00942 
00943 /*
00944  * Unlink an object from the container
00945  * and destroy the associated * bucket_entry structure.
00946  */
00947 void *__ao2_unlink_debug(struct ao2_container *c, void *user_data, int flags,
00948    const char *tag, const char *file, int line, const char *func)
00949 {
00950    if (INTERNAL_OBJ(user_data) == NULL) { /* safety check on the argument */
00951       return NULL;
00952    }
00953 
00954    flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
00955    __ao2_callback_debug(c, flags, ao2_match_by_addr, user_data, tag, file, line, func);
00956 
00957    return NULL;
00958 }
00959 
00960 void *__ao2_unlink(struct ao2_container *c, void *user_data, int flags)
00961 {
00962    if (INTERNAL_OBJ(user_data) == NULL) { /* safety check on the argument */
00963       return NULL;
00964    }
00965 
00966    flags |= (OBJ_UNLINK | OBJ_POINTER | OBJ_NODATA);
00967    __ao2_callback(c, flags, ao2_match_by_addr, user_data);
00968 
00969    return NULL;
00970 }
00971 
00972 /*!
00973  * \brief special callback that matches all
00974  */
00975 static int cb_true(void *user_data, void *arg, int flags)
00976 {
00977    return CMP_MATCH;
00978 }
00979 
00980 /*!
00981  * \brief similar to cb_true, but is an ao2_callback_data_fn instead
00982  */
00983 static int cb_true_data(void *user_data, void *arg, void *data, int flags)
00984 {
00985    return CMP_MATCH;
00986 }
00987 
00988 /*!
00989  * Browse the container using different stategies accoding the flags.
00990  * \return Is a pointer to an object or to a list of object if OBJ_MULTIPLE is
00991  * specified.
00992  * Luckily, for debug purposes, the added args (tag, file, line, func)
00993  * aren't an excessive load to the system, as the callback should not be
00994  * called as often as, say, the ao2_ref func is called.
00995  */
00996 static void *internal_ao2_callback(struct ao2_container *c, enum search_flags flags,
00997    void *cb_fn, void *arg, void *data, enum ao2_callback_type type, const char *tag,
00998    const char *file, int line, const char *func)
00999 {
01000    int i, start, last;  /* search boundaries */
01001    enum ao2_lock_req orig_lock;
01002    void *ret = NULL;
01003    ao2_callback_fn *cb_default = NULL;
01004    ao2_callback_data_fn *cb_withdata = NULL;
01005    struct ao2_container *multi_container = NULL;
01006    struct ao2_iterator *multi_iterator = NULL;
01007 
01008    if (INTERNAL_OBJ(c) == NULL) {   /* safety check on the argument */
01009       return NULL;
01010    }
01011 
01012    /*
01013     * This logic is used so we can support OBJ_MULTIPLE with OBJ_NODATA
01014     * turned off.  This if statement checks for the special condition
01015     * where multiple items may need to be returned.
01016     */
01017    if ((flags & (OBJ_MULTIPLE | OBJ_NODATA)) == OBJ_MULTIPLE) {
01018       /* we need to return an ao2_iterator with the results,
01019        * as there could be more than one. the iterator will
01020        * hold the only reference to a container that has all the
01021        * matching objects linked into it, so when the iterator
01022        * is destroyed, the container will be automatically
01023        * destroyed as well.
01024        */
01025       multi_container = __ao2_container_alloc(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL);
01026       if (!multi_container) {
01027          return NULL;
01028       }
01029       if (!(multi_iterator = ast_calloc(1, sizeof(*multi_iterator)))) {
01030          ao2_ref(multi_container, -1);
01031          return NULL;
01032       }
01033    }
01034 
01035    /* override the match function if necessary */
01036    if (cb_fn == NULL) { /* if NULL, match everything */
01037       if (type == WITH_DATA) {
01038          cb_withdata = cb_true_data;
01039       } else {
01040          cb_default = cb_true;
01041       }
01042    } else {
01043       /* We do this here to avoid the per object casting penalty (even though
01044          that is probably optimized away anyway). */
01045       if (type == WITH_DATA) {
01046          cb_withdata = cb_fn;
01047       } else {
01048          cb_default = cb_fn;
01049       }
01050    }
01051 
01052    /*
01053     * XXX this can be optimized.
01054     * If we have a hash function and lookup by pointer,
01055     * run the hash function. Otherwise, scan the whole container
01056     * (this only for the time being. We need to optimize this.)
01057     */
01058    if ((flags & (OBJ_POINTER | OBJ_KEY))) {
01059       /* we know hash can handle this case */
01060       start = i = c->hash_fn(arg, flags & (OBJ_POINTER | OBJ_KEY)) % c->n_buckets;
01061    } else {
01062       /* don't know, let's scan all buckets */
01063       start = i = -1;      /* XXX this must be fixed later. */
01064    }
01065 
01066    /* determine the search boundaries: i..last-1 */
01067    if (i < 0) {
01068       start = i = 0;
01069       last = c->n_buckets;
01070    } else if ((flags & OBJ_CONTINUE)) {
01071       last = c->n_buckets;
01072    } else {
01073       last = i + 1;
01074    }
01075 
01076    /* avoid modifications to the content */
01077    if (flags & OBJ_NOLOCK) {
01078       if (flags & OBJ_UNLINK) {
01079          orig_lock = adjust_lock(c, AO2_LOCK_REQ_WRLOCK, 1);
01080       } else {
01081          orig_lock = adjust_lock(c, AO2_LOCK_REQ_RDLOCK, 1);
01082       }
01083    } else {
01084       orig_lock = AO2_LOCK_REQ_MUTEX;
01085       if (flags & OBJ_UNLINK) {
01086          ao2_wrlock(c);
01087       } else {
01088          ao2_rdlock(c);
01089       }
01090    }
01091 
01092    for (; i < last ; i++) {
01093       /* scan the list with prev-cur pointers */
01094       struct bucket_entry *cur;
01095 
01096       AST_LIST_TRAVERSE_SAFE_BEGIN(&c->buckets[i], cur, entry) {
01097          int match = (CMP_MATCH | CMP_STOP);
01098 
01099          if (type == WITH_DATA) {
01100             match &= cb_withdata(EXTERNAL_OBJ(cur->astobj), arg, data, flags);
01101          } else {
01102             match &= cb_default(EXTERNAL_OBJ(cur->astobj), arg, flags);
01103          }
01104 
01105          /* we found the object, performing operations according flags */
01106          if (match == 0) { /* no match, no stop, continue */
01107             continue;
01108          } else if (match == CMP_STOP) {  /* no match but stop, we are done */
01109             i = last;
01110             break;
01111          }
01112 
01113          /* we have a match (CMP_MATCH) here */
01114          if (!(flags & OBJ_NODATA)) {  /* if must return the object, record the value */
01115             /* it is important to handle this case before the unlink */
01116             ret = EXTERNAL_OBJ(cur->astobj);
01117             if (!(flags & (OBJ_UNLINK | OBJ_MULTIPLE))) {
01118                if (tag) {
01119                   __ao2_ref_debug(ret, 1, tag, file, line, func);
01120                } else {
01121                   __ao2_ref(ret, 1);
01122                }
01123             }
01124          }
01125 
01126          /* If we are in OBJ_MULTIPLE mode and OBJ_NODATA is off,
01127           * link the object into the container that will hold the results.
01128           */
01129          if (ret && (multi_container != NULL)) {
01130             if (tag) {
01131                __ao2_link_debug(multi_container, ret, flags, tag, file, line, func);
01132             } else {
01133                __ao2_link(multi_container, ret, flags);
01134             }
01135             ret = NULL;
01136          }
01137 
01138          if (flags & OBJ_UNLINK) {  /* must unlink */
01139             /* we are going to modify the container, so update version */
01140             ast_atomic_fetchadd_int(&c->version, 1);
01141             AST_LIST_REMOVE_CURRENT(entry);
01142             /* update number of elements */
01143             ast_atomic_fetchadd_int(&c->elements, -1);
01144 
01145             /* - When unlinking and not returning the result, (OBJ_NODATA), the ref from the container
01146              * must be decremented.
01147              * - When unlinking with OBJ_MULTIPLE the ref from the original container
01148              * must be decremented regardless if OBJ_NODATA is used. This is because the result is
01149              * returned in a new container that already holds its own ref for the object. If the ref
01150              * from the original container is not accounted for here a memory leak occurs. */
01151             if (flags & (OBJ_NODATA | OBJ_MULTIPLE)) {
01152                if (tag)
01153                   __ao2_ref_debug(EXTERNAL_OBJ(cur->astobj), -1, tag, file, line, func);
01154                else
01155                   __ao2_ref(EXTERNAL_OBJ(cur->astobj), -1);
01156             }
01157             ast_free(cur); /* free the link record */
01158          }
01159 
01160          if ((match & CMP_STOP) || !(flags & OBJ_MULTIPLE)) {
01161             /* We found our only (or last) match, so force an exit from
01162                the outside loop. */
01163             i = last;
01164             break;
01165          }
01166       }
01167       AST_LIST_TRAVERSE_SAFE_END;
01168 
01169       if (ret) {
01170          break;
01171       }
01172 
01173       if (i == c->n_buckets - 1 && (flags & OBJ_POINTER) && (flags & OBJ_CONTINUE)) {
01174          /* Move to the beginning to ensure we check every bucket */
01175          i = -1;
01176          last = start;
01177       }
01178    }
01179 
01180    if (flags & OBJ_NOLOCK) {
01181       adjust_lock(c, orig_lock, 0);
01182    } else {
01183       ao2_unlock(c);
01184    }
01185 
01186    /* if multi_container was created, we are returning multiple objects */
01187    if (multi_container != NULL) {
01188       *multi_iterator = ao2_iterator_init(multi_container,
01189          AO2_ITERATOR_UNLINK | AO2_ITERATOR_MALLOCD);
01190       ao2_ref(multi_container, -1);
01191       return multi_iterator;
01192    } else {
01193       return ret;
01194    }
01195 }
01196 
01197 void *__ao2_callback_debug(struct ao2_container *c, enum search_flags flags,
01198    ao2_callback_fn *cb_fn, void *arg, const char *tag, const char *file, int line,
01199    const char *func)
01200 {
01201    return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, tag, file, line, func);
01202 }
01203 
01204 void *__ao2_callback(struct ao2_container *c, enum search_flags flags,
01205    ao2_callback_fn *cb_fn, void *arg)
01206 {
01207    return internal_ao2_callback(c,flags, cb_fn, arg, NULL, DEFAULT, NULL, NULL, 0, NULL);
01208 }
01209 
01210 void *__ao2_callback_data_debug(struct ao2_container *c, enum search_flags flags,
01211    ao2_callback_data_fn *cb_fn, void *arg, void *data, const char *tag, const char *file,
01212    int line, const char *func)
01213 {
01214    return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, tag, file, line, func);
01215 }
01216 
01217 void *__ao2_callback_data(struct ao2_container *c, enum search_flags flags,
01218    ao2_callback_data_fn *cb_fn, void *arg, void *data)
01219 {
01220    return internal_ao2_callback(c, flags, cb_fn, arg, data, WITH_DATA, NULL, NULL, 0, NULL);
01221 }
01222 
01223 /*!
01224  * the find function just invokes the default callback with some reasonable flags.
01225  */
01226 void *__ao2_find_debug(struct ao2_container *c, const void *arg, enum search_flags flags,
01227    const char *tag, const char *file, int line, const char *func)
01228 {
01229    void *arged = (void *) arg;/* Done to avoid compiler const warning */
01230 
01231    return __ao2_callback_debug(c, flags, c->cmp_fn, arged, tag, file, line, func);
01232 }
01233 
01234 void *__ao2_find(struct ao2_container *c, const void *arg, enum search_flags flags)
01235 {
01236    void *arged = (void *) arg;/* Done to avoid compiler const warning */
01237 
01238    return __ao2_callback(c, flags, c->cmp_fn, arged);
01239 }
01240 
01241 /*!
01242  * initialize an iterator so we start from the first object
01243  */
01244 struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
01245 {
01246    struct ao2_iterator a = {
01247       .c = c,
01248       .flags = flags
01249    };
01250 
01251    ao2_ref(c, +1);
01252 
01253    return a;
01254 }
01255 
01256 /*!
01257  * destroy an iterator
01258  */
01259 void ao2_iterator_destroy(struct ao2_iterator *iter)
01260 {
01261    ao2_ref(iter->c, -1);
01262    if (iter->flags & AO2_ITERATOR_MALLOCD) {
01263       ast_free(iter);
01264    } else {
01265       iter->c = NULL;
01266    }
01267 }
01268 
01269 /*
01270  * move to the next element in the container.
01271  */
01272 static void *internal_ao2_iterator_next(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
01273 {
01274    int lim;
01275    enum ao2_lock_req orig_lock;
01276    struct bucket_entry *p = NULL;
01277    void *ret;
01278 
01279    if (INTERNAL_OBJ(iter->c) == NULL) {
01280       return NULL;
01281    }
01282 
01283    if (iter->flags & AO2_ITERATOR_DONTLOCK) {
01284       if (iter->flags & AO2_ITERATOR_UNLINK) {
01285          orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_WRLOCK, 1);
01286       } else {
01287          orig_lock = adjust_lock(iter->c, AO2_LOCK_REQ_RDLOCK, 1);
01288       }
01289    } else {
01290       orig_lock = AO2_LOCK_REQ_MUTEX;
01291       if (iter->flags & AO2_ITERATOR_UNLINK) {
01292          ao2_wrlock(iter->c);
01293       } else {
01294          ao2_rdlock(iter->c);
01295       }
01296    }
01297 
01298    /* optimization. If the container is unchanged and
01299     * we have a pointer, try follow it
01300     */
01301    if (iter->c->version == iter->c_version && (p = iter->obj)) {
01302       if ((p = AST_LIST_NEXT(p, entry))) {
01303          goto found;
01304       }
01305       /* nope, start from the next bucket */
01306       iter->bucket++;
01307       iter->version = 0;
01308       iter->obj = NULL;
01309    }
01310 
01311    lim = iter->c->n_buckets;
01312 
01313    /* Browse the buckets array, moving to the next
01314     * buckets if we don't find the entry in the current one.
01315     * Stop when we find an element with version number greater
01316     * than the current one (we reset the version to 0 when we
01317     * switch buckets).
01318     */
01319    for (; iter->bucket < lim; iter->bucket++, iter->version = 0) {
01320       /* scan the current bucket */
01321       AST_LIST_TRAVERSE(&iter->c->buckets[iter->bucket], p, entry) {
01322          if (p->version > iter->version) {
01323             goto found;
01324          }
01325       }
01326    }
01327 
01328 found:
01329    if (p) {
01330       ret = EXTERNAL_OBJ(p->astobj);
01331       if (iter->flags & AO2_ITERATOR_UNLINK) {
01332          /* we are going to modify the container, so update version */
01333          ast_atomic_fetchadd_int(&iter->c->version, 1);
01334          AST_LIST_REMOVE(&iter->c->buckets[iter->bucket], p, entry);
01335          /* update number of elements */
01336          ast_atomic_fetchadd_int(&iter->c->elements, -1);
01337          iter->version = 0;
01338          iter->obj = NULL;
01339          iter->c_version = iter->c->version;
01340          ast_free(p);
01341       } else {
01342          iter->version = p->version;
01343          iter->obj = p;
01344          iter->c_version = iter->c->version;
01345 
01346          /* inc refcount of returned object */
01347          if (tag) {
01348             __ao2_ref_debug(ret, 1, tag, file, line, func);
01349          } else {
01350             __ao2_ref(ret, 1);
01351          }
01352       }
01353    } else {
01354       ret = NULL;
01355    }
01356 
01357    if (iter->flags & AO2_ITERATOR_DONTLOCK) {
01358       adjust_lock(iter->c, orig_lock, 0);
01359    } else {
01360       ao2_unlock(iter->c);
01361    }
01362 
01363    return ret;
01364 }
01365 
01366 void *__ao2_iterator_next_debug(struct ao2_iterator *iter, const char *tag, const char *file, int line, const char *func)
01367 {
01368    return internal_ao2_iterator_next(iter, tag, file, line, func);
01369 }
01370 
01371 void *__ao2_iterator_next(struct ao2_iterator *iter)
01372 {
01373    return internal_ao2_iterator_next(iter, NULL, __FILE__, __LINE__, __PRETTY_FUNCTION__);
01374 }
01375 
01376 /* callback for destroying container.
01377  * we can make it simple as we know what it does
01378  */
01379 static int cd_cb(void *obj, void *arg, int flag)
01380 {
01381    __ao2_ref(obj, -1);
01382    return 0;
01383 }
01384 
01385 static int cd_cb_debug(void *obj, void *arg, int flag)
01386 {
01387    __ao2_ref_debug(obj, -1, "deref object via container destroy",  __FILE__, __LINE__, __PRETTY_FUNCTION__);
01388    return 0;
01389 }
01390 
01391 static void container_destruct(void *_c)
01392 {
01393    struct ao2_container *c = _c;
01394    int i;
01395 
01396    __ao2_callback(c, OBJ_UNLINK, cd_cb, NULL);
01397 
01398    for (i = 0; i < c->n_buckets; i++) {
01399       struct bucket_entry *current;
01400 
01401       while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
01402          ast_free(current);
01403       }
01404    }
01405 
01406 #ifdef AO2_DEBUG
01407    ast_atomic_fetchadd_int(&ao2.total_containers, -1);
01408 #endif
01409 }
01410 
01411 static void container_destruct_debug(void *_c)
01412 {
01413    struct ao2_container *c = _c;
01414    int i;
01415 
01416    __ao2_callback_debug(c, OBJ_UNLINK, cd_cb_debug, NULL, "container_destruct_debug called", __FILE__, __LINE__, __PRETTY_FUNCTION__);
01417 
01418    for (i = 0; i < c->n_buckets; i++) {
01419       struct bucket_entry *current;
01420 
01421       while ((current = AST_LIST_REMOVE_HEAD(&c->buckets[i], entry))) {
01422          ast_free(current);
01423       }
01424    }
01425 
01426 #ifdef AO2_DEBUG
01427    ast_atomic_fetchadd_int(&ao2.total_containers, -1);
01428 #endif
01429 }
01430 
01431 /*!
01432  * \internal
01433  * \brief Put obj into the arg container.
01434  * \since 11.0
01435  *
01436  * \param obj  pointer to the (user-defined part) of an object.
01437  * \param arg callback argument from ao2_callback()
01438  * \param flags flags from ao2_callback()
01439  *
01440  * \retval 0 on success.
01441  * \retval CMP_STOP|CMP_MATCH on error.
01442  */
01443 static int dup_obj_cb(void *obj, void *arg, int flags)
01444 {
01445    struct ao2_container *dest = arg;
01446 
01447    return __ao2_link(dest, obj, OBJ_NOLOCK) ? 0 : (CMP_MATCH | CMP_STOP);
01448 }
01449 
01450 int ao2_container_dup(struct ao2_container *dest, struct ao2_container *src, enum search_flags flags)
01451 {
01452    void *obj;
01453    int res = 0;
01454 
01455    if (!(flags & OBJ_NOLOCK)) {
01456       ao2_rdlock(src);
01457       ao2_wrlock(dest);
01458    }
01459    obj = __ao2_callback(src, OBJ_NOLOCK, dup_obj_cb, dest);
01460    if (obj) {
01461       /* Failed to put this obj into the dest container. */
01462       __ao2_ref(obj, -1);
01463 
01464       /* Remove all items from the dest container. */
01465       __ao2_callback(dest, OBJ_NOLOCK | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE, NULL,
01466          NULL);
01467       res = -1;
01468    }
01469    if (!(flags & OBJ_NOLOCK)) {
01470       ao2_unlock(dest);
01471       ao2_unlock(src);
01472    }
01473 
01474    return res;
01475 }
01476 
01477 struct ao2_container *__ao2_container_clone(struct ao2_container *orig, enum search_flags flags)
01478 {
01479    struct ao2_container *clone;
01480    struct astobj2 *orig_obj;
01481    unsigned int options;
01482    int failed;
01483 
01484    orig_obj = INTERNAL_OBJ(orig);
01485    if (!orig_obj) {
01486       return NULL;
01487    }
01488    options = orig_obj->priv_data.options;
01489 
01490    /* Create the clone container with the same properties as the original. */
01491    clone = __ao2_container_alloc(options, orig->n_buckets, orig->hash_fn, orig->cmp_fn);
01492    if (!clone) {
01493       return NULL;
01494    }
01495 
01496    if (flags & OBJ_NOLOCK) {
01497       ao2_wrlock(clone);
01498    }
01499    failed = ao2_container_dup(clone, orig, flags);
01500    if (flags & OBJ_NOLOCK) {
01501       ao2_unlock(clone);
01502    }
01503    if (failed) {
01504       /* Object copy into the clone container failed. */
01505       __ao2_ref(clone, -1);
01506       clone = NULL;
01507    }
01508    return clone;
01509 }
01510 
01511 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)
01512 {
01513    struct ao2_container *clone;
01514    struct astobj2 *orig_obj;
01515    unsigned int options;
01516    int failed;
01517 
01518    orig_obj = INTERNAL_OBJ(orig);
01519    if (!orig_obj) {
01520       return NULL;
01521    }
01522    options = orig_obj->priv_data.options;
01523 
01524    /* Create the clone container with the same properties as the original. */
01525    clone = __ao2_container_alloc_debug(options, orig->n_buckets, orig->hash_fn,
01526       orig->cmp_fn, tag, file, line, func, ref_debug);
01527    if (!clone) {
01528       return NULL;
01529    }
01530 
01531    if (flags & OBJ_NOLOCK) {
01532       ao2_wrlock(clone);
01533    }
01534    failed = ao2_container_dup(clone, orig, flags);
01535    if (flags & OBJ_NOLOCK) {
01536       ao2_unlock(clone);
01537    }
01538    if (failed) {
01539       /* Object copy into the clone container failed. */
01540       if (ref_debug) {
01541          __ao2_ref_debug(clone, -1, tag, file, line, func);
01542       } else {
01543          __ao2_ref(clone, -1);
01544       }
01545       clone = NULL;
01546    }
01547    return clone;
01548 }
01549 
01550 void __ao2_cleanup_debug(void *obj, const char *file, int line, const char *function)
01551 {
01552    if (obj) {
01553       __ao2_ref_debug(obj, -1, "ao2_cleanup", file, line, function);
01554    }
01555 }
01556 
01557 void __ao2_cleanup(void *obj)
01558 {
01559    if (obj) {
01560       ao2_ref(obj, -1);
01561    }
01562 }
01563 
01564 void ao2_iterator_cleanup(struct ao2_iterator *iter)
01565 {
01566    if (iter) {
01567       ao2_iterator_destroy(iter);
01568    }
01569 }
01570 
01571 #ifdef AO2_DEBUG
01572 static int print_cb(void *obj, void *arg, int flag)
01573 {
01574    struct ast_cli_args *a = (struct ast_cli_args *) arg;
01575    char *s = (char *)obj;
01576 
01577    ast_cli(a->fd, "string <%s>\n", s);
01578    return 0;
01579 }
01580 
01581 /*
01582  * Print stats
01583  */
01584 static char *handle_astobj2_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01585 {
01586    switch (cmd) {
01587    case CLI_INIT:
01588       e->command = "astobj2 show stats";
01589       e->usage = "Usage: astobj2 show stats\n"
01590             "       Show astobj2 show stats\n";
01591       return NULL;
01592    case CLI_GENERATE:
01593       return NULL;
01594    }
01595    ast_cli(a->fd, "Objects    : %d\n", ao2.total_objects);
01596    ast_cli(a->fd, "Containers : %d\n", ao2.total_containers);
01597    ast_cli(a->fd, "Memory     : %d\n", ao2.total_mem);
01598    ast_cli(a->fd, "Locked     : %d\n", ao2.total_locked);
01599    ast_cli(a->fd, "Refs       : %d\n", ao2.total_refs);
01600    return CLI_SUCCESS;
01601 }
01602 
01603 /*
01604  * This is testing code for astobj
01605  */
01606 static char *handle_astobj2_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01607 {
01608    struct ao2_container *c1;
01609    struct ao2_container *c2;
01610    int i, lim;
01611    char *obj;
01612    static int prof_id = -1;
01613    struct ast_cli_args fake_args = { a->fd, 0, NULL };
01614 
01615    switch (cmd) {
01616    case CLI_INIT:
01617       e->command = "astobj2 test";
01618       e->usage = "Usage: astobj2 test <num>\n"
01619             "       Runs astobj2 test. Creates 'num' objects,\n"
01620             "       and test iterators, callbacks and may be other stuff\n";
01621       return NULL;
01622    case CLI_GENERATE:
01623       return NULL;
01624    }
01625 
01626    if (a->argc != 3) {
01627       return CLI_SHOWUSAGE;
01628    }
01629 
01630    if (prof_id == -1)
01631       prof_id = ast_add_profile("ao2_alloc", 0);
01632 
01633    ast_cli(a->fd, "argc %d argv %s %s %s\n", a->argc, a->argv[0], a->argv[1], a->argv[2]);
01634    lim = atoi(a->argv[2]);
01635    ast_cli(a->fd, "called astobj_test\n");
01636 
01637    handle_astobj2_stats(e, CLI_HANDLER, &fake_args);
01638    /*
01639     * allocate a container with no default callback, and no hash function.
01640     * No hash means everything goes in the same bucket.
01641     */
01642    c1 = ao2_t_container_alloc(100, NULL /* no callback */, NULL /* no hash */,"test");
01643    ast_cli(a->fd, "container allocated as %p\n", c1);
01644 
01645    /*
01646     * fill the container with objects.
01647     * ao2_alloc() gives us a reference which we pass to the
01648     * container when we do the insert.
01649     */
01650    for (i = 0; i < lim; i++) {
01651       ast_mark(prof_id, 1 /* start */);
01652       obj = ao2_t_alloc(80, NULL,"test");
01653       ast_mark(prof_id, 0 /* stop */);
01654       ast_cli(a->fd, "object %d allocated as %p\n", i, obj);
01655       sprintf(obj, "-- this is obj %d --", i);
01656       ao2_link(c1, obj);
01657       /* At this point, the refcount on obj is 2 due to the allocation
01658        * and linking. We can go ahead and reduce the refcount by 1
01659        * right here so that when the container is unreffed later, the
01660        * objects will be freed
01661        */
01662       ao2_t_ref(obj, -1, "test");
01663    }
01664 
01665    ast_cli(a->fd, "testing callbacks\n");
01666    ao2_t_callback(c1, 0, print_cb, a, "test callback");
01667 
01668    ast_cli(a->fd, "testing container cloning\n");
01669    c2 = ao2_container_clone(c1, 0);
01670    if (ao2_container_count(c1) != ao2_container_count(c2)) {
01671       ast_cli(a->fd, "Cloned container does not have the same number of objects!\n");
01672    }
01673    ao2_t_callback(c2, 0, print_cb, a, "test callback");
01674 
01675    ast_cli(a->fd, "testing iterators, remove every second object\n");
01676    {
01677       struct ao2_iterator ai;
01678       int x = 0;
01679 
01680       ai = ao2_iterator_init(c1, 0);
01681       while ( (obj = ao2_t_iterator_next(&ai,"test")) ) {
01682          ast_cli(a->fd, "iterator on <%s>\n", obj);
01683          if (x++ & 1)
01684             ao2_t_unlink(c1, obj,"test");
01685          ao2_t_ref(obj, -1,"test");
01686       }
01687       ao2_iterator_destroy(&ai);
01688       ast_cli(a->fd, "testing iterators again\n");
01689       ai = ao2_iterator_init(c1, 0);
01690       while ( (obj = ao2_t_iterator_next(&ai,"test")) ) {
01691          ast_cli(a->fd, "iterator on <%s>\n", obj);
01692          ao2_t_ref(obj, -1,"test");
01693       }
01694       ao2_iterator_destroy(&ai);
01695    }
01696 
01697    ast_cli(a->fd, "testing callbacks again\n");
01698    ao2_t_callback(c1, 0, print_cb, a, "test callback");
01699 
01700    ast_verbose("now you should see an error message:\n");
01701    ao2_t_ref(&i, -1, "");  /* i is not a valid object so we print an error here */
01702 
01703    ast_cli(a->fd, "destroy container\n");
01704    ao2_t_ref(c1, -1, "");  /* destroy container */
01705    ao2_t_ref(c2, -1, "");  /* destroy container */
01706    handle_astobj2_stats(e, CLI_HANDLER, &fake_args);
01707    return CLI_SUCCESS;
01708 }
01709 
01710 static struct ast_cli_entry cli_astobj2[] = {
01711    AST_CLI_DEFINE(handle_astobj2_stats, "Print astobj2 statistics"),
01712    AST_CLI_DEFINE(handle_astobj2_test, "Test astobj2"),
01713 };
01714 
01715 static void astobj2_cleanup(void)
01716 {
01717    ast_cli_unregister_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
01718 }
01719 #endif /* AO2_DEBUG */
01720 
01721 int astobj2_init(void)
01722 {
01723 #ifdef AO2_DEBUG
01724    ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
01725    ast_register_atexit(astobj2_cleanup);
01726 #endif
01727 
01728    return 0;
01729 }