various style fixes
[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  * Returns the total number of live registered alloc trace objects.
245  */
246 int
247 gst_alloc_trace_live_all (void)
248 {
249   GList *walk = _gst_alloc_tracers;
250   int num = 0;
251
252   while (walk) {
253     GstAllocTrace *trace = (GstAllocTrace *) walk->data;
254
255     num += trace->live;
256
257     walk = g_list_next (walk);
258   }
259
260   return num;
261 }
262
263 static gint
264 compare_func (GstAllocTrace * a, GstAllocTrace * b)
265 {
266   return strcmp (a->name, b->name);
267 }
268
269 static GList *
270 gst_alloc_trace_list_sorted (void)
271 {
272   GList *ret;
273
274   ret = g_list_sort (g_list_copy (_gst_alloc_tracers),
275       (GCompareFunc) compare_func);
276
277   return ret;
278 }
279
280 /**
281  * gst_alloc_trace_print_all:
282  *
283  * Print the status of all registered alloc trace objects.
284  */
285 void
286 gst_alloc_trace_print_all (void)
287 {
288   GList *orig, *walk;
289
290   orig = walk = gst_alloc_trace_list_sorted ();
291
292   while (walk) {
293     GstAllocTrace *trace = (GstAllocTrace *) walk->data;
294
295     gst_alloc_trace_print (trace);
296
297     walk = g_list_next (walk);
298   }
299
300   g_list_free (orig);
301 }
302
303 /**
304  * gst_alloc_trace_print_live:
305  *
306  * Print the status of all registered alloc trace objects, ignoring those
307  * without live objects.
308  */
309 void
310 gst_alloc_trace_print_live (void)
311 {
312   GList *orig, *walk;
313
314   orig = walk = gst_alloc_trace_list_sorted ();
315
316   while (walk) {
317     GstAllocTrace *trace = (GstAllocTrace *) walk->data;
318
319     if (trace->live)
320       gst_alloc_trace_print (trace);
321
322     walk = g_list_next (walk);
323   }
324
325   g_list_free (orig);
326 }
327
328 /**
329  * gst_alloc_trace_set_flags_all:
330  * @flags: the options to enable
331  *
332  * Enable the specified options on all registered alloc trace
333  * objects.
334  */
335 void
336 gst_alloc_trace_set_flags_all (GstAllocTraceFlags flags)
337 {
338   GList *walk = _gst_alloc_tracers;
339
340   while (walk) {
341     GstAllocTrace *trace = (GstAllocTrace *) walk->data;
342
343     GST_DEBUG ("set flags on %p\n", trace);
344     gst_alloc_trace_set_flags (trace, flags);
345
346     walk = g_list_next (walk);
347   }
348   _gst_trace_flags = flags;
349 }
350
351 /**
352  * gst_alloc_trace_get:
353  * @name: the name of the alloc trace object
354  *
355  * Get the named alloc trace object.
356  *
357  * Returns: a GstAllocTrace with the given name or NULL when
358  * no alloc tracer was registered with that name.
359  */
360 GstAllocTrace *
361 gst_alloc_trace_get (const gchar * name)
362 {
363   GList *walk = _gst_alloc_tracers;
364
365   g_return_val_if_fail (name, NULL);
366
367   while (walk) {
368     GstAllocTrace *trace = (GstAllocTrace *) walk->data;
369
370     if (!strcmp (trace->name, name))
371       return trace;
372
373     walk = g_list_next (walk);
374   }
375   return NULL;
376 }
377
378 /**
379  * gst_alloc_trace_print:
380  * @trace: the GstAllocTrace to print
381  *
382  * Print the status of the given GstAllocTrace.
383  */
384 void
385 gst_alloc_trace_print (const GstAllocTrace * trace)
386 {
387   GSList *mem_live;
388
389   g_return_if_fail (trace != NULL);
390
391   if (trace->flags & GST_ALLOC_TRACE_LIVE) {
392     g_print ("%-22.22s : %d\n", trace->name, trace->live);
393   } else {
394     g_print ("%-22.22s : (no live count)\n", trace->name);
395   }
396
397   if (trace->flags & GST_ALLOC_TRACE_MEM_LIVE) {
398     mem_live = trace->mem_live;
399
400     while (mem_live) {
401       g_print ("%-22.22s : %p\n", "", mem_live->data);
402       mem_live = mem_live->next;
403     }
404   }
405 }
406
407 /**
408  * gst_alloc_trace_set_flags:
409  * @trace: the GstAllocTrace
410  * @flags: flags to set
411  *
412  * Enable the given features on the given GstAllocTrace object.
413  */
414 void
415 gst_alloc_trace_set_flags (GstAllocTrace * trace, GstAllocTraceFlags flags)
416 {
417   g_return_if_fail (trace != NULL);
418
419   trace->flags = flags;
420 }