Changeset 5708

Add support for tracing object lifecycles

Comitted by:  mjagdis
Date:  Jun 04 2010 * 23:10 (about 1 year ago)

Affected files:

callweaver/trunk/include/callweaver/object.h (unified diff)

r5562r5708
3030 #include "callweaver/module.h"
3131
3232
33 /* If you need to trace the lifecycle of a reference counted object
34 * define OBJECT_TRACING below and the initialization of the object
35 * to be traced to used cw_object_init[_obj]_traced(...) instead of
36 * cw_object_init[_obj](...).
37 * Do NOT attempt to use this the trace manager messages as the trace
38 * is logged and the creates manager messages which would then be
39 * traced so generating recursive, traced log messages ad inifinitum.
40 */
41 #undef OBJECT_TRACING
42
43
44 #ifdef OBJECT_TRACING
45 # define OBJECT_TRACING_FIELD int trace;
46 # define OBJECT_TRACING_PARAMS const char *file, int line, const char *function,
47 # define OBJECT_TRACING_ARGS __FILE__, __LINE__, __PRETTY_FUNCTION__,
48 # define OBJECT_TRACING_PRINT(fmt, ...) if (obj->trace) cw_log(__CW_LOG_DEBUG, file, line, function, (fmt), ## __VA_ARGS__)
49 # define cw_object_init_obj(obj, module, refs) do { \
50 struct cw_object *__obj = (obj); \
51 __obj->trace = 0; \
52 cw_object_init_obj_internal(OBJECT_TRACING_ARGS __obj, (module), (refs)); \
53 } while (0)
54 # define cw_object_init_obj_traced(obj, module, refs) do { \
55 struct cw_object *__obj = (obj); \
56 __obj->trace = 1; \
57 cw_object_init_obj_internal(OBJECT_TRACING_ARGS __obj, (module), (refs)); \
58 } while (0)
59 # define cw_object_get_obj(obj) cw_object_get_obj_internal(OBJECT_TRACING_ARGS (obj))
60 # define cw_object_dup_obj(obj) cw_object_dup_obj_internal(OBJECT_TRACING_ARGS (obj))
61 # define cw_object_put_obj(obj) cw_object_put_obj_internal(OBJECT_TRACING_ARGS (obj))
62 #else
63 # define OBJECT_TRACING_FIELD
64 # define OBJECT_TRACING_PARAMS
65 # define OBJECT_TRACING_ARGS
66 # define OBJECT_TRACING_PRINT(fmt, ...)
67 # define cw_object_init_obj(obj, module, refs) \
68 cw_object_init_obj_internal((obj), (module), (refs))
69 # define cw_object_init_obj_traced(obj, module, refs) \
70 cw_object_init_obj_internal((obj), (module), (refs))
71 # define cw_object_get_obj(obj) cw_object_get_obj_internal((obj))
72 # define cw_object_dup_obj(obj) cw_object_dup_obj_internal((obj))
73 # define cw_object_put_obj(obj) cw_object_put_obj_internal((obj))
74 #endif
75
76
3377 struct cw_object;
3478 struct cw_registry_entry;
3579
------
3983
4084 struct cw_object {
4185 atomic_t refs;
86 OBJECT_TRACING_FIELD
4287 struct cw_module *module;
4388 void (*release)(struct cw_object *);
4489 };
------
56101 #define CW_OBJECT_CURRENT_MODULE (get_modinfo()->self)
57102
58103
59 static inline void cw_object_init_obj(struct cw_object *obj, struct cw_module *module, int refs);
60 static inline struct cw_object *cw_object_get_obj(struct cw_object *obj);
61 static inline struct cw_object *cw_object_dup_obj(struct cw_object *obj);
62 static inline int cw_object_put_obj(struct cw_object *obj);
104 static inline void cw_object_init_obj_internal(OBJECT_TRACING_PARAMS struct cw_object *obj, struct cw_module *module, int refs);
105 static inline struct cw_object *cw_object_get_obj_internal(OBJECT_TRACING_PARAMS struct cw_object *obj);
106 static inline struct cw_object *cw_object_dup_obj_internal(OBJECT_TRACING_PARAMS struct cw_object *obj);
107 static inline int cw_object_put_obj_internal(OBJECT_TRACING_PARAMS struct cw_object *obj);
63108 static inline int cw_object_refs_obj(struct cw_object *obj);
64109
65110
------
76121 * was allowed for in the value of refs passed as the third argument
77122 */
78123 #define cw_object_init(ptr, mod, refs) ({ \
79 const typeof(ptr) __ptr = (ptr); \
124 typeof(ptr) __ptr = (ptr); \
80125 if (__ptr) \
81126 cw_object_init_obj(&__ptr->obj, (mod), (refs)); \
82127 __ptr; \
83128 })
129 #ifdef OBJECT_TRACING
130 # define cw_object_init_traced(ptr, mod, refs) ({ \
131 typeof(ptr) __ptr = (ptr); \
132 if (__ptr) \
133 cw_object_init_obj_traced(&__ptr->obj, (mod), (refs)); \
134 __ptr; \
135 })
136 #else
137 # define cw_object_init_traced(ptr, mod, refs) cw_object_init((ptr), (mod), (refs))
138 #endif
84139
85140
86141 /*! \brief Destroy the object data for a reference counted struct
------
109164 * \return a pointer to the ref counted struct
110165 */
111166 #define cw_object_get(ptr) ({ \
112 const typeof(ptr) __ptr = (ptr); \
167 typeof(ptr) __ptr = (ptr); \
113168 if (__ptr) \
114169 cw_object_get_obj(&__ptr->obj); \
115170 __ptr; \
------
128183 * \return a pointer to the ref counted struct
129184 */
130185 #define cw_object_dup(ptr) ({ \
131 const typeof(ptr) __ptr = (ptr); \
186 typeof(ptr) __ptr = (ptr); \
132187 if (__ptr) \
133188 cw_object_dup_obj(&__ptr->obj); \
134189 __ptr; \
------
147202 * \return 1 if the reference counter became zero, 0 otherwise
148203 */
149204 #define cw_object_put(ptr) ({ \
150 const typeof(ptr) __ptr = (ptr); \
205 typeof(ptr) __ptr = (ptr); \
151206 int __r = 0; \
152207 if (__ptr) \
153208 __r = cw_object_put_obj(&__ptr->obj); \
------
166221 *
167222 * \return nothing
168223 */
169 static inline void cw_object_init_obj(struct cw_object *obj, struct cw_module *module, int refs)
224 static inline void cw_object_init_obj_internal(OBJECT_TRACING_PARAMS struct cw_object *obj, struct cw_module *module, int refs)
170225 {
171226 obj->module = module;
172227
------
174229 cw_object_get(module);
175230
176231 atomic_set(&obj->refs, refs);
232
233 OBJECT_TRACING_PRINT("object 0x%p init refs=%d\n", obj, refs);
177234 }
178235
179236
------
195252 *
196253 * \return the given object with the reference counter incremented
197254 */
198 static inline struct cw_object *cw_object_get_obj(struct cw_object *obj)
255 static inline struct cw_object *cw_object_get_obj_internal(OBJECT_TRACING_PARAMS struct cw_object *obj)
199256 {
200 if (atomic_fetch_and_add(&obj->refs, 1) == 0)
257 int prev;
258
259 prev = atomic_fetch_and_add(&obj->refs, 1);
260
261 OBJECT_TRACING_PRINT("object 0x%p get refs=%d\n", obj, prev + 1);
262
263 if (prev == 0)
201264 cw_object_get(obj->module);
202265
203266 return obj;
------
212275 *
213276 * \return a new counted reference to the same object as the given reference
214277 */
215 static inline struct cw_object *cw_object_dup_obj(struct cw_object *obj)
278 static inline struct cw_object *cw_object_dup_obj_internal(OBJECT_TRACING_PARAMS struct cw_object *obj)
216279 {
217 atomic_inc(&obj->refs);
280 int prev;
281
282 prev = atomic_fetch_and_add(&obj->refs, 1);
283
284 OBJECT_TRACING_PRINT("object 0x%p dup refs=%d\n", obj, prev + 1);
285
286 /* If object tracing is not enabled prev will be set but not used */
287 CW_UNUSED(prev);
288
218289 return obj;
219290 }
220291
------
231302 *
232303 * \return 1 if the reference counter became zero, 0 otherwise
233304 */
234 static inline int cw_object_put_obj(struct cw_object *obj)
305 static inline int cw_object_put_obj_internal(OBJECT_TRACING_PARAMS struct cw_object *obj)
235306 {
236 if (atomic_fetch_and_sub(&obj->refs, 1) == 0 + 1) {
307 int prev;
308
309 prev = atomic_fetch_and_sub(&obj->refs, 1);
310
311 if (prev == 0 + 1) {
237312 struct cw_module *module = obj->module;
313
314 OBJECT_TRACING_PRINT("object 0x%p released\n", obj);
315
238316 if (obj->release)
239317 obj->release(obj);
240318 cw_object_put(module);
241319 return 1;
242320 }
321
322 OBJECT_TRACING_PRINT("object 0x%p put refs=%d\n", obj, prev - 1);
243323 return 0;
244324 }
245325