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