[Intel-gfx] [RFC] Tracing infrastructure for driver performance

Chris Wilson chris at chris-wilson.co.uk
Wed Jul 8 20:58:30 CEST 2009


/* For reference, here is the user space utility to read i915_trace.
 * -ickle
 */

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>

enum {
	I915_TRACE_HEADER,

	I915_TRACE_OBJECT_CREATE,
	I915_TRACE_OBJECT_BIND,
	I915_TRACE_OBJECT_CHANGE_DOMAIN,
	I915_TRACE_OBJECT_GET_FENCE,
	I915_TRACE_OBJECT_UNBIND,
	I915_TRACE_OBJECT_DESTROY,

	I915_TRACE_SUBMIT,
	I915_TRACE_FLUSH,
	I915_TRACE_COMPLETE,
	I915_TRACE_RETIRE,
	I915_TRACE_WAIT_BEGIN,
	I915_TRACE_WAIT_END,
};

#define I915_TRACE_MAGIC 0xdeadbeef
#define I915_TRACE_VERSION 0

struct i915_trace_event {
    uint64_t time;
    uint32_t minor;
    uint32_t id;
    union {
	uint64_t obj;
	uint32_t seqno;
    };
    uint32_t arg1;
    uint32_t arg2;
};

static void
watch (int fd)
{
    struct i915_trace_event event[4096 / sizeof (struct i915_trace_event)];
    int ret;

    /* the very first event is a stream header */
    ret = read (fd, &event[0], sizeof (event[0]));
    if (ret != sizeof (event[0]))
	return;

    if (event[0].id != I915_TRACE_HEADER ||
	event[0].seqno != I915_TRACE_MAGIC ||
	event[0].arg1 != I915_TRACE_VERSION)
    {
	fprintf (stderr, "unhandled i915 trace: "
		 "type=%d, magic=%d, version=%d\n",
		 event[0].id,
		 event[0].seqno,
		 event[0].arg1);
	return;
    }

    do {
	struct i915_trace_event *ev;

	ret = read (fd, event, sizeof (event));
	if (ret < 0)
	    return;

	ev = event;
	while ((ret -= sizeof (*ev)) >= 0) {
	    switch (ev->id) {
		case I915_TRACE_HEADER:
		    break;

		case I915_TRACE_OBJECT_CREATE:
		    printf ("%qu: object_create(%08llx, %d)\n",
			    ev->time,
			    ev->obj,
			    ev->arg1);
		    break;

		case I915_TRACE_OBJECT_BIND:
		    printf ("%qu: object_bind(%08llx)\n",
			    ev->time, ev->obj);
		    break;

		case I915_TRACE_OBJECT_CHANGE_DOMAIN:
		    printf ("%qu: object_change_domain(%08llx, %04x, %04x)\n",
			    ev->time, ev->obj, ev->arg1, ev->arg2);
		    break;

		case I915_TRACE_OBJECT_GET_FENCE:
		    printf ("%qu: object_get_fence(%08llx, %d, %d)\n",
			    ev->time, ev->obj, ev->arg1, ev->arg2);
		    break;

		case I915_TRACE_OBJECT_UNBIND:
		    printf ("%qu: object_unbind(%08llx)\n",
			    ev->time, ev->obj);
		    break;

		case I915_TRACE_OBJECT_DESTROY:
		    printf ("%qu: object_destroy(%08llx)\n",
			    ev->time, ev->obj);
		    break;

		case I915_TRACE_SUBMIT:
		    printf ("%qu: submit(%d)\n", ev->time, ev->seqno);
		    break;
		case I915_TRACE_FLUSH:
		    printf ("%qu: flush(%d, %04x, %04x)\n",
			    ev->time, ev->seqno, ev->arg1, ev->arg2);
		    break;
		case I915_TRACE_COMPLETE:
		    printf ("%qu: complete(%d)\n", ev->time, ev->seqno);
		    break;
		case I915_TRACE_RETIRE:
		    printf ("%qu: retire(%d)\n", ev->time, ev->seqno);
		    break;

		case I915_TRACE_WAIT_BEGIN:
		    printf ("%qu: wait(%d) begin\n", ev->time, ev->seqno);
		    break;
		case I915_TRACE_WAIT_END:
		    printf ("%qu: wait(%d) end\n", ev->time, ev->seqno);
		    break;
	    }
	    ev++;
	}
    } while (1);
}

static int
open_trace (const char *path, int card)
{
    char buf[4096];

    snprintf (buf, sizeof (buf), "%s/dri/%d/i915_trace", path, card);
    return open (buf, O_RDWR);
}

static int
tracepoints_enable (int fd, int active)
{
    return write (fd, active ? "*\n" : "!\n", 2) == 2;
}

int
main (int argc, char **argv)
{
    const char *debugfs = "/sys/kernel/debug";
    int card = 0;
    int fd;

    if (argc > 1)
	card = atoi (argv[1]);

    fd = open_trace (debugfs, card);
    if (fd < 0) {
	perror ("failed to open trace");
	return 1;
    }

    if (! tracepoints_enable (fd, 1)) {
	perror ("failed to enable events");
	close (fd);
	return 1;
    }

    watch (fd);

    if (! tracepoints_enable (fd, 0))
	perror ("failed to disable events");

    close (fd);

    return 0;
}





More information about the Intel-gfx mailing list