diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-06-04 18:49:08 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-06-06 04:45:37 -0400 |
commit | 2db8e9d6b255a4fd070df70fa58306bf64b41984 (patch) | |
tree | af13861865fcd7a11132aec845b40266df11a412 /drivers/gpu/drm | |
parent | ef1b460d1bab7e5b04c34f88c3dfa042528e7c27 (diff) |
drm/i915: Track clients and print their object usage in debugfs
By stashing a pointer of who opened the device and keeping a list of
open fd, we can then walk each client and inspect how many objects they
have open. For example,
i915_gem_objects:
1102 objects, 613646336 bytes
663 [662] objects, 468783104 [468750336] bytes in gtt
37 [37] active objects, 46874624 [46874624] bytes
626 [625] inactive objects, 421908480 [421875712] bytes
282 unbound objects, 6512640 bytes
85 purgeable objects, 6787072 bytes
28 pinned mappable objects, 3686400 bytes
40 fault mappable objects, 27783168 bytes
2145386496 [536870912] gtt total
Xorg: 43 objects, 32243712 bytes (10223616 active, 16683008 inactive, 4096 unbound)
gnome-shell: 30 objects, 28381184 bytes (0 active, 28336128 inactive, 0 unbound)
xonotic-linux64: 1032 objects, 569933824 bytes (46874624 active, 383545344 inactive, 6508544 unbound)
v2: Use existing drm->filelist as pointed out by Ben.
v3: Not even stashing the task_struct is required as Ben pointed out
drm_file->pid.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0e7e3c04d939..d4e78b64ca87 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -196,6 +196,32 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data) | |||
196 | } \ | 196 | } \ |
197 | } while (0) | 197 | } while (0) |
198 | 198 | ||
199 | struct file_stats { | ||
200 | int count; | ||
201 | size_t total, active, inactive, unbound; | ||
202 | }; | ||
203 | |||
204 | static int per_file_stats(int id, void *ptr, void *data) | ||
205 | { | ||
206 | struct drm_i915_gem_object *obj = ptr; | ||
207 | struct file_stats *stats = data; | ||
208 | |||
209 | stats->count++; | ||
210 | stats->total += obj->base.size; | ||
211 | |||
212 | if (obj->gtt_space) { | ||
213 | if (!list_empty(&obj->ring_list)) | ||
214 | stats->active += obj->base.size; | ||
215 | else | ||
216 | stats->inactive += obj->base.size; | ||
217 | } else { | ||
218 | if (!list_empty(&obj->global_list)) | ||
219 | stats->unbound += obj->base.size; | ||
220 | } | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
199 | static int i915_gem_object_info(struct seq_file *m, void* data) | 225 | static int i915_gem_object_info(struct seq_file *m, void* data) |
200 | { | 226 | { |
201 | struct drm_info_node *node = (struct drm_info_node *) m->private; | 227 | struct drm_info_node *node = (struct drm_info_node *) m->private; |
@@ -204,6 +230,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data) | |||
204 | u32 count, mappable_count, purgeable_count; | 230 | u32 count, mappable_count, purgeable_count; |
205 | size_t size, mappable_size, purgeable_size; | 231 | size_t size, mappable_size, purgeable_size; |
206 | struct drm_i915_gem_object *obj; | 232 | struct drm_i915_gem_object *obj; |
233 | struct drm_file *file; | ||
207 | int ret; | 234 | int ret; |
208 | 235 | ||
209 | ret = mutex_lock_interruptible(&dev->struct_mutex); | 236 | ret = mutex_lock_interruptible(&dev->struct_mutex); |
@@ -263,6 +290,21 @@ static int i915_gem_object_info(struct seq_file *m, void* data) | |||
263 | dev_priv->gtt.total, | 290 | dev_priv->gtt.total, |
264 | dev_priv->gtt.mappable_end - dev_priv->gtt.start); | 291 | dev_priv->gtt.mappable_end - dev_priv->gtt.start); |
265 | 292 | ||
293 | seq_printf(m, "\n"); | ||
294 | list_for_each_entry_reverse(file, &dev->filelist, lhead) { | ||
295 | struct file_stats stats; | ||
296 | |||
297 | memset(&stats, 0, sizeof(stats)); | ||
298 | idr_for_each(&file->object_idr, per_file_stats, &stats); | ||
299 | seq_printf(m, "%s: %u objects, %zu bytes (%zu active, %zu inactive, %zu unbound)\n", | ||
300 | get_pid_task(file->pid, PIDTYPE_PID)->comm, | ||
301 | stats.count, | ||
302 | stats.total, | ||
303 | stats.active, | ||
304 | stats.inactive, | ||
305 | stats.unbound); | ||
306 | } | ||
307 | |||
266 | mutex_unlock(&dev->struct_mutex); | 308 | mutex_unlock(&dev->struct_mutex); |
267 | 309 | ||
268 | return 0; | 310 | return 0; |