gst/: More docs.
[platform/upstream/gstreamer.git] / gst / gsttrace.c
1 /* GStreamer
2  * Copyright (C) 1999,2000 Erik Walthinsen <omega@cse.ogi.edu>
3  *                    2000 Wim Taymans <wtay@chello.be>
4  *
5  * gsttrace.c: Tracing functions (deprecated)
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /**
24  * SECTION:gsttrace
25  * @short_description: Tracing functionality
26  *
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 #include <stdio.h>
33 #ifdef HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <string.h>
39
40 #include "gst_private.h"
41 #include "gstinfo.h"
42
43 #include "gsttrace.h"
44
45 static
46 #ifdef __inline__
47   __inline__
48 #endif
49     void
50 read_tsc (gint64 * dst)
51 {
52 #ifdef HAVE_RDTSC
53   guint64 tsc;
54   __asm__ __volatile__ ("rdtsc":"=A" (tsc));
55
56   *dst = tsc;
57 #else
58   *dst = 0;
59 #endif
60 }
61
62 void
63 gst_trace_read_tsc (gint64 * dst)
64 {
65   read_tsc (dst);
66 }
67
68 GstTrace *_gst_trace_default = NULL;
69 gint _gst_trace_on = 1;
70
71 GstTrace *
72 gst_trace_new (gchar * filename, gint size)
73 {
74   GstTrace *trace = g_malloc (sizeof (GstTrace));
75
76   g_return_val_if_fail (trace != NULL, NULL);
77   trace->filename = g_strdup (filename);
78   GST_DEBUG ("opening '%s'\n", trace->filename);
79 #ifndef S_IWUSR
80 #define S_IWUSR S_IWRITE
81 #endif
82 #ifndef S_IRUSR
83 #define S_IRUSR S_IREAD
84 #endif
85   trace->fd =
86       open (trace->filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
87   perror ("opening trace file");
88   g_return_val_if_fail (trace->fd > 0, NULL);
89   trace->buf = g_malloc (size * sizeof (GstTraceEntry));
90   g_return_val_if_fail (trace->buf != NULL, NULL);
91   trace->bufsize = size;
92   trace->bufoffset = 0;
93
94   return trace;
95 }
96
97 void
98 gst_trace_destroy (GstTrace * trace)
99 {
100   g_return_if_fail (trace != NULL);
101   g_return_if_fail (trace->buf != NULL);
102
103   if (gst_trace_get_remaining (trace) > 0)
104     gst_trace_flush (trace);
105   close (trace->fd);
106   g_free (trace->buf);
107   g_free (trace);
108 }
109
110 void
111 gst_trace_flush (GstTrace * trace)
112 {
113   if (!trace) {
114     trace = _gst_trace_default;
115     if (!trace)
116       return;
117   }
118
119   g_return_if_fail (write (trace->fd, trace->buf,
120           trace->bufoffset * sizeof (GstTraceEntry)) != -1);
121   trace->bufoffset = 0;
122 }
123
124 void
125 gst_trace_text_flush (GstTrace * trace)
126 {
127   int i;
128
129 #define STRSIZE (20 + 1 + 10 + 1 + 10 + 1 + 112 + 1 + 1)
130   char str[STRSIZE];
131
132   if (!trace) {
133     trace = _gst_trace_default;
134     if (!trace)
135       return;
136   }
137
138   for (i = 0; i < trace->bufoffset; i++) {
139     g_snprintf (str, STRSIZE, "%20" G_GINT64_FORMAT " %10d %10d %s\n",
140         trace->buf[i].timestamp,
141         trace->buf[i].sequence, trace->buf[i].data, trace->buf[i].message);
142     g_return_if_fail (write (trace->fd, str, strlen (str)) != -1);
143   }
144   trace->bufoffset = 0;
145 #undef STRSIZE
146 }
147
148 void
149 gst_trace_set_default (GstTrace * trace)
150 {
151   g_return_if_fail (trace != NULL);
152   _gst_trace_default = trace;
153 }
154
155 void
156 _gst_trace_add_entry (GstTrace * trace, guint32 seq, guint32 data, gchar * msg)
157 {
158   GstTraceEntry *entry;
159
160   if (!trace) {
161     trace = _gst_trace_default;
162     if (!trace)
163       return;
164   }
165
166   entry = trace->buf + trace->bufoffset;
167   read_tsc (&(entry->timestamp));
168   entry->sequence = seq;
169   entry->data = data;
170   strncpy (entry->message, msg, 112);
171   trace->bufoffset++;
172
173   gst_trace_flush (trace);
174 }
175
176
177 /* global flags */
178 static GstAllocTraceFlags _gst_trace_flags = 0;
179
180 /* list of registered tracers */
181 static GList *_gst_alloc_tracers = NULL;
182
183 /**
184  * gst_alloc_trace_available:
185  *
186  * Check if alloc tracing was commiled into the core
187  *
188  * Returns: TRUE if the core was compiled with alloc
189  * tracing enabled.
190  */
191 gboolean
192 gst_alloc_trace_available (void)
193 {
194 #ifdef GST_DISABLE_ALLOC_TRACE
195   return FALSE;
196 #else
197   return TRUE;
198 #endif
199 }
200
201 /**
202  * _gst_alloc_trace_register:
203  * @name: the name of the new alloc trace object.
204  *
205  * Register an get a handle to a GstAllocTrace object that
206  * can be used to trace memory allocations.
207  *
208  * Returns: A handle to a GstAllocTrace.
209  */
210 GstAllocTrace *
211 _gst_alloc_trace_register (const gchar * name)
212 {
213   GstAllocTrace *trace;
214
215   g_return_val_if_fail (name, NULL);
216
217   trace = g_new0 (GstAllocTrace, 1);
218   trace->name = g_strdup (name);
219   trace->live = 0;
220   trace->mem_live = NULL;
221   trace->flags = _gst_trace_flags;
222
223   _gst_alloc_tracers = g_list_prepend (_gst_alloc_tracers, trace);
224
225   return trace;
226 }
227
228 /**
229  * gst_alloc_trace_list:
230  *
231  * Get a list of all registered alloc trace objects.
232  *
233  * Returns: a GList of GstAllocTrace objects.
234  */
235 const GList *
236 gst_alloc_trace_list (void)
237 {
238   return _gst_alloc_tracers;
239 }
240
241 /**
242  * gst_alloc_trace_live_all:
243  *
244  * Get the total number of live registered alloc trace objects.
245  *
246  * Returns: the total number of live registered alloc trace objects.
247  */
248 int
249 gst_alloc_trace_live_all (void)
250 {
251   GList *walk = _gst_alloc_tracers;
252   int num = 0;
253
254   while (walk) {
255     GstAllocTrace *trace = (GstAllocTrace *) walk->data;
256
257     num += trace->live;
258
259     walk = g_list_next (walk);
260   }
261
262   return num;
263 }
264
265 static gint
266 compare_func (GstAllocTrace * a, GstAllocTrace * b)
267 {
268   return strcmp (a->name, b->name);
269 }
270
271 static GList *
272 gst_alloc_trace_list_sorted (void)
273 {
274   GList *ret;
275
276   ret = g_list_sort (g_list_copy (_gst_alloc_tracers),
277       (GCompareFunc) compare_func);
278
279   return ret;
280 }
281
282 /**
283  * gst_alloc_trace_print_all:
284  *
285  * Print the status of all registered alloc trace objects.
286  */
287 void
288 gst_alloc_trace_print_all (void)
289 {
290   GList *orig, *walk;
291
292   orig = walk = gst_alloc_trace_list_sorted ();
293
294   while (walk) {
295     GstAllocTrace *trace = (GstAllocTrace *) walk->data;
296
297     gst_alloc_trace_print (trace);
298
299     walk = g_list_next (walk);
300   }
301
302   g_list_free (orig);
303 }
304
305 /**
306  * gst_alloc_trace_print_live:
307  *
308  * Print the status of all registered alloc trace objects, ignoring those
309  * without live objects.
310  */
311 void
312 gst_alloc_trace_print_live (void)
313 {
314   GList *orig, *walk;
315
316   orig = walk = gst_alloc_trace_list_sorted ();
317
318   while (walk) {
319     GstAllocTrace *trace = (GstAllocTrace *) walk->data;
320
321     if (trace->live)
322       gst_alloc_trace_print (trace);
323
324     walk = g_list_next (walk);
325   }
326
327   g_list_free (orig);
328 }
329
330 /**
331  * gst_alloc_trace_set_flags_all:
332  * @flags: the options to enable
333  *
334  * Enable the specified options on all registered alloc trace
335  * objects.
336  */
337 void
338 gst_alloc_trace_set_flags_all (GstAllocTraceFlags flags)
339 {
340   GList *walk = _gst_alloc_tracers;
341
342   while (walk) {
343     GstAllocTrace *trace = (GstAllocTrace *) walk->data;
344
345     GST_DEBUG ("set flags on %p\n", trace);
346     gst_alloc_trace_set_flags (trace, flags);
347
348     walk = g_list_next (walk);
349   }
350   _gst_trace_flags = flags;
351 }
352
353 /**
354  * gst_alloc_trace_get:
355  * @name: the name of the alloc trace object
356  *
357  * Get the named alloc trace object.
358  *
359  * Returns: a GstAllocTrace with the given name or NULL when
360  * no alloc tracer was registered with that name.
361  */
362 GstAllocTrace *
363 gst_alloc_trace_get (const gchar * name)
364 {
365   GList *walk = _gst_alloc_tracers;
366
367   g_return_val_if_fail (name, NULL);
368
369   while (walk) {
370     GstAllocTrace *trace = (GstAllocTrace *) walk->data;
371
372     if (!strcmp (trace->name, name))
373       return trace;
374
375     walk = g_list_next (walk);
376   }
377   return NULL;
378 }
379
380 /**
381  * gst_alloc_trace_print:
382  * @trace: the GstAllocTrace to print
383  *
384  * Print the status of the given GstAllocTrace.
385  */
386 void
387 gst_alloc_trace_print (const GstAllocTrace * trace)
388 {
389   GSList *mem_live;
390
391   g_return_if_fail (trace != NULL);
392
393   if (trace->flags & GST_ALLOC_TRACE_LIVE) {
394     g_print ("%-22.22s : %d\n", trace->name, trace->live);
395   } else {
396     g_print ("%-22.22s : (no live count)\n", trace->name);
397   }
398
399   if (trace->flags & GST_ALLOC_TRACE_MEM_LIVE) {
400     mem_live = trace->mem_live;
401
402     while (mem_live) {
403       g_print ("%-22.22s : %p\n", "", mem_live->data);
404       mem_live = mem_live->next;
405     }
406   }
407 }
408
409 /**
410  * gst_alloc_trace_set_flags:
411  * @trace: the GstAllocTrace
412  * @flags: flags to set
413  *
414  * Enable the given features on the given GstAllocTrace object.
415  */
416 void
417 gst_alloc_trace_set_flags (GstAllocTrace * trace, GstAllocTraceFlags flags)
418 {
419   g_return_if_fail (trace != NULL);
420
421   trace->flags = flags;
422 }