libdrm-radeon: new tracker tools
authorJerome Glisse <glisse@freedesktop.org>
Fri, 14 Nov 2008 11:08:27 +0000 (12:08 +0100)
committerJerome Glisse <glisse@freedesktop.org>
Fri, 14 Nov 2008 11:16:10 +0000 (12:16 +0100)
To keep record of bo activities and print them when necessary,
should help in tracking unbalanced ref/unref calls.

libdrm/radeon/Makefile.am
libdrm/radeon/radeon_bo.h
libdrm/radeon/radeon_track.c [new file with mode: 0644]
libdrm/radeon/radeon_track.h [new file with mode: 0644]

index d15a266..39ee021 100644 (file)
@@ -36,11 +36,13 @@ libdrm_radeon_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
 
 libdrm_radeon_la_SOURCES = \
        radeon_bo_gem.c \
-       radeon_cs_gem.c
+       radeon_cs_gem.c \
+       radeon_track.c
 
 libdrm_radeonincludedir = ${includedir}/drm
 libdrm_radeoninclude_HEADERS = \
        radeon_bo.h \
        radeon_cs.h \
        radeon_bo_gem.h \
-       radeon_cs_gem.h
+       radeon_cs_gem.h \
+       radeon_track.h
index f884e0f..ed78503 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <stdio.h>
 #include <stdint.h>
+#include "radeon_track.h"
 
 /* bo object */
 #define RADEON_BO_FLAGS_MACRO_TILE  1
@@ -46,6 +47,9 @@ struct radeon_bo {
     uint32_t                    domains;
     uint32_t                    flags;
     unsigned                    cref;
+#ifdef RADEON_BO_TRACK
+    struct radeon_track         *track;
+#endif
     void                        *ptr;
     struct radeon_bo_manager    *bom;
 };
@@ -67,6 +71,7 @@ struct radeon_bo_funcs {
 struct radeon_bo_manager {
     struct radeon_bo_funcs  *funcs;
     int                     fd;
+    struct radeon_tracker   tracker;
 };
     
 static inline void _radeon_bo_debug(struct radeon_bo *bo,
@@ -90,10 +95,12 @@ static inline struct radeon_bo *_radeon_bo_open(struct radeon_bo_manager *bom,
                                                 int line)
 {
     struct radeon_bo *bo;
+
     bo = bom->funcs->bo_open(bom, handle, size, alignment, domains, flags);
-#ifdef RADEON_BO_TRACK_OPEN
+#ifdef RADEON_BO_TRACK
     if (bo) {
-        _radeon_bo_debug(bo, 1, file, func, line);
+        bo->track = radeon_tracker_add_track(&bom->tracker, bo->handle);
+        radeon_track_add_event(bo->track, file, func, "open", line);
     }
 #endif
     return bo;
@@ -105,8 +112,8 @@ static inline void _radeon_bo_ref(struct radeon_bo *bo,
                                   int line)
 {
     bo->cref++;
-#ifdef RADEON_BO_TRACK_REF
-    _radeon_bo_debug(bo, 2, file, func, line);
+#ifdef RADEON_BO_TRACK
+    radeon_track_add_event(bo->track, file, func, "ref", line); 
 #endif
     bo->bom->funcs->bo_ref(bo);
 }
@@ -117,8 +124,12 @@ static inline void _radeon_bo_unref(struct radeon_bo *bo,
                                     int line)
 {
     bo->cref--;
-#ifdef RADEON_BO_TRACK_REF
-    _radeon_bo_debug(bo, 3, file, func, line);
+#ifdef RADEON_BO_TRACK
+    radeon_track_add_event(bo->track, file, func, "unref", line);
+    if (bo->cref <= 0) {
+        radeon_tracker_remove_track(&bo->bom->tracker, bo->track);
+        bo->track = NULL;
+    }
 #endif
     bo->bom->funcs->bo_unref(bo);
 }
@@ -129,9 +140,6 @@ static inline int _radeon_bo_map(struct radeon_bo *bo,
                                  const char *func,
                                  int line)
 {
-#ifdef RADEON_BO_TRACK_MAP
-    _radeon_bo_debug(bo, 4, file, func, line);
-#endif
     return bo->bom->funcs->bo_map(bo, write);
 }
 
@@ -140,9 +148,6 @@ static inline int _radeon_bo_unmap(struct radeon_bo *bo,
                                    const char *func,
                                    int line)
 {
-#ifdef RADEON_BO_TRACK_MAP
-    _radeon_bo_debug(bo, 5, file, func, line);
-#endif
     return bo->bom->funcs->bo_unmap(bo);
 }
 
diff --git a/libdrm/radeon/radeon_track.c b/libdrm/radeon/radeon_track.c
new file mode 100644 (file)
index 0000000..c0c6f85
--- /dev/null
@@ -0,0 +1,139 @@
+/* 
+ * Copyright © 2008 Jérôme Glisse
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
+ * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ *      Jérôme Glisse <glisse@freedesktop.org>
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "radeon_track.h"
+
+void radeon_track_add_event(struct radeon_track *track,
+                            const char *file,
+                            const char *func,
+                            const char *op,
+                            unsigned line)
+{
+    struct radeon_track_event *event;
+
+    if (track == NULL) {
+        return;
+    }
+    event = (void*)calloc(1,sizeof(struct radeon_track_event));
+    if (event == NULL) {
+        return;
+    }
+    event->line = line;
+    event->file = strdup(file);
+    event->func = strdup(func);
+    event->op = strdup(op);
+    if (event->file == NULL || event->func == NULL || event->op == NULL) {
+        free(event->file);
+        free(event->func);
+        free(event->op);
+        free(event);
+        return;
+    }
+    event->next = track->events;
+    track->events = event;
+}
+
+struct radeon_track *radeon_tracker_add_track(struct radeon_tracker *tracker,
+                                              unsigned key)
+{
+    struct radeon_track *track;
+
+    track = (struct radeon_track*)calloc(1, sizeof(struct radeon_track));
+    if (track) {
+        track->next = tracker->tracks.next;
+        track->prev = &tracker->tracks;
+        tracker->tracks.next = track;
+        if (track->next) {
+            track->next->prev = track;
+        }
+        track->key = key;
+        track->events = NULL;
+    }
+    return track;
+}
+
+void radeon_tracker_remove_track(struct radeon_tracker *tracker,
+                                 struct radeon_track *track)
+{
+    struct radeon_track_event *event;
+    void *tmp;
+
+    if (track == NULL) {
+        return;
+    }
+    track->prev->next = track->next;
+    if (track->next) {
+        track->next->prev = track->prev;
+    }
+    event = track->events;
+    while (event) {
+        tmp = event;
+        free(event->file);
+        free(event->func);
+        free(event->op);
+        event = event->next;
+        free(tmp);
+    }
+    track->events = NULL;
+    free(track);
+}
+
+void radeon_tracker_print(struct radeon_tracker *tracker, FILE *file)
+{
+    struct radeon_track *track;
+    struct radeon_track_event *event;
+    void *tmp;
+
+    track = tracker->tracks.next;
+    while (track) {
+        event = track->events;
+        fprintf(file, "[0x%08X] :\n", track->key);
+        while (event) {
+            tmp = event;
+            fprintf(file, "  [0x%08X:%s](%s:%s:%d)\n",
+                    track->key, event->op,  event->file,
+                    event->func, event->line);
+            free(event->file);
+            free(event->func);
+            free(event->op);
+            event->file = NULL;
+            event->func = NULL;
+            event->op = NULL;
+            event = event->next;
+            free(tmp);
+        }
+        track->events = NULL;
+        tmp = track;
+        track = track->next;
+        free(tmp);
+    }
+}
diff --git a/libdrm/radeon/radeon_track.h b/libdrm/radeon/radeon_track.h
new file mode 100644 (file)
index 0000000..838d1f3
--- /dev/null
@@ -0,0 +1,64 @@
+/* 
+ * Copyright © 2008 Jérôme Glisse
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
+ * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ *      Jérôme Glisse <glisse@freedesktop.org>
+ */
+#ifndef RADEON_TRACK_H
+#define RADEON_TRACK_H
+
+struct radeon_track_event {
+    struct radeon_track_event   *next;
+    char                        *file;
+    char                        *func;
+    char                        *op;
+    unsigned                    line;
+};
+
+struct radeon_track {
+    struct radeon_track         *next;
+    struct radeon_track         *prev;
+    unsigned                    key;
+    struct radeon_track_event   *events;
+};
+
+struct radeon_tracker {
+    struct radeon_track         tracks; 
+};
+
+void radeon_track_add_event(struct radeon_track *track,
+                            const char *file,
+                            const char *func,
+                            const char *op,
+                            unsigned line);
+struct radeon_track *radeon_tracker_add_track(struct radeon_tracker *tracker,
+                                              unsigned key);
+void radeon_tracker_remove_track(struct radeon_tracker *tracker,
+                                 struct radeon_track *track);
+void radeon_tracker_print(struct radeon_tracker *tracker,
+                          FILE *file);
+
+#endif