xf86-video-intel: configure.ac src/sna/kgem.c src/sna/kgem.h src/sna/sna_accel.c src/sna/sna_driver.c src/sna/sna.h

Chris Wilson ickle at kemper.freedesktop.org
Mon Jun 11 04:19:01 PDT 2012


 configure.ac         |    4 +++
 src/sna/kgem.c       |   33 +++++++++++++++++++++++++++++++
 src/sna/kgem.h       |    7 ++++++
 src/sna/sna.h        |   13 +++++++++++-
 src/sna/sna_accel.c  |   53 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/sna/sna_driver.c |    6 ++++-
 6 files changed, 114 insertions(+), 2 deletions(-)

New commits:
commit 392e33a62d729c64c57699505220b4029e015470
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Jun 11 09:51:41 2012 +0100

    sna: Instrument memory/bo allocations for monitoring over time
    
    Hide it behind --enable-debug=memory to avoid incurring the cost for
    everybody.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/configure.ac b/configure.ac
index a9e8fa5..0b93a2f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -315,7 +315,11 @@ if test "x$DEBUG" != xno; then
 		AC_DEFINE([HAVE_VALGRIND], 1, [Use valgrind intrinsics to suppress false warnings])
 	fi
 fi
+if test "x$DEBUG" = xmemory; then
+	AC_DEFINE(DEBUG_MEMORY,1,[Enable memory debugging])
+fi
 if test "x$DEBUG" = xfull; then
+	AC_DEFINE(DEBUG_MEMORY,1,[Enable memory debugging])
 	AC_DEFINE(HAS_DEBUG_FULL,1,[Enable all debugging])
         CFLAGS="$CFLAGS -O0 -ggdb3"
 fi
diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index d1ba753..0c7b56c 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -116,6 +116,21 @@ static inline int bytes(struct kgem_bo *bo)
 #define bucket(B) (B)->size.pages.bucket
 #define num_pages(B) (B)->size.pages.count
 
+#ifdef DEBUG_MEMORY
+static void debug_alloc(struct kgem *kgem, size_t size)
+{
+	kgem->debug_memory.bo_allocs++;
+	kgem->debug_memory.bo_bytes += size;
+}
+static void debug_alloc__bo(struct kgem *kgem, struct kgem_bo *bo)
+{
+	debug_alloc(kgem, bytes(bo));
+}
+#else
+#define debug_alloc(k, b)
+#define debug_alloc__bo(k, b)
+#endif
+
 static void kgem_sna_reset(struct kgem *kgem)
 {
 	struct sna *sna = container_of(kgem, struct sna, kgem);
@@ -1008,6 +1023,11 @@ static void kgem_bo_free(struct kgem *kgem, struct kgem_bo *bo)
 	assert(bo->exec == NULL);
 	assert(!bo->vmap || bo->rq == NULL);
 
+#ifdef DEBUG_MEMORY
+	kgem->debug_memory.bo_allocs--;
+	kgem->debug_memory.bo_bytes -= bytes(bo);
+#endif
+
 	kgem_bo_binding_free(kgem, bo);
 
 	if (IS_VMAP_MAP(bo->map)) {
@@ -2316,6 +2336,8 @@ struct kgem_bo *kgem_create_for_name(struct kgem *kgem, uint32_t name)
 
 	bo->reusable = false;
 	bo->flush = true;
+
+	debug_alloc__bo(kgem, bo);
 	return bo;
 }
 
@@ -2349,6 +2371,7 @@ struct kgem_bo *kgem_create_linear(struct kgem *kgem, int size, unsigned flags)
 		return NULL;
 	}
 
+	debug_alloc__bo(kgem, bo);
 	return bo;
 }
 
@@ -2882,6 +2905,8 @@ create:
 
 	assert(bytes(bo) >= bo->pitch * kgem_aligned_height(kgem, height, bo->tiling));
 
+	debug_alloc__bo(kgem, bo);
+
 	DBG(("  new pitch=%d, tiling=%d, handle=%d, id=%d\n",
 	     bo->pitch, bo->tiling, bo->handle, bo->unique_id));
 	return bo;
@@ -3449,6 +3474,8 @@ struct kgem_bo *kgem_create_map(struct kgem *kgem,
 	bo->reusable = false;
 	bo->vmap = true;
 
+	debug_alloc__bo(kgem, bo);
+
 	DBG(("%s(ptr=%p, size=%d, pages=%d, read_only=%d) => handle=%d\n",
 	     __FUNCTION__, ptr, size, NUM_PAGES(size), read_only, handle));
 	return bo;
@@ -3729,6 +3756,8 @@ struct kgem_bo *kgem_create_buffer(struct kgem *kgem,
 			}
 			DBG(("%s: created handle=%d for buffer\n",
 			     __FUNCTION__, bo->base.handle));
+
+			debug_alloc(kgem, alloc);
 		}
 
 		bo->mem = kgem_bo_map__cpu(kgem, &bo->base);
@@ -3916,6 +3945,8 @@ struct kgem_bo *kgem_create_buffer(struct kgem *kgem,
 			}
 			DBG(("%s: created handle=%d for buffer\n",
 			     __FUNCTION__, bo->base.handle));
+
+			debug_alloc(kgem, alloc * PAGE_SIZE);
 		}
 
 		bo->mem = kgem_bo_map__cpu(kgem, &bo->base);
@@ -4195,6 +4226,8 @@ kgem_replace_bo(struct kgem *kgem,
 			gem_close(kgem->fd, handle);
 			return NULL;
 		}
+
+		debug_alloc__bo(kgem, dst);
 	}
 	dst->pitch = pitch;
 	dst->unique_id = kgem_get_unique_id(kgem);
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index e4a5b4c..b747dc7 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -173,6 +173,13 @@ struct kgem {
 	uint32_t batch[64*1024-8];
 	struct drm_i915_gem_exec_object2 exec[256];
 	struct drm_i915_gem_relocation_entry reloc[4096];
+
+#ifdef DEBUG_MEMORY
+	struct {
+		int bo_allocs;
+		size_t bo_bytes;
+	} debug_memory;
+#endif
 };
 
 #define KGEM_BATCH_RESERVED 1
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 6aa54d1..16bdf13 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -195,9 +195,11 @@ enum {
 	THROTTLE_TIMER,
 	EXPIRE_TIMER,
 	INACTIVE_TIMER,
+#if DEBUG_MEMORY
+	DEBUG_MEMORY_TIMER,
+#endif
 	NUM_TIMERS
 };
-#define NUM_FINE_TIMERS 1
 
 struct sna {
 	ScrnInfoPtr scrn;
@@ -287,6 +289,15 @@ struct sna {
 
 	struct kgem kgem;
 	struct sna_render render;
+
+#if DEBUG_MEMORY
+	struct {
+	       int shadow_pixels_allocs;
+	       int cpu_bo_allocs;
+	       size_t shadow_pixels_bytes;
+	       size_t cpu_bo_bytes;
+	} debug_memory;
+#endif
 };
 
 Bool sna_mode_pre_init(ScrnInfoPtr scrn, struct sna *sna);
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 0840056..8498b3c 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -362,6 +362,11 @@ sna_pixmap_alloc_cpu(struct sna *sna,
 	DBG(("%s: pixmap=%ld\n", __FUNCTION__, pixmap->drawable.serialNumber));
 	assert(priv->stride);
 
+#ifdef DEBUG_MEMORY
+	sna->debug_memory.shadow_pixels_allocs++;
+	sna->debug_memory.shadow_pixels_bytes += priv->stride * pixmap->drawable.height;
+#endif
+
 	if (priv->create & KGEM_CAN_CREATE_CPU) {
 		DBG(("%s: allocating CPU buffer (%dx%d)\n", __FUNCTION__,
 		     pixmap->drawable.width, pixmap->drawable.height));
@@ -377,6 +382,10 @@ sna_pixmap_alloc_cpu(struct sna *sna,
 
 			priv->ptr = kgem_bo_map__cpu(&sna->kgem, priv->cpu_bo);
 			priv->stride = priv->cpu_bo->pitch;
+#ifdef DEBUG_MEMORY
+			sna->debug_memory.cpu_bo_allocs++;
+			sna->debug_memory.cpu_bo_bytes += kgem_bo_size(priv->cpu_bo);
+#endif
 		}
 	}
 
@@ -400,6 +409,10 @@ static void sna_pixmap_free_cpu(struct sna *sna, struct sna_pixmap *priv)
 	assert(priv->cpu_damage == NULL);
 	assert(list_is_empty(&priv->list));
 
+#ifdef DEBUG_MEMORY
+	sna->debug_memory.shadow_pixels_allocs--;
+	sna->debug_memory.shadow_pixels_bytes -= priv->stride * priv->pixmap->drawable.height;
+#endif
 	if (priv->cpu_bo) {
 		DBG(("%s: discarding CPU buffer, handle=%d, size=%d\n",
 		     __FUNCTION__, priv->cpu_bo->handle, kgem_bo_size(priv->cpu_bo)));
@@ -409,6 +422,10 @@ static void sna_pixmap_free_cpu(struct sna *sna, struct sna_pixmap *priv)
 		}
 		kgem_bo_destroy(&sna->kgem, priv->cpu_bo);
 		priv->cpu_bo = NULL;
+#ifdef DEBUG_MEMORY
+		sna->debug_memory.cpu_bo_allocs--;
+		sna->debug_memory.cpu_bo_bytes -= kgem_bo_size(priv->cpu_bo);
+#endif
 	} else
 		free(priv->ptr);
 
@@ -12317,6 +12334,35 @@ static void sna_accel_inactive(struct sna *sna)
 		sna_accel_disarm_timer(sna, INACTIVE_TIMER);
 }
 
+#ifdef DEBUG_MEMORY
+static bool sna_accel_do_debug_memory(struct sna *sna)
+{
+	int32_t delta = sna->timer_expire[DEBUG_MEMORY_TIMER] - sna->time;
+
+	if (delta <= 3) {
+		sna->timer_expire[DEBUG_MEMORY_TIMER] = sna->time + 10 * 1000;
+		return true;
+	} else
+		return false;
+}
+
+static void sna_accel_debug_memory(struct sna *sna)
+{
+	ErrorF("Allocated shadow pixels: %d, %d bytes, as CPU bo: %d, %d bytes\n",
+	       sna->debug_memory.shadow_pixels_allocs,
+	       sna->debug_memory.shadow_pixels_bytes,
+	       sna->debug_memory.cpu_bo_allocs,
+	       sna->debug_memory.cpu_bo_bytes);
+	ErrorF("Allocated bo: %d, %d bytes\n",
+	       sna->kgem.debug_memory.bo_allocs,
+	       sna->kgem.debug_memory.bo_bytes);
+}
+
+#else
+#define sna_accel_do_debug_memory(x) 0
+static void sna_accel_debug_memory(struct sna *sna) { }
+#endif
+
 Bool sna_accel_pre_init(struct sna *sna)
 {
 	sna->timer = TimerSet(NULL, 0, 0, sna_timeout, sna);
@@ -12340,6 +12386,10 @@ Bool sna_accel_init(ScreenPtr screen, struct sna *sna)
 
 	AddGeneralSocket(sna->kgem.fd);
 
+#ifdef DEBUG_MEMORY
+	sna->timer_expire[DEBUG_MEMORY_TIMER] = GetTimeInMillis()+ 10 * 1000;
+#endif
+
 	screen->CreateGC = sna_create_gc;
 	screen->GetImage = sna_get_image;
 	screen->GetSpans = sna_get_spans;
@@ -12476,6 +12526,9 @@ void sna_accel_block_handler(struct sna *sna, struct timeval **tv)
 	if (sna_accel_do_inactive(sna))
 		sna_accel_inactive(sna);
 
+	if (sna_accel_do_debug_memory(sna))
+		sna_accel_debug_memory(sna);
+
 	if (sna->flush == 0 && sna->watch_flush == 1) {
 		DBG(("%s: removing watchers\n", __FUNCTION__));
 		DeleteCallback(&FlushCallback, sna_accel_flush_callback, sna);
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index 32b96e1..64132b5 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -1074,10 +1074,14 @@ Bool sna_init_scrn(ScrnInfoPtr scrn, int entity_num)
 	xf86DrvMsg(scrn->scrnIndex, X_INFO,
 		   "SNA compiled: %s\n", BUILDER_DESCRIPTION);
 #endif
-#if HAVE_EXTRA_DEBUG
+#if HAS_EXTRA_DEBUG
 	xf86DrvMsg(scrn->scrnIndex, X_INFO,
 		   "SNA compiled with debugging enabled\n");
 #endif
+#if DEBUG_MEMORY
+	xf86DrvMsg(scrn->scrnIndex, X_INFO,
+		   "SNA compiled with memory allocation reporting enabled\n");
+#endif
 
 	DBG(("%s\n", __FUNCTION__));
 	DBG(("pixman version: %s\n", pixman_version_string()));


More information about the xorg-commit mailing list