astobj2: Add backtrace to log_bad_ao2.
[asterisk/asterisk.git] / main / astobj2.c
1 /*
2  * astobj2 - replacement containers for asterisk data structures.
3  *
4  * Copyright (C) 2006 Marta Carbone, Luigi Rizzo - Univ. di Pisa, Italy
5  *
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.
11  *
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.
15  */
16
17 /*! \file
18  *
19  * \brief Functions implementing astobj2 objects.
20  *
21  * \author Richard Mudgett <rmudgett@digium.com>
22  */
23
24 /*** MODULEINFO
25         <support_level>core</support_level>
26  ***/
27
28 #include "asterisk.h"
29
30 ASTERISK_REGISTER_FILE()
31
32 #include "asterisk/_private.h"
33 #include "asterisk/astobj2.h"
34 #include "astobj2_private.h"
35 #include "astobj2_container_private.h"
36 #include "asterisk/cli.h"
37 #include "asterisk/paths.h"
38
39 /* Use ast_log_safe in place of ast_log. */
40 #define ast_log ast_log_safe
41
42 static FILE *ref_log;
43
44 /*!
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.
51  */
52 struct __priv_data {
53         int ref_counter;
54         ao2_destructor_fn destructor_fn;
55         /*! This field is used for astobj2 and ao2_weakproxy objects to reference each other */
56         void *weakptr;
57         /*! User data size for stats */
58         size_t data_size;
59         /*! The ao2 object option flags */
60         uint32_t options;
61         /*! magic number.  This is used to verify that a pointer passed in is a
62          *  valid astobj2 or ao2_weak reference */
63         uint32_t magic;
64 };
65
66 #define AO2_MAGIC       0xa570b123
67 #define AO2_WEAK        0xa570b122
68 #define IS_AO2_MAGIC_BAD(p) (AO2_MAGIC != (p->priv_data.magic | 1))
69
70 /*!
71  * What an astobj2 object looks like: fixed-size private data
72  * followed by variable-size user data.
73  */
74 struct astobj2 {
75         struct __priv_data priv_data;
76         void *user_data[0];
77 };
78
79 struct ao2_weakproxy_notification {
80         ao2_weakproxy_notification_cb cb;
81         void *data;
82         AST_LIST_ENTRY(ao2_weakproxy_notification) list;
83 };
84
85 static void weakproxy_run_callbacks(struct ao2_weakproxy *weakproxy);
86
87 struct ao2_lock_priv {
88         ast_mutex_t lock;
89 };
90
91 /* AstObj2 with recursive lock. */
92 struct astobj2_lock {
93         struct ao2_lock_priv mutex;
94         struct __priv_data priv_data;
95         void *user_data[0];
96 };
97
98 struct ao2_rwlock_priv {
99         ast_rwlock_t lock;
100         /*! Count of the number of threads holding a lock on this object. -1 if it is the write lock. */
101         int num_lockers;
102 };
103
104 /* AstObj2 with RW lock. */
105 struct astobj2_rwlock {
106         struct ao2_rwlock_priv rwlock;
107         struct __priv_data priv_data;
108         void *user_data[0];
109 };
110
111 struct ao2_lockobj_priv {
112         void *lock;
113 };
114
115 /* AstObj2 with locking provided by a separate object. */
116 struct astobj2_lockobj {
117         struct ao2_lockobj_priv lockobj;
118         struct __priv_data priv_data;
119         void *user_data[0];
120 };
121
122 #ifdef AO2_DEBUG
123 struct ao2_stats ao2;
124 #endif
125
126 #define INTERNAL_OBJ_MUTEX(user_data) \
127         ((struct astobj2_lock *) (((char *) (user_data)) - sizeof(struct astobj2_lock)))
128
129 #define INTERNAL_OBJ_RWLOCK(user_data) \
130         ((struct astobj2_rwlock *) (((char *) (user_data)) - sizeof(struct astobj2_rwlock)))
131
132 #define INTERNAL_OBJ_LOCKOBJ(user_data) \
133         ((struct astobj2_lockobj *) (((char *) (user_data)) - sizeof(struct astobj2_lockobj)))
134
135 #define INTERNAL_OBJ(user_data) \
136         (struct astobj2 *) ((char *) user_data - sizeof(struct astobj2))
137
138 /*!
139  * \brief convert from a pointer _p to a user-defined object
140  *
141  * \return the pointer to the astobj2 structure
142  */
143 #define __INTERNAL_OBJ_CHECK(user_data, file, line, func) \
144         ({ \
145                 struct astobj2 *p ## __LINE__; \
146                 if (!user_data \
147                         || !(p ## __LINE__ = INTERNAL_OBJ(user_data)) \
148                         || IS_AO2_MAGIC_BAD(p ## __LINE__)) { \
149                         log_bad_ao2(user_data, file, line, func); \
150                         p ## __LINE__ = NULL; \
151                 } \
152                 (p ## __LINE__); \
153         })
154
155 #define INTERNAL_OBJ_CHECK(user_data) \
156         __INTERNAL_OBJ_CHECK(user_data, __FILE__, __LINE__, __PRETTY_FUNCTION__)
157
158 /*!
159  * \brief convert from a pointer _p to an astobj2 object
160  *
161  * \return the pointer to the user-defined portion.
162  */
163 #define EXTERNAL_OBJ(_p)        ((_p) == NULL ? NULL : (_p)->user_data)
164
165 int internal_is_ao2_object(void *user_data)
166 {
167         struct astobj2 *p;
168
169         if (!user_data) {
170                 return 0;
171         }
172
173         p = INTERNAL_OBJ(user_data);
174
175         return !p || IS_AO2_MAGIC_BAD(p) ? 0 : 1;
176 }
177
178 void log_bad_ao2(void *user_data, const char *file, int line, const char *func)
179 {
180         struct astobj2 *p;
181         char bad_magic[100];
182
183         if (!user_data) {
184                 __ast_assert_failed(0, "user_data is NULL", file, line, func);
185                 return;
186         }
187
188         p = INTERNAL_OBJ(user_data);
189         snprintf(bad_magic, sizeof(bad_magic), "bad magic number 0x%x for object %p",
190                 p->priv_data.magic, user_data);
191         __ast_assert_failed(0, bad_magic, file, line, func);
192 }
193
194 int __ao2_lock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
195 {
196         struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
197         struct astobj2_lock *obj_mutex;
198         struct astobj2_rwlock *obj_rwlock;
199         struct astobj2_lockobj *obj_lockobj;
200         int res = 0;
201
202         if (obj == NULL) {
203                 return -1;
204         }
205
206         switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
207         case AO2_ALLOC_OPT_LOCK_MUTEX:
208                 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
209                 res = __ast_pthread_mutex_lock(file, line, func, var, &obj_mutex->mutex.lock);
210 #ifdef AO2_DEBUG
211                 if (!res) {
212                         ast_atomic_fetchadd_int(&ao2.total_locked, 1);
213                 }
214 #endif
215                 break;
216         case AO2_ALLOC_OPT_LOCK_RWLOCK:
217                 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
218                 switch (lock_how) {
219                 case AO2_LOCK_REQ_MUTEX:
220                 case AO2_LOCK_REQ_WRLOCK:
221                         res = __ast_rwlock_wrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
222                         if (!res) {
223                                 ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
224 #ifdef AO2_DEBUG
225                                 ast_atomic_fetchadd_int(&ao2.total_locked, 1);
226 #endif
227                         }
228                         break;
229                 case AO2_LOCK_REQ_RDLOCK:
230                         res = __ast_rwlock_rdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
231                         if (!res) {
232                                 ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
233 #ifdef AO2_DEBUG
234                                 ast_atomic_fetchadd_int(&ao2.total_locked, 1);
235 #endif
236                         }
237                         break;
238                 }
239                 break;
240         case AO2_ALLOC_OPT_LOCK_NOLOCK:
241                 /* The ao2 object has no lock. */
242                 break;
243         case AO2_ALLOC_OPT_LOCK_OBJ:
244                 obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
245                 res = __ao2_lock(obj_lockobj->lockobj.lock, lock_how, file, func, line, var);
246                 break;
247         default:
248                 ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
249                         user_data);
250                 return -1;
251         }
252
253         return res;
254 }
255
256 int __ao2_unlock(void *user_data, const char *file, const char *func, int line, const char *var)
257 {
258         struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
259         struct astobj2_lock *obj_mutex;
260         struct astobj2_rwlock *obj_rwlock;
261         struct astobj2_lockobj *obj_lockobj;
262         int res = 0;
263         int current_value;
264
265         if (obj == NULL) {
266                 return -1;
267         }
268
269         switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
270         case AO2_ALLOC_OPT_LOCK_MUTEX:
271                 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
272                 res = __ast_pthread_mutex_unlock(file, line, func, var, &obj_mutex->mutex.lock);
273 #ifdef AO2_DEBUG
274                 if (!res) {
275                         ast_atomic_fetchadd_int(&ao2.total_locked, -1);
276                 }
277 #endif
278                 break;
279         case AO2_ALLOC_OPT_LOCK_RWLOCK:
280                 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
281
282                 current_value = ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1) - 1;
283                 if (current_value < 0) {
284                         /* It was a WRLOCK that we are unlocking.  Fix the count. */
285                         ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -current_value);
286                 }
287                 res = __ast_rwlock_unlock(file, line, func, &obj_rwlock->rwlock.lock, var);
288 #ifdef AO2_DEBUG
289                 if (!res) {
290                         ast_atomic_fetchadd_int(&ao2.total_locked, -1);
291                 }
292 #endif
293                 break;
294         case AO2_ALLOC_OPT_LOCK_NOLOCK:
295                 /* The ao2 object has no lock. */
296                 break;
297         case AO2_ALLOC_OPT_LOCK_OBJ:
298                 obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
299                 res = __ao2_unlock(obj_lockobj->lockobj.lock, file, func, line, var);
300                 break;
301         default:
302                 ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
303                         user_data);
304                 res = -1;
305                 break;
306         }
307         return res;
308 }
309
310 int __ao2_trylock(void *user_data, enum ao2_lock_req lock_how, const char *file, const char *func, int line, const char *var)
311 {
312         struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
313         struct astobj2_lock *obj_mutex;
314         struct astobj2_rwlock *obj_rwlock;
315         struct astobj2_lockobj *obj_lockobj;
316         int res = 0;
317
318         if (obj == NULL) {
319                 return -1;
320         }
321
322         switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
323         case AO2_ALLOC_OPT_LOCK_MUTEX:
324                 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
325                 res = __ast_pthread_mutex_trylock(file, line, func, var, &obj_mutex->mutex.lock);
326 #ifdef AO2_DEBUG
327                 if (!res) {
328                         ast_atomic_fetchadd_int(&ao2.total_locked, 1);
329                 }
330 #endif
331                 break;
332         case AO2_ALLOC_OPT_LOCK_RWLOCK:
333                 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
334                 switch (lock_how) {
335                 case AO2_LOCK_REQ_MUTEX:
336                 case AO2_LOCK_REQ_WRLOCK:
337                         res = __ast_rwlock_trywrlock(file, line, func, &obj_rwlock->rwlock.lock, var);
338                         if (!res) {
339                                 ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, -1);
340 #ifdef AO2_DEBUG
341                                 ast_atomic_fetchadd_int(&ao2.total_locked, 1);
342 #endif
343                         }
344                         break;
345                 case AO2_LOCK_REQ_RDLOCK:
346                         res = __ast_rwlock_tryrdlock(file, line, func, &obj_rwlock->rwlock.lock, var);
347                         if (!res) {
348                                 ast_atomic_fetchadd_int(&obj_rwlock->rwlock.num_lockers, +1);
349 #ifdef AO2_DEBUG
350                                 ast_atomic_fetchadd_int(&ao2.total_locked, 1);
351 #endif
352                         }
353                         break;
354                 }
355                 break;
356         case AO2_ALLOC_OPT_LOCK_NOLOCK:
357                 /* The ao2 object has no lock. */
358                 return 0;
359         case AO2_ALLOC_OPT_LOCK_OBJ:
360                 obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
361                 res = __ao2_trylock(obj_lockobj->lockobj.lock, lock_how, file, func, line, var);
362                 break;
363         default:
364                 ast_log(__LOG_ERROR, file, line, func, "Invalid lock option on ao2 object %p\n",
365                         user_data);
366                 return -1;
367         }
368
369
370         return res;
371 }
372
373 /*!
374  * \internal
375  * \brief Adjust an object's lock to the requested level.
376  *
377  * \param user_data An ao2 object to adjust lock level.
378  * \param lock_how What level to adjust lock.
379  * \param keep_stronger TRUE if keep original lock level if it is stronger.
380  *
381  * \pre The ao2 object is already locked.
382  *
383  * \details
384  * An ao2 object with a RWLOCK will have its lock level adjusted
385  * to the specified level if it is not already there.  An ao2
386  * object with a different type of lock is not affected.
387  *
388  * \return Original lock level.
389  */
390 enum ao2_lock_req __adjust_lock(void *user_data, enum ao2_lock_req lock_how, int keep_stronger)
391 {
392         struct astobj2 *obj = INTERNAL_OBJ(user_data);
393         struct astobj2_rwlock *obj_rwlock;
394         struct astobj2_lockobj *obj_lockobj;
395         enum ao2_lock_req orig_lock;
396
397         switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
398         case AO2_ALLOC_OPT_LOCK_RWLOCK:
399                 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
400                 if (obj_rwlock->rwlock.num_lockers < 0) {
401                         orig_lock = AO2_LOCK_REQ_WRLOCK;
402                 } else {
403                         orig_lock = AO2_LOCK_REQ_RDLOCK;
404                 }
405                 switch (lock_how) {
406                 case AO2_LOCK_REQ_MUTEX:
407                         lock_how = AO2_LOCK_REQ_WRLOCK;
408                         /* Fall through */
409                 case AO2_LOCK_REQ_WRLOCK:
410                         if (lock_how != orig_lock) {
411                                 /* Switch from read lock to write lock. */
412                                 ao2_unlock(user_data);
413                                 ao2_wrlock(user_data);
414                         }
415                         break;
416                 case AO2_LOCK_REQ_RDLOCK:
417                         if (!keep_stronger && lock_how != orig_lock) {
418                                 /* Switch from write lock to read lock. */
419                                 ao2_unlock(user_data);
420                                 ao2_rdlock(user_data);
421                         }
422                         break;
423                 }
424                 break;
425         case AO2_ALLOC_OPT_LOCK_OBJ:
426                 obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
427                 orig_lock = __adjust_lock(obj_lockobj->lockobj.lock, lock_how, keep_stronger);
428                 break;
429         default:
430                 ast_log(LOG_ERROR, "Invalid lock option on ao2 object %p\n", user_data);
431                 /* Fall through */
432         case AO2_ALLOC_OPT_LOCK_NOLOCK:
433         case AO2_ALLOC_OPT_LOCK_MUTEX:
434                 orig_lock = AO2_LOCK_REQ_MUTEX;
435                 break;
436         }
437
438         return orig_lock;
439 }
440
441 void *ao2_object_get_lockaddr(void *user_data)
442 {
443         struct astobj2 *obj;
444         struct astobj2_lock *obj_mutex;
445
446         obj = INTERNAL_OBJ_CHECK(user_data);
447
448         if (obj == NULL) {
449                 return NULL;
450         }
451
452         switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
453         case AO2_ALLOC_OPT_LOCK_MUTEX:
454                 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
455                 return &obj_mutex->mutex.lock;
456         default:
457                 break;
458         }
459
460         return NULL;
461 }
462
463 int __ao2_ref(void *user_data, int delta,
464         const char *tag, const char *file, int line, const char *func)
465 {
466         struct astobj2 *obj = __INTERNAL_OBJ_CHECK(user_data, file, line, func);
467         struct astobj2_lock *obj_mutex;
468         struct astobj2_rwlock *obj_rwlock;
469         struct astobj2_lockobj *obj_lockobj;
470         int current_value;
471         int ret;
472         void *weakproxy = NULL;
473
474         if (obj == NULL) {
475                 if (ref_log && user_data) {
476                         fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
477                                 user_data, delta, ast_get_tid(), file, line, func, tag ?: "");
478                         fflush(ref_log);
479                 }
480                 return -1;
481         }
482
483         /* if delta is 0, just return the refcount */
484         if (delta == 0) {
485                 return obj->priv_data.ref_counter;
486         }
487
488         if (delta < 0 && obj->priv_data.magic == AO2_MAGIC && (weakproxy = obj->priv_data.weakptr)) {
489                 ao2_lock(weakproxy);
490         }
491
492         /* we modify with an atomic operation the reference counter */
493         ret = ast_atomic_fetchadd_int(&obj->priv_data.ref_counter, delta);
494         current_value = ret + delta;
495
496 #ifdef AO2_DEBUG
497         ast_atomic_fetchadd_int(&ao2.total_refs, delta);
498 #endif
499
500         if (weakproxy) {
501                 if (current_value == 1) {
502                         /* The only remaining reference is the one owned by the weak object */
503                         struct astobj2 *internal_weakproxy;
504
505                         internal_weakproxy = INTERNAL_OBJ_CHECK(weakproxy);
506
507                         /* Unlink the obj from the weak proxy */
508                         internal_weakproxy->priv_data.weakptr = NULL;
509                         obj->priv_data.weakptr = NULL;
510
511                         /* Notify the subscribers that weakproxy now points to NULL. */
512                         weakproxy_run_callbacks(weakproxy);
513
514                         /* weak is already unlinked from obj so this won't recurse */
515                         ao2_ref(user_data, -1);
516                 }
517
518                 ao2_unlock(weakproxy);
519
520                 if (current_value == 1) {
521                         ao2_ref(weakproxy, -1);
522                 }
523         }
524
525         if (0 < current_value) {
526                 /* The object still lives. */
527                 if (ref_log && tag) {
528                         fprintf(ref_log, "%p,%s%d,%d,%s,%d,%s,%d,%s\n", user_data,
529                                 (delta < 0 ? "" : "+"), delta, ast_get_tid(),
530                                 file, line, func, ret, tag);
531                         fflush(ref_log);
532                 }
533                 return ret;
534         }
535
536         /* this case must never happen */
537         if (current_value < 0) {
538                 ast_log(__LOG_ERROR, file, line, func,
539                         "Invalid refcount %d on ao2 object %p\n", current_value, user_data);
540                 if (ref_log) {
541                         /* Log to ref_log invalid even if (tag == NULL) */
542                         fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**invalid**,%s\n",
543                                 user_data, delta, ast_get_tid(), file, line, func, tag ?: "");
544                         fflush(ref_log);
545                 }
546                 ast_assert(0);
547                 /* stop here even if assert doesn't DO_CRASH */
548                 return -1;
549         }
550
551         /* last reference, destroy the object */
552         if (obj->priv_data.destructor_fn != NULL) {
553                 obj->priv_data.destructor_fn(user_data);
554         }
555
556 #ifdef AO2_DEBUG
557         ast_atomic_fetchadd_int(&ao2.total_mem, - obj->priv_data.data_size);
558         ast_atomic_fetchadd_int(&ao2.total_objects, -1);
559 #endif
560
561         /* In case someone uses an object after it's been freed */
562         obj->priv_data.magic = 0;
563
564         switch (obj->priv_data.options & AO2_ALLOC_OPT_LOCK_MASK) {
565         case AO2_ALLOC_OPT_LOCK_MUTEX:
566                 obj_mutex = INTERNAL_OBJ_MUTEX(user_data);
567                 ast_mutex_destroy(&obj_mutex->mutex.lock);
568
569                 ast_free(obj_mutex);
570                 break;
571         case AO2_ALLOC_OPT_LOCK_RWLOCK:
572                 obj_rwlock = INTERNAL_OBJ_RWLOCK(user_data);
573                 ast_rwlock_destroy(&obj_rwlock->rwlock.lock);
574
575                 ast_free(obj_rwlock);
576                 break;
577         case AO2_ALLOC_OPT_LOCK_NOLOCK:
578                 ast_free(obj);
579                 break;
580         case AO2_ALLOC_OPT_LOCK_OBJ:
581                 obj_lockobj = INTERNAL_OBJ_LOCKOBJ(user_data);
582                 ao2_t_ref(obj_lockobj->lockobj.lock, -1, "release lockobj");
583
584                 ast_free(obj_lockobj);
585                 break;
586         default:
587                 ast_log(__LOG_ERROR, file, line, func,
588                         "Invalid lock option on ao2 object %p\n", user_data);
589                 break;
590         }
591
592         if (ref_log && tag) {
593                 fprintf(ref_log, "%p,%d,%d,%s,%d,%s,**destructor**,%s\n",
594                         user_data, delta, ast_get_tid(), file, line, func, tag);
595                 fflush(ref_log);
596         }
597
598         return ret;
599 }
600
601 void __ao2_cleanup_debug(void *obj, const char *tag, const char *file, int line, const char *function)
602 {
603         if (obj) {
604                 __ao2_ref(obj, -1, tag, file, line, function);
605         }
606 }
607
608 void __ao2_cleanup(void *obj)
609 {
610         if (obj) {
611                 ao2_ref(obj, -1);
612         }
613 }
614
615 static void *internal_ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options,
616         void *lockobj, const char *tag, const char *file, int line, const char *func)
617 {
618         /* allocation */
619         struct astobj2 *obj;
620         struct astobj2_lock *obj_mutex;
621         struct astobj2_rwlock *obj_rwlock;
622         struct astobj2_lockobj *obj_lockobj;
623
624         switch (options & AO2_ALLOC_OPT_LOCK_MASK) {
625         case AO2_ALLOC_OPT_LOCK_MUTEX:
626                 obj_mutex = __ast_calloc(1, sizeof(*obj_mutex) + data_size, file, line, func);
627                 if (obj_mutex == NULL) {
628                         return NULL;
629                 }
630
631                 ast_mutex_init(&obj_mutex->mutex.lock);
632                 obj = (struct astobj2 *) &obj_mutex->priv_data;
633                 break;
634         case AO2_ALLOC_OPT_LOCK_RWLOCK:
635                 obj_rwlock = __ast_calloc(1, sizeof(*obj_rwlock) + data_size, file, line, func);
636                 if (obj_rwlock == NULL) {
637                         return NULL;
638                 }
639
640                 ast_rwlock_init(&obj_rwlock->rwlock.lock);
641                 obj = (struct astobj2 *) &obj_rwlock->priv_data;
642                 break;
643         case AO2_ALLOC_OPT_LOCK_NOLOCK:
644                 obj = __ast_calloc(1, sizeof(*obj) + data_size, file, line, func);
645                 if (obj == NULL) {
646                         return NULL;
647                 }
648                 break;
649         case AO2_ALLOC_OPT_LOCK_OBJ:
650                 lockobj = ao2_t_bump(lockobj, "set lockobj");
651                 if (!lockobj) {
652                         ast_log(__LOG_ERROR, file, line, func, "AO2_ALLOC_OPT_LOCK_OBJ requires a non-NULL lockobj.\n");
653                         return NULL;
654                 }
655
656                 obj_lockobj = __ast_calloc(1, sizeof(*obj_lockobj) + data_size, file, line, func);
657                 if (obj_lockobj == NULL) {
658                         ao2_t_ref(lockobj, -1, "release lockobj for failed alloc");
659                         return NULL;
660                 }
661
662                 obj_lockobj->lockobj.lock = lockobj;
663                 obj = (struct astobj2 *) &obj_lockobj->priv_data;
664                 break;
665         default:
666                 /* Invalid option value. */
667                 ast_log(__LOG_DEBUG, file, line, func, "Invalid lock option requested\n");
668                 return NULL;
669         }
670
671         /* Initialize common ao2 values. */
672         obj->priv_data.ref_counter = 1;
673         obj->priv_data.destructor_fn = destructor_fn;   /* can be NULL */
674         obj->priv_data.data_size = data_size;
675         obj->priv_data.options = options;
676         obj->priv_data.magic = AO2_MAGIC;
677
678 #ifdef AO2_DEBUG
679         ast_atomic_fetchadd_int(&ao2.total_objects, 1);
680         ast_atomic_fetchadd_int(&ao2.total_mem, data_size);
681         ast_atomic_fetchadd_int(&ao2.total_refs, 1);
682 #endif
683
684         if (ref_log && tag) {
685                 fprintf(ref_log, "%p,+1,%d,%s,%d,%s,**constructor**,%s\n",
686                         EXTERNAL_OBJ(obj), ast_get_tid(), file, line, func, tag);
687                 fflush(ref_log);
688         }
689
690         /* return a pointer to the user data */
691         return EXTERNAL_OBJ(obj);
692 }
693
694 void *__ao2_alloc(size_t data_size, ao2_destructor_fn destructor_fn, unsigned int options,
695         const char *tag, const char *file, int line, const char *func)
696 {
697         return internal_ao2_alloc(data_size, destructor_fn, options, NULL, tag, file, line, func);
698 }
699
700 void *__ao2_alloc_with_lockobj(size_t data_size, ao2_destructor_fn destructor_fn, void *lockobj,
701         const char *tag, const char *file, int line, const char *func)
702 {
703         return internal_ao2_alloc(data_size, destructor_fn, AO2_ALLOC_OPT_LOCK_OBJ, lockobj,
704                 tag, file, line, func);
705 }
706
707 unsigned int ao2_options_get(void *obj)
708 {
709         struct astobj2 *orig_obj;
710
711         orig_obj = INTERNAL_OBJ_CHECK(obj);
712         if (!orig_obj) {
713                 return 0;
714         }
715         return orig_obj->priv_data.options;
716 }
717
718
719 void __ao2_global_obj_release(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name)
720 {
721         if (!holder) {
722                 /* For sanity */
723                 ast_log(LOG_ERROR, "Must be called with a global object!\n");
724                 ast_assert(0);
725                 return;
726         }
727         if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
728                 /* Could not get the write lock. */
729                 ast_assert(0);
730                 return;
731         }
732
733         /* Release the held ao2 object. */
734         if (holder->obj) {
735                 __ao2_ref(holder->obj, -1, tag, file, line, func);
736                 holder->obj = NULL;
737         }
738
739         __ast_rwlock_unlock(file, line, func, &holder->lock, name);
740 }
741
742 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)
743 {
744         void *obj_old;
745
746         if (!holder) {
747                 /* For sanity */
748                 ast_log(LOG_ERROR, "Must be called with a global object!\n");
749                 ast_assert(0);
750                 return NULL;
751         }
752         if (__ast_rwlock_wrlock(file, line, func, &holder->lock, name)) {
753                 /* Could not get the write lock. */
754                 ast_assert(0);
755                 return NULL;
756         }
757
758         if (obj) {
759                 __ao2_ref(obj, +1, tag, file, line, func);
760         }
761         obj_old = holder->obj;
762         holder->obj = obj;
763
764         __ast_rwlock_unlock(file, line, func, &holder->lock, name);
765
766         return obj_old;
767 }
768
769 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)
770 {
771         void *obj_old;
772
773         obj_old = __ao2_global_obj_replace(holder, obj, tag, file, line, func, name);
774         if (obj_old) {
775                 __ao2_ref(obj_old, -1, tag, file, line, func);
776                 return 1;
777         }
778         return 0;
779 }
780
781 void *__ao2_global_obj_ref(struct ao2_global_obj *holder, const char *tag, const char *file, int line, const char *func, const char *name)
782 {
783         void *obj;
784
785         if (!holder) {
786                 /* For sanity */
787                 ast_log(LOG_ERROR, "Must be called with a global object!\n");
788                 ast_assert(0);
789                 return NULL;
790         }
791
792         if (__ast_rwlock_rdlock(file, line, func, &holder->lock, name)) {
793                 /* Could not get the read lock. */
794                 ast_assert(0);
795                 return NULL;
796         }
797
798         obj = holder->obj;
799         if (obj) {
800                 __ao2_ref(obj, +1, tag, file, line, func);
801         }
802
803         __ast_rwlock_unlock(file, line, func, &holder->lock, name);
804
805         return obj;
806 }
807
808
809 static void weakproxy_run_callbacks(struct ao2_weakproxy *weakproxy)
810 {
811         struct ao2_weakproxy_notification *destroyed_cb;
812
813         while ((destroyed_cb = AST_LIST_REMOVE_HEAD(&weakproxy->destroyed_cb, list))) {
814                 destroyed_cb->cb(weakproxy, destroyed_cb->data);
815                 ast_free(destroyed_cb);
816         }
817 }
818
819 void *__ao2_weakproxy_alloc(size_t data_size, ao2_destructor_fn destructor_fn,
820         const char *tag, const char *file, int line, const char *func)
821 {
822         struct ao2_weakproxy *weakproxy;
823
824         if (data_size < sizeof(*weakproxy)) {
825                 ast_assert(0);
826                 ast_log(LOG_ERROR, "Requested data_size smaller than minimum.\n");
827                 return NULL;
828         }
829
830         weakproxy = __ao2_alloc(data_size, destructor_fn, AO2_ALLOC_OPT_LOCK_MUTEX,
831                 tag, file, line, func);
832
833         if (weakproxy) {
834                 struct astobj2 *weakproxy_internal;
835
836                 /* Just created weakproxy, no need to check if it's valid. */
837                 weakproxy_internal = INTERNAL_OBJ(weakproxy);
838                 weakproxy_internal->priv_data.magic = AO2_WEAK;
839         }
840
841         return weakproxy;
842 }
843
844 int __ao2_weakproxy_set_object(void *weakproxy, void *obj, int flags,
845         const char *tag, const char *file, int line, const char *func)
846 {
847         struct astobj2 *weakproxy_internal = __INTERNAL_OBJ_CHECK(weakproxy, file, line, func);
848         struct astobj2 *obj_internal = __INTERNAL_OBJ_CHECK(obj, file, line, func);
849         int ret = -1;
850
851         if (!weakproxy_internal
852                 || weakproxy_internal->priv_data.magic != AO2_WEAK) {
853                 return -1;
854         }
855
856         if (!obj_internal
857                 || obj_internal->priv_data.weakptr
858                 || obj_internal->priv_data.magic != AO2_MAGIC) {
859                 return -1;
860         }
861
862         if (!(flags & OBJ_NOLOCK)) {
863                 ao2_lock(weakproxy);
864         }
865
866         if (!weakproxy_internal->priv_data.weakptr) {
867                 __ao2_ref(obj, +1, tag, file, line, func);
868                 __ao2_ref(weakproxy, +1, tag, file, line, func);
869
870                 weakproxy_internal->priv_data.weakptr = obj;
871                 obj_internal->priv_data.weakptr = weakproxy;
872
873                 ret = 0;
874         }
875
876         if (!(flags & OBJ_NOLOCK)) {
877                 ao2_unlock(weakproxy);
878                 /* It is possible for obj to be accessed now.  It's allowed
879                  * for weakproxy to already be in a container.  Another thread
880                  * could have been waiting for a lock on weakproxy to retreive
881                  * the object.
882                  */
883         }
884
885         return ret;
886 }
887
888 int __ao2_weakproxy_ref_object(void *weakproxy, int delta, int flags,
889         const char *tag, const char *file, int line, const char *func)
890 {
891         struct astobj2 *internal = __INTERNAL_OBJ_CHECK(weakproxy, file, line, func);
892         int ret = -1;
893
894         if (!internal || internal->priv_data.magic != AO2_WEAK) {
895                 /* This method is meant to be run on weakproxy objects! */
896                 return -2;
897         }
898
899         /* We have a weak object, grab lock. */
900         if (!(flags & OBJ_NOLOCK)) {
901                 ao2_lock(weakproxy);
902         }
903
904         if (internal->priv_data.weakptr) {
905                 ret = __ao2_ref(internal->priv_data.weakptr, delta, tag, file, line, func);
906         }
907
908         if (!(flags & OBJ_NOLOCK)) {
909                 ao2_unlock(weakproxy);
910         }
911
912         return ret;
913 }
914
915 void *__ao2_weakproxy_get_object(void *weakproxy, int flags,
916         const char *tag, const char *file, int line, const char *func)
917 {
918         struct astobj2 *internal = __INTERNAL_OBJ_CHECK(weakproxy, file, line, func);
919         void *obj;
920
921         if (!internal || internal->priv_data.magic != AO2_WEAK) {
922                 /* This method is meant to be run on weakproxy objects! */
923                 return NULL;
924         }
925
926         /* We have a weak object, grab reference to object within lock */
927         if (!(flags & OBJ_NOLOCK)) {
928                 ao2_lock(weakproxy);
929         }
930
931         obj = internal->priv_data.weakptr;
932         if (obj) {
933                 __ao2_ref(obj, +1, tag, file, line, func);
934         }
935
936         if (!(flags & OBJ_NOLOCK)) {
937                 ao2_unlock(weakproxy);
938         }
939
940         return obj;
941 }
942
943 void *__ao2_get_weakproxy(void *obj, const char *tag, const char *file, int line, const char *func)
944 {
945         struct astobj2 *obj_internal = __INTERNAL_OBJ_CHECK(obj, file, line, func);
946
947         if (!obj_internal || obj_internal->priv_data.magic != AO2_MAGIC) {
948                 /* This method is meant to be run on normal ao2 objects! */
949                 return NULL;
950         }
951
952         if (!obj_internal->priv_data.weakptr) {
953                 return NULL;
954         }
955
956         __ao2_ref(obj_internal->priv_data.weakptr, +1, tag, file, line, func);
957         return obj_internal->priv_data.weakptr;
958 }
959
960 int ao2_weakproxy_subscribe(void *weakproxy, ao2_weakproxy_notification_cb cb, void *data, int flags)
961 {
962         struct astobj2 *weakproxy_internal = INTERNAL_OBJ_CHECK(weakproxy);
963         int ret = -1;
964
965         if (!weakproxy_internal || weakproxy_internal->priv_data.magic != AO2_WEAK) {
966                 return -1;
967         }
968
969         if (!(flags & OBJ_NOLOCK)) {
970                 ao2_lock(weakproxy);
971         }
972
973         if (weakproxy_internal->priv_data.weakptr) {
974                 struct ao2_weakproxy *weak = weakproxy;
975                 struct ao2_weakproxy_notification *sub = ast_calloc(1, sizeof(*sub));
976
977                 if (sub) {
978                         sub->cb = cb;
979                         sub->data = data;
980                         AST_LIST_INSERT_HEAD(&weak->destroyed_cb, sub, list);
981                         ret = 0;
982                 }
983         } else {
984                 cb(weakproxy, data);
985                 ret = 0;
986         }
987
988         if (!(flags & OBJ_NOLOCK)) {
989                 ao2_unlock(weakproxy);
990         }
991
992         return ret;
993 }
994
995 int ao2_weakproxy_unsubscribe(void *weakproxy, ao2_weakproxy_notification_cb destroyed_cb, void *data, int flags)
996 {
997         struct astobj2 *internal_weakproxy = INTERNAL_OBJ_CHECK(weakproxy);
998         struct ao2_weakproxy *weak;
999         struct ao2_weakproxy_notification *sub;
1000         int ret = 0;
1001
1002         if (!internal_weakproxy || internal_weakproxy->priv_data.magic != AO2_WEAK || !destroyed_cb) {
1003                 return -1;
1004         }
1005
1006         if (!(flags & OBJ_NOLOCK)) {
1007                 ao2_lock(weakproxy);
1008         }
1009
1010         weak = weakproxy;
1011         AST_LIST_TRAVERSE_SAFE_BEGIN(&weak->destroyed_cb, sub, list) {
1012                 if (sub->cb == destroyed_cb && sub->data == data) {
1013                         AST_LIST_REMOVE_CURRENT(list);
1014                         ast_free(sub);
1015                         ret++;
1016                         if (!(flags & OBJ_MULTIPLE)) {
1017                                 break;
1018                         }
1019                 }
1020         }
1021         AST_LIST_TRAVERSE_SAFE_END;
1022
1023         if (!(flags & OBJ_NOLOCK)) {
1024                 ao2_unlock(weakproxy);
1025         }
1026
1027         return ret;
1028 }
1029
1030
1031 #ifdef AO2_DEBUG
1032 static int print_cb(void *obj, void *arg, int flag)
1033 {
1034         struct ast_cli_args *a = (struct ast_cli_args *) arg;
1035         char *s = (char *)obj;
1036
1037         ast_cli(a->fd, "string <%s>\n", s);
1038         return 0;
1039 }
1040
1041 /*
1042  * Print stats
1043  */
1044 static char *handle_astobj2_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1045 {
1046         switch (cmd) {
1047         case CLI_INIT:
1048                 e->command = "astobj2 show stats";
1049                 e->usage = "Usage: astobj2 show stats\n"
1050                            "       Show astobj2 show stats\n";
1051                 return NULL;
1052         case CLI_GENERATE:
1053                 return NULL;
1054         }
1055         ast_cli(a->fd, "Objects    : %d\n", ao2.total_objects);
1056         ast_cli(a->fd, "Containers : %d\n", ao2.total_containers);
1057         ast_cli(a->fd, "Memory     : %d\n", ao2.total_mem);
1058         ast_cli(a->fd, "Locked     : %d\n", ao2.total_locked);
1059         ast_cli(a->fd, "Refs       : %d\n", ao2.total_refs);
1060         return CLI_SUCCESS;
1061 }
1062
1063 /*
1064  * This is testing code for astobj
1065  */
1066 static char *handle_astobj2_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1067 {
1068         struct ao2_container *c1;
1069         struct ao2_container *c2;
1070         int i, lim;
1071         char *obj;
1072         static int prof_id = -1;
1073         struct ast_cli_args fake_args = { a->fd, 0, NULL };
1074
1075         switch (cmd) {
1076         case CLI_INIT:
1077                 e->command = "astobj2 test";
1078                 e->usage = "Usage: astobj2 test <num>\n"
1079                            "       Runs astobj2 test. Creates 'num' objects,\n"
1080                            "       and test iterators, callbacks and maybe other stuff\n";
1081                 return NULL;
1082         case CLI_GENERATE:
1083                 return NULL;
1084         }
1085
1086         if (a->argc != 3) {
1087                 return CLI_SHOWUSAGE;
1088         }
1089
1090         if (prof_id == -1) {
1091                 prof_id = ast_add_profile("ao2_alloc", 0);
1092         }
1093
1094         ast_cli(a->fd, "argc %d argv %s %s %s\n", a->argc, a->argv[0], a->argv[1], a->argv[2]);
1095         lim = atoi(a->argv[2]);
1096         ast_cli(a->fd, "called astobj_test\n");
1097
1098         handle_astobj2_stats(e, CLI_HANDLER, &fake_args);
1099         /*
1100          * Allocate a list container.
1101          */
1102         c1 = ao2_t_container_alloc_list(AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL /* no sort */,
1103                 NULL /* no callback */, "test");
1104         ast_cli(a->fd, "container allocated as %p\n", c1);
1105
1106         /*
1107          * fill the container with objects.
1108          * ao2_alloc() gives us a reference which we pass to the
1109          * container when we do the insert.
1110          */
1111         for (i = 0; i < lim; i++) {
1112                 ast_mark(prof_id, 1 /* start */);
1113                 obj = ao2_t_alloc(80, NULL,"test");
1114                 ast_mark(prof_id, 0 /* stop */);
1115                 ast_cli(a->fd, "object %d allocated as %p\n", i, obj);
1116                 sprintf(obj, "-- this is obj %d --", i);
1117                 ao2_link(c1, obj);
1118                 /* At this point, the refcount on obj is 2 due to the allocation
1119                  * and linking. We can go ahead and reduce the refcount by 1
1120                  * right here so that when the container is unreffed later, the
1121                  * objects will be freed
1122                  */
1123                 ao2_t_ref(obj, -1, "test");
1124         }
1125
1126         ast_cli(a->fd, "testing callbacks\n");
1127         ao2_t_callback(c1, 0, print_cb, a, "test callback");
1128
1129         ast_cli(a->fd, "testing container cloning\n");
1130         c2 = ao2_container_clone(c1, 0);
1131         if (ao2_container_count(c1) != ao2_container_count(c2)) {
1132                 ast_cli(a->fd, "Cloned container does not have the same number of objects!\n");
1133         }
1134         ao2_t_callback(c2, 0, print_cb, a, "test callback");
1135
1136         ast_cli(a->fd, "testing iterators, remove every second object\n");
1137         {
1138                 struct ao2_iterator ai;
1139                 int x = 0;
1140
1141                 ai = ao2_iterator_init(c1, 0);
1142                 while ( (obj = ao2_t_iterator_next(&ai,"test")) ) {
1143                         ast_cli(a->fd, "iterator on <%s>\n", obj);
1144                         if (x++ & 1)
1145                                 ao2_t_unlink(c1, obj,"test");
1146                         ao2_t_ref(obj, -1,"test");
1147                 }
1148                 ao2_iterator_destroy(&ai);
1149                 ast_cli(a->fd, "testing iterators again\n");
1150                 ai = ao2_iterator_init(c1, 0);
1151                 while ( (obj = ao2_t_iterator_next(&ai,"test")) ) {
1152                         ast_cli(a->fd, "iterator on <%s>\n", obj);
1153                         ao2_t_ref(obj, -1,"test");
1154                 }
1155                 ao2_iterator_destroy(&ai);
1156         }
1157
1158         ast_cli(a->fd, "testing callbacks again\n");
1159         ao2_t_callback(c1, 0, print_cb, a, "test callback");
1160
1161         ast_verbose("now you should see an error and possible assertion failure messages:\n");
1162         ao2_t_ref(&i, -1, "");  /* i is not a valid object so we print an error here */
1163
1164         ast_cli(a->fd, "destroy container\n");
1165         ao2_t_ref(c1, -1, "");  /* destroy container */
1166         ao2_t_ref(c2, -1, "");  /* destroy container */
1167         handle_astobj2_stats(e, CLI_HANDLER, &fake_args);
1168         return CLI_SUCCESS;
1169 }
1170 #endif /* AO2_DEBUG */
1171
1172 #if defined(AO2_DEBUG)
1173 static struct ast_cli_entry cli_astobj2[] = {
1174         AST_CLI_DEFINE(handle_astobj2_stats, "Print astobj2 statistics"),
1175         AST_CLI_DEFINE(handle_astobj2_test, "Test astobj2"),
1176 };
1177 #endif /* AO2_DEBUG */
1178
1179 static void astobj2_cleanup(void)
1180 {
1181 #if defined(AO2_DEBUG)
1182         ast_cli_unregister_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
1183 #endif
1184
1185         if (ast_opt_ref_debug) {
1186                 fclose(ref_log);
1187                 ref_log = NULL;
1188         }
1189 }
1190
1191 int astobj2_init(void)
1192 {
1193         char ref_filename[1024];
1194
1195         if (ast_opt_ref_debug) {
1196                 snprintf(ref_filename, sizeof(ref_filename), "%s/refs", ast_config_AST_LOG_DIR);
1197                 ref_log = fopen(ref_filename, "w");
1198                 if (!ref_log) {
1199                         ast_log(LOG_ERROR, "Could not open ref debug log file: %s\n", ref_filename);
1200                 }
1201         }
1202
1203         if (container_init() != 0) {
1204                 fclose(ref_log);
1205                 return -1;
1206         }
1207
1208 #if defined(AO2_DEBUG)
1209         ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2));
1210 #endif  /* defined(AO2_DEBUG) */
1211
1212         ast_register_cleanup(astobj2_cleanup);
1213
1214         return 0;
1215 }