public inbox for igt-dev@lists.freedesktop.org
 help / color / mirror / Atom feed
* [igt-dev] ✓ Fi.CI.IGT: success for series starting with [1/2] tools/intel_gpu_top: Add support for stdout logging
  2019-02-08 12:03 [igt-dev] [IGT 1/2] " Tvrtko Ursulin
@ 2019-02-08 14:11 ` Patchwork
  0 siblings, 0 replies; 7+ messages in thread
From: Patchwork @ 2019-02-08 14:11 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: igt-dev

== Series Details ==

Series: series starting with [1/2] tools/intel_gpu_top: Add support for stdout logging
URL   : https://patchwork.freedesktop.org/series/56393/
State : success

== Summary ==

CI Bug Log - changes from IGT_4814_full -> IGTPW_2362_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/56393/revisions/1/mbox/

Known issues
------------

  Here are the changes found in IGTPW_2362_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_mmap_gtt@hang:
    - shard-snb:          NOTRUN -> FAIL [fdo#109469]

  * igt@kms_available_modes_crc@available_mode_test_crc:
    - shard-kbl:          PASS -> FAIL [fdo#106641]

  * igt@kms_busy@extended-modeset-hang-newfb-with-reset-render-a:
    - shard-snb:          NOTRUN -> DMESG-WARN [fdo#107956]

  * igt@kms_color@pipe-a-ctm-max:
    - shard-apl:          PASS -> FAIL [fdo#108147]

  * igt@kms_color@pipe-a-gamma:
    - shard-kbl:          PASS -> FAIL [fdo#104782]

  * igt@kms_cursor_crc@cursor-128x128-suspend:
    - shard-apl:          PASS -> FAIL [fdo#103191] / [fdo#103232]

  * igt@kms_cursor_crc@cursor-64x21-sliding:
    - shard-apl:          PASS -> FAIL [fdo#103232] +1
    - shard-glk:          PASS -> FAIL [fdo#103232]

  * igt@kms_flip@2x-flip-vs-expired-vblank-interruptible:
    - shard-glk:          PASS -> FAIL [fdo#105363]

  * igt@kms_frontbuffer_tracking@fbc-1p-offscren-pri-indfb-draw-mmap-gtt:
    - shard-kbl:          PASS -> DMESG-WARN [fdo#103558] / [fdo#105602] +6

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-blt:
    - shard-kbl:          PASS -> FAIL [fdo#103167]

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-onoff:
    - shard-apl:          PASS -> FAIL [fdo#103167] +2

  * igt@kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-mmap-wc:
    - shard-glk:          PASS -> FAIL [fdo#103167] +9

  * igt@kms_plane@plane-position-covered-pipe-a-planes:
    - shard-glk:          PASS -> FAIL [fdo#103166] +3

  * igt@kms_plane_alpha_blend@pipe-a-alpha-opaque-fb:
    - shard-glk:          NOTRUN -> FAIL [fdo#108145]

  * igt@kms_plane_lowres@pipe-a-tiling-none:
    - shard-kbl:          PASS -> FAIL [fdo#103166]

  * igt@kms_plane_multiple@atomic-pipe-b-tiling-x:
    - shard-apl:          PASS -> FAIL [fdo#103166] +2

  * igt@kms_rotation_crc@multiplane-rotation:
    - shard-kbl:          PASS -> FAIL [fdo#109016]

  * igt@kms_setmode@basic:
    - shard-apl:          PASS -> FAIL [fdo#99912]

  
#### Possible fixes ####

  * igt@kms_ccs@pipe-a-crc-sprite-planes-basic:
    - shard-kbl:          FAIL [fdo#107725] / [fdo#108145] -> PASS

  * igt@kms_color@pipe-c-ctm-max:
    - shard-kbl:          FAIL [fdo#108147] -> PASS
    - shard-apl:          FAIL [fdo#108147] -> PASS

  * igt@kms_color@pipe-c-legacy-gamma:
    - shard-apl:          FAIL [fdo#104782] -> PASS

  * igt@kms_cursor_crc@cursor-128x128-random:
    - shard-apl:          FAIL [fdo#103232] -> PASS +6

  * igt@kms_cursor_crc@cursor-256x256-random:
    - shard-kbl:          FAIL [fdo#103232] -> PASS

  * igt@kms_cursor_crc@cursor-256x85-sliding:
    - shard-glk:          FAIL [fdo#103232] -> PASS +1

  * igt@kms_flip@flip-vs-expired-vblank:
    - shard-glk:          FAIL [fdo#102887] / [fdo#105363] -> PASS

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-mmap-gtt:
    - shard-apl:          FAIL [fdo#103167] -> PASS +2

  * igt@kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-render:
    - shard-glk:          FAIL [fdo#103167] -> PASS

  * igt@kms_plane@pixel-format-pipe-a-planes-source-clamping:
    - shard-glk:          FAIL [fdo#108948] -> PASS

  * igt@kms_plane@pixel-format-pipe-b-planes-source-clamping:
    - shard-apl:          FAIL [fdo#108948] -> PASS

  * igt@kms_plane@plane-position-covered-pipe-c-planes:
    - shard-apl:          FAIL [fdo#103166] -> PASS +2

  * igt@kms_plane_alpha_blend@pipe-b-alpha-opaque-fb:
    - shard-glk:          FAIL [fdo#108145] -> PASS +1

  * igt@kms_plane_multiple@atomic-pipe-c-tiling-yf:
    - shard-kbl:          FAIL [fdo#103166] -> PASS +4

  * igt@kms_setmode@basic:
    - shard-kbl:          FAIL [fdo#99912] -> PASS

  * igt@kms_vblank@pipe-c-ts-continuation-suspend:
    - shard-kbl:          INCOMPLETE [fdo#103665] -> PASS

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#102887]: https://bugs.freedesktop.org/show_bug.cgi?id=102887
  [fdo#103166]: https://bugs.freedesktop.org/show_bug.cgi?id=103166
  [fdo#103167]: https://bugs.freedesktop.org/show_bug.cgi?id=103167
  [fdo#103191]: https://bugs.freedesktop.org/show_bug.cgi?id=103191
  [fdo#103232]: https://bugs.freedesktop.org/show_bug.cgi?id=103232
  [fdo#103558]: https://bugs.freedesktop.org/show_bug.cgi?id=103558
  [fdo#103665]: https://bugs.freedesktop.org/show_bug.cgi?id=103665
  [fdo#104782]: https://bugs.freedesktop.org/show_bug.cgi?id=104782
  [fdo#105363]: https://bugs.freedesktop.org/show_bug.cgi?id=105363
  [fdo#105602]: https://bugs.freedesktop.org/show_bug.cgi?id=105602
  [fdo#106641]: https://bugs.freedesktop.org/show_bug.cgi?id=106641
  [fdo#107725]: https://bugs.freedesktop.org/show_bug.cgi?id=107725
  [fdo#107956]: https://bugs.freedesktop.org/show_bug.cgi?id=107956
  [fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
  [fdo#108147]: https://bugs.freedesktop.org/show_bug.cgi?id=108147
  [fdo#108948]: https://bugs.freedesktop.org/show_bug.cgi?id=108948
  [fdo#109016]: https://bugs.freedesktop.org/show_bug.cgi?id=109016
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
  [fdo#109469]: https://bugs.freedesktop.org/show_bug.cgi?id=109469
  [fdo#99912]: https://bugs.freedesktop.org/show_bug.cgi?id=99912


Participating hosts (7 -> 5)
------------------------------

  Missing    (2): shard-skl shard-iclb 


Build changes
-------------

    * IGT: IGT_4814 -> IGTPW_2362

  CI_DRM_5566: dc8d2739325432dd969028550e9e9b3070b76db1 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_2362: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2362/
  IGT_4814: cec046d72944a2d559ce5bd83358f08f20454005 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2362/
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [igt-dev] [IGT 1/2] tools/intel_gpu_top: Add support for stdout logging
@ 2019-02-11 11:45 Tvrtko Ursulin
  2019-02-11 11:45 ` [igt-dev] [IGT 2/2] tools/intel_gpu_top: Add file output capability Tvrtko Ursulin
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Tvrtko Ursulin @ 2019-02-11 11:45 UTC (permalink / raw)
  To: igt-dev; +Cc: Intel-gfx, Eero Tamminen, 3.14pi, Tvrtko Ursulin

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

Two new output modes are added: listing of text data to standard out (-l
on the command line), and dumping of JSON formatted records (-J), also to
standard out.

The first mode is selected automatically when non-interactive standard out
is detected.

Example of text output:

 Freq MHz      IRQ RC6 Power     IMC MiB/s           RCS/0           BCS/0           VCS/0           VCS/1          VECS/0
 req  act       /s   %     W     rd     wr       %  se  wa       %  se  wa       %  se  wa       %  se  wa       %  se  wa
   0    0        0   0  0.00    360      0    0.00   0   0    0.00   0   0    0.00   0   0    0.00   0   0    0.00   0   0
 350  350        0 100  0.00     35      2    0.00   0   0    0.00   0   0    0.00   0   0    0.00   0   0    0.00   0   0
 350  350        0 100  0.00     34      2    0.00   0   0    0.00   0   0    0.00   0   0    0.00   0   0    0.00   0   0
 350  350        0 100  0.00    143      6    0.00   0   0    0.00   0   0    0.00   0   0    0.00   0   0    0.00   0   0
 350  350        0 100  0.00    169      7    0.00   0   0    0.00   0   0    0.00   0   0    0.00   0   0    0.00   0   0
 350  350        0 100  0.00    169      7    0.00   0   0    0.00   0   0    0.00   0   0    0.00   0   0    0.00   0   0

Example of JSON output:

{
        "period": {
                "duration": 1002.525224,
                "unit": "ms"
        },
        "frequency": {
                "requested": 349.118398,
                "actual": 349.118398,
                "unit": "MHz"
        },
        "interrupts": {
                "count": 0.000000,
                "unit": "irq/s"
        },
        "rc6": {
                "value": 99.897752,
                "unit": "%"
        },
        "power": {
                "value": 0.000000,
                "unit": "W"
        },
        "imc-bandwidth": {
                "reads": 149.683843,
                "writes": 6.104093,
                "unit": "MiB/s"
        },
        "engines": {
                "Render/3D/0": {
                        "busy": 0.000000,
                        "sema": 0.000000,
                        "wait": 0.000000,
                        "unit": "%"
                },
                "Blitter/0": {
                        "busy": 0.000000,
                        "sema": 0.000000,
                        "wait": 0.000000,
                        "unit": "%"
                },
                "Video/0": {
                        "busy": 0.000000,
                        "sema": 0.000000,
                        "wait": 0.000000,
                        "unit": "%"
                },
                "Video/1": {
                        "busy": 0.000000,
                        "sema": 0.000000,
                        "wait": 0.000000,
                        "unit": "%"
                },
                "VideoEnhance/0": {
                        "busy": 0.000000,
                        "sema": 0.000000,
                        "wait": 0.000000,
                        "unit": "%"
                }
        }
}

v2:
 * Show example output in commit message.
 * Install signal handler to complete output on SIGINT. (Chris Wilson)

v3:
 * Use asprintf where possible. (Chris Wilson)

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
References: https://bugs.freedesktop.org/show_bug.cgi?id=108689
Cc: Eero Tamminen <eero.t.tamminen@intel.com>
Cc: 3.14pi@ukr.net
Cc: Chris Wilson <chris@chris-wilson.co.uk>
---
 man/intel_gpu_top.rst |   9 +-
 tools/intel_gpu_top.c | 761 +++++++++++++++++++++++++++++++++++-------
 2 files changed, 644 insertions(+), 126 deletions(-)

diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
index 19c712307d28..d5bda093c8e8 100644
--- a/man/intel_gpu_top.rst
+++ b/man/intel_gpu_top.rst
@@ -7,9 +7,9 @@ Display a top-like summary of Intel GPU usage
 ---------------------------------------------
 .. include:: defs.rst
 :Author: IGT Developers <igt-dev@lists.freedesktop.org>
-:Date: 2018-04-04
+:Date: 2019-02-08
 :Version: |PACKAGE_STRING|
-:Copyright: 2009,2011,2012,2016,2018 Intel Corporation
+:Copyright: 2009,2011,2012,2016,2018,2019 Intel Corporation
 :Manual section: |MANUAL_SECTION|
 :Manual group: |MANUAL_GROUP|
 
@@ -31,6 +31,11 @@ OPTIONS
 -s <ms>
     Refresh period in milliseconds.
 
+-l
+    List text data to standard out.
+
+-J
+    Output JSON formatted data to standard output.
 -h
     Show help text.
 
diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
index b923c3cfbe97..900979eea7a1 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2007-2018 Intel Corporation
+ * Copyright © 2007-2019 Intel Corporation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -19,10 +19,6 @@
  * 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.
- *
- * Authors:
- *    Eric Anholt <eric@anholt.net>
- *    Eugeni Dodonov <eugeni.dodonov@intel.com>
  */
 
 #include <stdio.h>
@@ -41,6 +37,8 @@
 #include <errno.h>
 #include <math.h>
 #include <locale.h>
+#include <limits.h>
+#include <signal.h>
 
 #include "igt_perf.h"
 
@@ -58,7 +56,8 @@ struct pmu_counter {
 
 struct engine {
 	const char *name;
-	const char *display_name;
+	char *display_name;
+	char *short_name;
 
 	unsigned int class;
 	unsigned int instance;
@@ -142,6 +141,22 @@ static const char *class_display_name(unsigned int class)
 	}
 }
 
+static const char *class_short_name(unsigned int class)
+{
+	switch (class) {
+	case I915_ENGINE_CLASS_RENDER:
+		return "RCS";
+	case I915_ENGINE_CLASS_COPY:
+		return "BCS";
+	case I915_ENGINE_CLASS_VIDEO:
+		return "VCS";
+	case I915_ENGINE_CLASS_VIDEO_ENHANCE:
+		return "VECS";
+	default:
+		return "UNKN";
+	}
+}
+
 static int engine_cmp(const void *__a, const void *__b)
 {
 	const struct engine *a = (struct engine *)__a;
@@ -220,17 +235,18 @@ static struct engines *discover_engines(void)
 				    I915_PMU_SAMPLE_BITS) &
 				    ((1 << I915_PMU_SAMPLE_INSTANCE_BITS) - 1);
 
-		ret = snprintf(buf, sizeof(buf), "%s/%u",
+		ret = asprintf(&engine->display_name, "%s/%u",
 			       class_display_name(engine->class),
 			       engine->instance);
-		if (ret < 0 || ret == sizeof(buf)) {
-			ret = ENOBUFS;
+		if (!engine->display_name) {
+			ret = errno;
 			break;
 		}
-		ret = 0;
 
-		engine->display_name = strdup(buf);
-		if (!engine->display_name) {
+		ret = asprintf(&engine->short_name, "%s/%u",
+			       class_short_name(engine->class),
+			       engine->instance);
+		if (!engine->short_name) {
 			ret = errno;
 			break;
 		}
@@ -242,6 +258,8 @@ static struct engines *discover_engines(void)
 			ret = errno;
 			break;
 		}
+
+		ret = 0;
 	}
 
 	if (ret) {
@@ -551,7 +569,7 @@ static uint64_t pmu_read_multi(int fd, unsigned int num, uint64_t *val)
 	return buf[1];
 }
 
-static double __pmu_calc(struct pmu_pair *p, double d, double t, double s)
+static double pmu_calc(struct pmu_pair *p, double d, double t, double s)
 {
 	double v;
 
@@ -576,30 +594,6 @@ static void fill_str(char *buf, unsigned int bufsz, char c, unsigned int num)
 	*buf = 0;
 }
 
-static void pmu_calc(struct pmu_counter *cnt,
-		     char *buf, unsigned int bufsz,
-		     unsigned int width, unsigned width_dec,
-		     double d, double t, double s)
-{
-	double val;
-	int len;
-
-	assert(bufsz >= (width + width_dec + 1));
-
-	if (!cnt->present) {
-		fill_str(buf, bufsz, '-', width + width_dec);
-		return;
-	}
-
-	val = __pmu_calc(&cnt->val, d, t, s);
-
-	len = snprintf(buf, bufsz, "%*.*f", width + width_dec, width_dec, val);
-	if (len < 0 || len == bufsz) {
-		fill_str(buf, bufsz, 'X', width + width_dec);
-		return;
-	}
-}
-
 static uint64_t __pmu_read_single(int fd, uint64_t *ts)
 {
 	uint64_t data[2] = { };
@@ -697,11 +691,559 @@ usage(const char *appname)
 		"\n"
 		"\tThe following parameters are optional:\n\n"
 		"\t[-s <ms>]       Refresh period in milliseconds (default %ums).\n"
+		"\t[-l]            List data to standard out.\n"
+		"\t[-J]            JSON data to standard out.\n"
 		"\t[-h]            Show this help text.\n"
 		"\n",
 		appname, DEFAULT_PERIOD_MS);
 }
 
+static enum {
+	INTERACTIVE,
+	STDOUT,
+	JSON
+} output_mode;
+
+struct cnt_item {
+	struct pmu_counter *pmu;
+	unsigned int fmt_d;
+	unsigned int fmt_dd;
+	double d;
+	double t;
+	double s;
+	const char *name;
+	const char *unit;
+
+	/* Internal fields. */
+	char buf[16];
+};
+
+struct cnt_group {
+	const char *name;
+	const char *display_name;
+	struct cnt_item *items;
+};
+
+static unsigned int json_indent_level;
+
+static const char *json_indent[] = {
+	"",
+	"\t",
+	"\t\t",
+	"\t\t\t",
+	"\t\t\t\t",
+	"\t\t\t\t\t",
+};
+
+#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
+
+static unsigned int json_prev_struct_members;
+static unsigned int json_struct_members;
+
+static void
+json_open_struct(const char *name)
+{
+	assert(json_indent_level < ARRAY_SIZE(json_indent));
+
+	json_prev_struct_members = json_struct_members;
+	json_struct_members = 0;
+
+	if (name)
+		printf("%s%s\"%s\": {\n",
+		       json_prev_struct_members ? ",\n" : "",
+		       json_indent[json_indent_level],
+		       name);
+	else
+		printf("%s\n%s{\n",
+		       json_prev_struct_members ? "," : "",
+		       json_indent[json_indent_level]);
+
+	json_indent_level++;
+}
+
+static void
+json_close_struct(void)
+{
+	assert(json_indent_level > 0);
+
+	printf("\n%s}", json_indent[--json_indent_level]);
+
+	if (json_indent_level == 0)
+		fflush(stdout);
+}
+
+static unsigned int
+json_add_member(const struct cnt_group *parent, struct cnt_item *item,
+		unsigned int headers)
+{
+	assert(json_indent_level < ARRAY_SIZE(json_indent));
+
+	printf("%s%s\"%s\": ",
+		json_struct_members ? ",\n" : "",
+		json_indent[json_indent_level], item->name);
+
+	json_struct_members++;
+
+	if (!strcmp(item->name, "unit"))
+		printf("\"%s\"", item->unit);
+	else
+		printf("%f",
+		       pmu_calc(&item->pmu->val, item->d, item->t, item->s));
+
+	return 1;
+}
+
+static unsigned int stdout_level;
+
+#define STDOUT_HEADER_REPEAT 20
+static unsigned int stdout_lines = STDOUT_HEADER_REPEAT;
+
+static void
+stdout_open_struct(const char *name)
+{
+	stdout_level++;
+	assert(stdout_level > 0);
+}
+
+static void
+stdout_close_struct(void)
+{
+	assert(stdout_level > 0);
+	if (--stdout_level == 0) {
+		stdout_lines++;
+		printf("\n");
+		fflush(stdout);
+	}
+}
+
+static unsigned int
+stdout_add_member(const struct cnt_group *parent, struct cnt_item *item,
+		  unsigned int headers)
+{
+	unsigned int fmt_tot = item->fmt_d + (item->fmt_dd ? 1 : 0);
+	char buf[fmt_tot + 1];
+	double val;
+	int len;
+
+	if (!item->pmu)
+		return 0;
+	else if (!item->pmu->present)
+		return 0;
+
+	if (headers == 1) {
+		unsigned int grp_tot = 0;
+		struct cnt_item *it;
+
+		if (item != parent->items)
+			return 0;
+
+		for (it = parent->items; it->pmu; it++) {
+			if (!it->pmu->present)
+				continue;
+
+			grp_tot += 1 + it->fmt_d + (it->fmt_dd ? 1 : 0);
+		}
+
+		printf("%*s ", grp_tot - 1, parent->display_name);
+		return 0;
+	} else if (headers == 2) {
+		printf("%*s ", fmt_tot, item->unit ?: item->name);
+		return 0;
+	}
+
+	val = pmu_calc(&item->pmu->val, item->d, item->t, item->s);
+
+	len = snprintf(buf, sizeof(buf), "%*.*f", fmt_tot, item->fmt_dd, val);
+	if (len < 0 || len == sizeof(buf))
+		fill_str(buf, sizeof(buf), 'X', fmt_tot);
+
+	len = printf("%s ", buf);
+
+	return len > 0 ? len : 0;
+}
+
+static void
+term_open_struct(const char *name)
+{
+}
+
+static void
+term_close_struct(void)
+{
+}
+
+static unsigned int
+term_add_member(const struct cnt_group *parent, struct cnt_item *item,
+		unsigned int headers)
+{
+	unsigned int fmt_tot = item->fmt_d + (item->fmt_dd ? 1 : 0);
+	double val;
+	int len;
+
+	if (!item->pmu)
+		return 0;
+
+	assert(fmt_tot <= sizeof(item->buf));
+
+	if (!item->pmu->present) {
+		fill_str(item->buf, sizeof(item->buf), '-', fmt_tot);
+		return 1;
+	}
+
+	val = pmu_calc(&item->pmu->val, item->d, item->t, item->s);
+	len = snprintf(item->buf, sizeof(item->buf),
+		       "%*.*f",
+		       fmt_tot, item->fmt_dd, val);
+
+	if (len < 0 || len == sizeof(item->buf))
+		fill_str(item->buf, sizeof(item->buf), 'X', fmt_tot);
+
+	return 1;
+}
+
+struct print_operations {
+	void (*open_struct)(const char *name);
+	void (*close_struct)(void);
+	unsigned int (*add_member)(const struct cnt_group *parent,
+				   struct cnt_item *item,
+				   unsigned int headers);
+	bool (*print_group)(struct cnt_group *group, unsigned int headers);
+};
+
+static const struct print_operations *pops;
+
+static unsigned int
+present_in_group(const struct cnt_group *grp)
+{
+	unsigned int present = 0;
+	struct cnt_item *item;
+
+	for (item = grp->items; item->name; item++) {
+		if (item->pmu && item->pmu->present)
+			present++;
+	}
+
+	return present;
+}
+
+static bool
+print_group(struct cnt_group *grp, unsigned int headers)
+{
+	unsigned int consumed = 0;
+	struct cnt_item *item;
+
+	if (!present_in_group(grp))
+		return false;
+
+	pops->open_struct(grp->name);
+
+	for (item = grp->items; item->name; item++)
+		consumed += pops->add_member(grp, item, headers);
+
+	pops->close_struct();
+
+	return consumed;
+}
+
+static bool
+term_print_group(struct cnt_group *grp, unsigned int headers)
+{
+	unsigned int consumed = 0;
+	struct cnt_item *item;
+
+	pops->open_struct(grp->name);
+
+	for (item = grp->items; item->name; item++)
+		consumed += pops->add_member(grp, item, headers);
+
+	pops->close_struct();
+
+	return consumed;
+}
+
+static const struct print_operations json_pops = {
+	.open_struct = json_open_struct,
+	.close_struct = json_close_struct,
+	.add_member = json_add_member,
+	.print_group = print_group,
+};
+
+static const struct print_operations stdout_pops = {
+	.open_struct = stdout_open_struct,
+	.close_struct = stdout_close_struct,
+	.add_member = stdout_add_member,
+	.print_group = print_group,
+};
+
+static const struct print_operations term_pops = {
+	.open_struct = term_open_struct,
+	.close_struct = term_close_struct,
+	.add_member = term_add_member,
+	.print_group = term_print_group,
+};
+
+static bool print_groups(struct cnt_group **groups)
+{
+	unsigned int headers = stdout_lines % STDOUT_HEADER_REPEAT + 1;
+	bool print_data = true;
+
+	if (output_mode == STDOUT && (headers == 1 || headers == 2)) {
+		for (struct cnt_group **grp = groups; *grp; grp++)
+			print_data = pops->print_group(*grp, headers);
+	}
+
+	for (struct cnt_group **grp = groups; print_data && *grp; grp++)
+		pops->print_group(*grp, false);
+
+	return print_data;
+}
+
+static int
+print_header(struct engines *engines, double t,
+	     int lines, int con_w, int con_h, bool *consumed)
+{
+	struct pmu_counter fake_pmu = {
+		.present = true,
+		.val.cur = 1,
+	};
+	struct cnt_item period_items[] = {
+		{ &fake_pmu, 0, 0, 1.0, 1.0, t * 1e3, "duration" },
+		{ NULL, 0, 0, 0.0, 0.0, 0.0, "unit", "ms" },
+		{ },
+	};
+	struct cnt_group period_group = {
+		.name = "period",
+		.items = period_items,
+	};
+	struct cnt_item freq_items[] = {
+		{ &engines->freq_req, 4, 0, 1.0, t, 1, "requested", "req" },
+		{ &engines->freq_act, 4, 0, 1.0, t, 1, "actual", "act" },
+		{ NULL, 0, 0, 0.0, 0.0, 0.0, "unit", "MHz" },
+		{ },
+	};
+	struct cnt_group freq_group = {
+		.name = "frequency",
+		.display_name = "Freq MHz",
+		.items = freq_items,
+	};
+	struct cnt_item irq_items[] = {
+		{ &engines->irq, 8, 0, 1.0, t, 1, "count", "/s" },
+		{ NULL, 0, 0, 0.0, 0.0, 0.0, "unit", "irq/s" },
+		{ },
+	};
+	struct cnt_group irq_group = {
+		.name = "interrupts",
+		.display_name = "IRQ",
+		.items = irq_items,
+	};
+	struct cnt_item rc6_items[] = {
+		{ &engines->rc6, 3, 0, 1e9, t, 100, "value", "%" },
+		{ NULL, 0, 0, 0.0, 0.0, 0.0, "unit", "%" },
+		{ },
+	};
+	struct cnt_group rc6_group = {
+		.name = "rc6",
+		.display_name = "RC6",
+		.items = rc6_items,
+	};
+	struct cnt_item power_items[] = {
+		{ &engines->rapl, 4, 2, 1.0, t, engines->rapl_scale, "value",
+		  "W" },
+		{ NULL, 0, 0, 0.0, 0.0, 0.0, "unit", "W" },
+		{ },
+	};
+	struct cnt_group power_group = {
+		.name = "power",
+		.display_name = "Power",
+		.items = power_items,
+	};
+	struct cnt_group *groups[] = {
+		&period_group,
+		&freq_group,
+		&irq_group,
+		&rc6_group,
+		&power_group,
+		NULL
+	};
+
+	if (output_mode != JSON)
+		memmove(&groups[0], &groups[1],
+			sizeof(groups) - sizeof(groups[0]));
+
+	pops->open_struct(NULL);
+
+	*consumed = print_groups(groups);
+
+	if (output_mode == INTERACTIVE) {
+		printf("\033[H\033[J");
+
+		if (lines++ < con_h)
+			printf("intel-gpu-top - %s/%s MHz;  %s%% RC6; %s %s; %s irqs/s\n",
+			       freq_items[1].buf, freq_items[0].buf,
+			       rc6_items[0].buf, power_items[0].buf,
+			       engines->rapl_unit,
+			       irq_items[0].buf);
+
+		if (lines++ < con_h)
+			printf("\n");
+	}
+
+	return lines;
+}
+
+static int
+print_imc(struct engines *engines, double t, int lines, int con_w, int con_h)
+{
+	struct cnt_item imc_items[] = {
+		{ &engines->imc_reads, 6, 0, 1.0, t, engines->imc_reads_scale,
+		  "reads", "rd" },
+		{ &engines->imc_writes, 6, 0, 1.0, t, engines->imc_writes_scale,
+		  "writes", "wr" },
+		{ NULL, 0, 0, 0.0, 0.0, 0.0, "unit" },
+		{ },
+	};
+	struct cnt_group imc_group = {
+		.name = "imc-bandwidth",
+		.items = imc_items,
+	};
+	struct cnt_group *groups[] = {
+		&imc_group,
+		NULL
+	};
+	int ret;
+
+	ret = asprintf((char **)&imc_group.display_name, "IMC %s/s",
+			engines->imc_reads_unit);
+	assert(ret >= 0);
+
+	ret = asprintf((char **)&imc_items[2].unit, "%s/s",
+			engines->imc_reads_unit);
+	assert(ret >= 0);
+
+	print_groups(groups);
+
+	free((void *)imc_group.display_name);
+	free((void *)imc_items[2].unit);
+
+	if (output_mode == INTERACTIVE) {
+		if (lines++ < con_h)
+			printf("      IMC reads:   %s %s/s\n",
+			       imc_items[0].buf, engines->imc_reads_unit);
+
+		if (lines++ < con_h)
+			printf("     IMC writes:   %s %s/s\n",
+			       imc_items[1].buf, engines->imc_writes_unit);
+
+		if (lines++ < con_h)
+			printf("\n");
+	}
+
+	return lines;
+}
+
+static int
+print_engines_header(struct engines *engines, double t,
+		     int lines, int con_w, int con_h)
+{
+	for (unsigned int i = 0;
+	     i < engines->num_engines && lines < con_h;
+	     i++) {
+		struct engine *engine = engine_ptr(engines, i);
+
+		if (!engine->num_counters)
+			continue;
+
+		pops->open_struct("engines");
+
+		if (output_mode == INTERACTIVE) {
+			const char *a = "          ENGINE      BUSY ";
+			const char *b = " MI_SEMA MI_WAIT";
+
+			printf("\033[7m%s%*s%s\033[0m\n",
+			       a, (int)(con_w - 1 - strlen(a) - strlen(b)),
+			       " ", b);
+
+			lines++;
+		}
+
+		break;
+	}
+
+	return lines;
+}
+
+static int
+print_engine(struct engines *engines, unsigned int i, double t,
+	     int lines, int con_w, int con_h)
+{
+	struct engine *engine = engine_ptr(engines, i);
+	struct cnt_item engine_items[] = {
+		{ &engine->busy, 6, 2, 1e9, t, 100, "busy", "%" },
+		{ &engine->sema, 3, 0, 1e9, t, 100, "sema", "se" },
+		{ &engine->wait, 3, 0, 1e9, t, 100, "wait", "wa" },
+		{ NULL, 0, 0, 0.0, 0.0, 0.0, "unit", "%" },
+		{ },
+	};
+	struct cnt_group engine_group = {
+		.name = engine->display_name,
+		.display_name = engine->short_name,
+		.items = engine_items,
+	};
+	struct cnt_group *groups[] = {
+		&engine_group,
+		NULL
+	};
+
+	if (!engine->num_counters)
+		return lines;
+
+	print_groups(groups);
+
+	if (output_mode == INTERACTIVE) {
+		unsigned int max_w = con_w - 1;
+		unsigned int len;
+		char buf[128];
+		double val;
+
+		len = snprintf(buf, sizeof(buf), "    %s%%    %s%%",
+			       engine_items[1].buf, engine_items[2].buf);
+
+		len += printf("%16s %s%% ",
+			      engine->display_name, engine_items[0].buf);
+
+		val = pmu_calc(&engine->busy.val, 1e9, t, 100);
+		print_percentage_bar(val, max_w - len);
+
+		printf("%s\n", buf);
+
+		lines++;
+	}
+
+	return lines;
+}
+
+static int
+print_engines_footer(struct engines *engines, double t,
+		     int lines, int con_w, int con_h)
+{
+	pops->close_struct();
+	pops->close_struct();
+
+	if (output_mode == INTERACTIVE) {
+		if (lines++ < con_h)
+			printf("\n");
+	}
+
+	return lines;
+}
+
+static bool stop_top;
+
+static void sigint_handler(int  sig)
+{
+	stop_top = true;
+}
+
 int main(int argc, char **argv)
 {
 	unsigned int period_us = DEFAULT_PERIOD_MS * 1000;
@@ -711,11 +1253,17 @@ int main(int argc, char **argv)
 	int ret, ch;
 
 	/* Parse options */
-	while ((ch = getopt(argc, argv, "s:h")) != -1) {
+	while ((ch = getopt(argc, argv, "s:Jlh")) != -1) {
 		switch (ch) {
 		case 's':
 			period_us = atoi(optarg) * 1000;
 			break;
+		case 'J':
+			output_mode = JSON;
+			break;
+		case 'l':
+			output_mode = STDOUT;
+			break;
 		case 'h':
 			usage(argv[0]);
 			exit(0);
@@ -726,6 +1274,31 @@ int main(int argc, char **argv)
 		}
 	}
 
+	if (output_mode == INTERACTIVE && isatty(1) != 1)
+		output_mode = STDOUT;
+
+	if (output_mode != INTERACTIVE) {
+		sighandler_t sig = signal(SIGINT, sigint_handler);
+
+		if (sig == SIG_ERR)
+			fprintf(stderr, "Failed to install signal handler!\n");
+	}
+
+	switch (output_mode) {
+	case INTERACTIVE:
+		pops = &term_pops;
+		break;
+	case STDOUT:
+		pops = &stdout_pops;
+		break;
+	case JSON:
+		pops = &json_pops;
+		break;
+	default:
+		assert(0);
+		break;
+	};
+
 	engines = discover_engines();
 	if (!engines) {
 		fprintf(stderr,
@@ -743,21 +1316,16 @@ int main(int argc, char **argv)
 
 	pmu_sample(engines);
 
-	for (;;) {
-		double t;
-#define BUFSZ 16
-		char freq[BUFSZ];
-		char fact[BUFSZ];
-		char irq[BUFSZ];
-		char rc6[BUFSZ];
-		char power[BUFSZ];
-		char reads[BUFSZ];
-		char writes[BUFSZ];
-		struct winsize ws;
+	while (!stop_top) {
+		bool consumed = false;
 		int lines = 0;
+		struct winsize ws;
+		double t;
 
 		/* Update terminal size. */
-		if (ioctl(0, TIOCGWINSZ, &ws) != -1) {
+		if (output_mode != INTERACTIVE) {
+			con_w = con_h = INT_MAX;
+		} else if (ioctl(0, TIOCGWINSZ, &ws) != -1) {
 			con_w = ws.ws_col;
 			con_h = ws.ws_row;
 		}
@@ -765,87 +1333,32 @@ int main(int argc, char **argv)
 		pmu_sample(engines);
 		t = (double)(engines->ts.cur - engines->ts.prev) / 1e9;
 
-		printf("\033[H\033[J");
-
-		pmu_calc(&engines->freq_req, freq, BUFSZ, 4, 0, 1.0, t, 1);
-		pmu_calc(&engines->freq_act, fact, BUFSZ, 4, 0, 1.0, t, 1);
-		pmu_calc(&engines->irq, irq, BUFSZ, 8, 0, 1.0, t, 1);
-		pmu_calc(&engines->rc6, rc6, BUFSZ, 3, 0, 1e9, t, 100);
-		pmu_calc(&engines->rapl, power, BUFSZ, 4, 2, 1.0, t,
-			 engines->rapl_scale);
-		pmu_calc(&engines->imc_reads, reads, BUFSZ, 6, 0, 1.0, t,
-			 engines->imc_reads_scale);
-		pmu_calc(&engines->imc_writes, writes, BUFSZ, 6, 0, 1.0, t,
-			 engines->imc_writes_scale);
-
-		if (lines++ < con_h)
-			printf("intel-gpu-top - %s/%s MHz;  %s%% RC6; %s %s; %s irqs/s\n",
-			       fact, freq, rc6, power, engines->rapl_unit, irq);
-
-		if (lines++ < con_h)
-			printf("\n");
-
-		if (engines->imc_fd) {
-			if (lines++ < con_h)
-				printf("      IMC reads:   %s %s/s\n",
-				       reads, engines->imc_reads_unit);
-
-			if (lines++ < con_h)
-				printf("     IMC writes:   %s %s/s\n",
-				       writes, engines->imc_writes_unit);
-
-			if (++lines < con_h)
-				printf("\n");
-		}
-
-		for (i = 0; i < engines->num_engines; i++) {
-			struct engine *engine = engine_ptr(engines, i);
-
-			if (engine->num_counters && lines < con_h) {
-				const char *a = "          ENGINE      BUSY ";
-				const char *b = " MI_SEMA MI_WAIT";
-
-				printf("\033[7m%s%*s%s\033[0m\n",
-				       a,
-				       (int)(con_w - 1 - strlen(a) - strlen(b)),
-				       " ", b);
-				lines++;
-				break;
-			}
-		}
-
-		for (i = 0; i < engines->num_engines && lines < con_h; i++) {
-			struct engine *engine = engine_ptr(engines, i);
-			unsigned int max_w = con_w - 1;
-			unsigned int len;
-			char sema[BUFSZ];
-			char wait[BUFSZ];
-			char busy[BUFSZ];
-			char buf[128];
-			double val;
-
-			if (!engine->num_counters)
-				continue;
+		if (stop_top)
+			break;
 
-			pmu_calc(&engine->sema, sema, BUFSZ, 3, 0, 1e9, t, 100);
-			pmu_calc(&engine->wait, wait, BUFSZ, 3, 0, 1e9, t, 100);
-			len = snprintf(buf, sizeof(buf), "    %s%%    %s%%",
-				       sema, wait);
+		while (!consumed) {
+			lines = print_header(engines, t, lines, con_w, con_h,
+					     &consumed);
 
-			pmu_calc(&engine->busy, busy, BUFSZ, 6, 2, 1e9, t,
-				 100);
-			len += printf("%16s %s%% ", engine->display_name, busy);
+			if (engines->imc_fd)
+				lines = print_imc(engines, t, lines, con_w,
+						  con_h);
 
-			val = __pmu_calc(&engine->busy.val, 1e9, t, 100);
-			print_percentage_bar(val, max_w - len);
+			lines = print_engines_header(engines, t, lines, con_w,
+						     con_h);
 
-			printf("%s\n", buf);
+			for (i = 0;
+			     i < engines->num_engines && lines < con_h;
+			     i++)
+				lines = print_engine(engines, i, t, lines,
+						     con_w, con_h);
 
-			lines++;
+			lines = print_engines_footer(engines, t, lines, con_w,
+						     con_h);
 		}
 
-		if (lines++ < con_h)
-			printf("\n");
+		if (stop_top)
+			break;
 
 		usleep(period_us);
 	}
-- 
2.19.1

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [igt-dev] [IGT 2/2] tools/intel_gpu_top: Add file output capability
  2019-02-11 11:45 [igt-dev] [IGT 1/2] tools/intel_gpu_top: Add support for stdout logging Tvrtko Ursulin
@ 2019-02-11 11:45 ` Tvrtko Ursulin
  2019-02-11 12:12 ` [igt-dev] ✓ Fi.CI.BAT: success for series starting with [1/2] tools/intel_gpu_top: Add support for stdout logging Patchwork
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Tvrtko Ursulin @ 2019-02-11 11:45 UTC (permalink / raw)
  To: igt-dev; +Cc: Intel-gfx, Eero Tamminen, 3.14pi, Tvrtko Ursulin

From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

A new -o command switch enables logging to a file.

v2:
 * Support "-o -" for explicit stdout selection. (Chris Wilson)

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
References: https://bugs.freedesktop.org/show_bug.cgi?id=108689
Cc: Eero Tamminen <eero.t.tamminen@intel.com>
Cc: 3.14pi@ukr.net
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
---
 man/intel_gpu_top.rst | 19 ++++++++-----
 tools/intel_gpu_top.c | 63 ++++++++++++++++++++++++++++---------------
 2 files changed, 53 insertions(+), 29 deletions(-)

diff --git a/man/intel_gpu_top.rst b/man/intel_gpu_top.rst
index d5bda093c8e8..d487baca0c63 100644
--- a/man/intel_gpu_top.rst
+++ b/man/intel_gpu_top.rst
@@ -28,16 +28,21 @@ The tool gathers data using perf performance counters (PMU) exposed by i915 and
 OPTIONS
 =======
 
--s <ms>
-    Refresh period in milliseconds.
+-h
+    Show help text.
+
+-J
+    Output JSON formatted data.
 
 -l
-    List text data to standard out.
+    List plain text data.
 
--J
-    Output JSON formatted data to standard output.
--h
-    Show help text.
+-o <file path | ->
+    Output to the specified file instead of standard output.
+    '-' can also be specified to explicitly select standard output.
+
+-s <ms>
+    Refresh period in milliseconds.
 
 LIMITATIONS
 ===========
diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c
index 900979eea7a1..60505a606bfc 100644
--- a/tools/intel_gpu_top.c
+++ b/tools/intel_gpu_top.c
@@ -690,10 +690,11 @@ usage(const char *appname)
 		"Usage: %s [parameters]\n"
 		"\n"
 		"\tThe following parameters are optional:\n\n"
-		"\t[-s <ms>]       Refresh period in milliseconds (default %ums).\n"
-		"\t[-l]            List data to standard out.\n"
-		"\t[-J]            JSON data to standard out.\n"
 		"\t[-h]            Show this help text.\n"
+		"\t[-J]            Output JSON formatted data.\n"
+		"\t[-l]            List plain text data.\n"
+		"\t[-o <file|->]   Output to specified file or '-' for standard out.\n"
+		"\t[-s <ms>]       Refresh period in milliseconds (default %ums).\n"
 		"\n",
 		appname, DEFAULT_PERIOD_MS);
 }
@@ -740,6 +741,8 @@ static const char *json_indent[] = {
 static unsigned int json_prev_struct_members;
 static unsigned int json_struct_members;
 
+FILE *out;
+
 static void
 json_open_struct(const char *name)
 {
@@ -749,14 +752,14 @@ json_open_struct(const char *name)
 	json_struct_members = 0;
 
 	if (name)
-		printf("%s%s\"%s\": {\n",
-		       json_prev_struct_members ? ",\n" : "",
-		       json_indent[json_indent_level],
-		       name);
+		fprintf(out, "%s%s\"%s\": {\n",
+			json_prev_struct_members ? ",\n" : "",
+			json_indent[json_indent_level],
+			name);
 	else
-		printf("%s\n%s{\n",
-		       json_prev_struct_members ? "," : "",
-		       json_indent[json_indent_level]);
+		fprintf(out, "%s\n%s{\n",
+			json_prev_struct_members ? "," : "",
+			json_indent[json_indent_level]);
 
 	json_indent_level++;
 }
@@ -766,7 +769,7 @@ json_close_struct(void)
 {
 	assert(json_indent_level > 0);
 
-	printf("\n%s}", json_indent[--json_indent_level]);
+	fprintf(out, "\n%s}", json_indent[--json_indent_level]);
 
 	if (json_indent_level == 0)
 		fflush(stdout);
@@ -778,17 +781,17 @@ json_add_member(const struct cnt_group *parent, struct cnt_item *item,
 {
 	assert(json_indent_level < ARRAY_SIZE(json_indent));
 
-	printf("%s%s\"%s\": ",
+	fprintf(out, "%s%s\"%s\": ",
 		json_struct_members ? ",\n" : "",
 		json_indent[json_indent_level], item->name);
 
 	json_struct_members++;
 
 	if (!strcmp(item->name, "unit"))
-		printf("\"%s\"", item->unit);
+		fprintf(out, "\"%s\"", item->unit);
 	else
-		printf("%f",
-		       pmu_calc(&item->pmu->val, item->d, item->t, item->s));
+		fprintf(out, "%f",
+			pmu_calc(&item->pmu->val, item->d, item->t, item->s));
 
 	return 1;
 }
@@ -811,8 +814,8 @@ stdout_close_struct(void)
 	assert(stdout_level > 0);
 	if (--stdout_level == 0) {
 		stdout_lines++;
-		printf("\n");
-		fflush(stdout);
+		fputs("\n", out);
+		fflush(out);
 	}
 }
 
@@ -844,10 +847,10 @@ stdout_add_member(const struct cnt_group *parent, struct cnt_item *item,
 			grp_tot += 1 + it->fmt_d + (it->fmt_dd ? 1 : 0);
 		}
 
-		printf("%*s ", grp_tot - 1, parent->display_name);
+		fprintf(out, "%*s ", grp_tot - 1, parent->display_name);
 		return 0;
 	} else if (headers == 2) {
-		printf("%*s ", fmt_tot, item->unit ?: item->name);
+		fprintf(out, "%*s ", fmt_tot, item->unit ?: item->name);
 		return 0;
 	}
 
@@ -857,7 +860,7 @@ stdout_add_member(const struct cnt_group *parent, struct cnt_item *item,
 	if (len < 0 || len == sizeof(buf))
 		fill_str(buf, sizeof(buf), 'X', fmt_tot);
 
-	len = printf("%s ", buf);
+	len = fprintf(out, "%s ", buf);
 
 	return len > 0 ? len : 0;
 }
@@ -1248,13 +1251,17 @@ int main(int argc, char **argv)
 {
 	unsigned int period_us = DEFAULT_PERIOD_MS * 1000;
 	int con_w = -1, con_h = -1;
+	char *output_path = NULL;
 	struct engines *engines;
 	unsigned int i;
 	int ret, ch;
 
 	/* Parse options */
-	while ((ch = getopt(argc, argv, "s:Jlh")) != -1) {
+	while ((ch = getopt(argc, argv, "o:s:Jlh")) != -1) {
 		switch (ch) {
+		case 'o':
+			output_path = optarg;
+			break;
 		case 's':
 			period_us = atoi(optarg) * 1000;
 			break;
@@ -1274,9 +1281,21 @@ int main(int argc, char **argv)
 		}
 	}
 
-	if (output_mode == INTERACTIVE && isatty(1) != 1)
+	if (output_mode == INTERACTIVE && (output_path || isatty(1) != 1))
 		output_mode = STDOUT;
 
+	if (output_path && strcmp(output_path, "-")) {
+		out = fopen(output_path, "w");
+
+		if (!out) {
+			fprintf(stderr, "Failed to open output file - '%s'!\n",
+				strerror(errno));
+			exit(1);
+		}
+	} else {
+		out = stdout;
+	}
+
 	if (output_mode != INTERACTIVE) {
 		sighandler_t sig = signal(SIGINT, sigint_handler);
 
-- 
2.19.1

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [igt-dev] ✓ Fi.CI.BAT: success for series starting with [1/2] tools/intel_gpu_top: Add support for stdout logging
  2019-02-11 11:45 [igt-dev] [IGT 1/2] tools/intel_gpu_top: Add support for stdout logging Tvrtko Ursulin
  2019-02-11 11:45 ` [igt-dev] [IGT 2/2] tools/intel_gpu_top: Add file output capability Tvrtko Ursulin
@ 2019-02-11 12:12 ` Patchwork
  2019-02-11 12:21 ` [igt-dev] [IGT 1/2] " Chris Wilson
  2019-02-11 14:09 ` [igt-dev] ✓ Fi.CI.IGT: success for series starting with [1/2] " Patchwork
  3 siblings, 0 replies; 7+ messages in thread
From: Patchwork @ 2019-02-11 12:12 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: igt-dev

== Series Details ==

Series: series starting with [1/2] tools/intel_gpu_top: Add support for stdout logging
URL   : https://patchwork.freedesktop.org/series/56490/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_5586 -> IGTPW_2371
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/56490/revisions/1/mbox/

Known issues
------------

  Here are the changes found in IGTPW_2371 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@kms_busy@basic-flip-a:
    - fi-gdg-551:         PASS -> FAIL [fdo#103182]

  * igt@kms_chamelium@hdmi-hpd-fast:
    - fi-kbl-7500u:       PASS -> FAIL [fdo#109485]

  * igt@kms_pipe_crc_basic@suspend-read-crc-pipe-b:
    - fi-byt-clapper:     PASS -> FAIL [fdo#103191] / [fdo#107362]

  
#### Possible fixes ####

  * igt@gem_exec_suspend@basic-s4-devices:
    - fi-blb-e6850:       INCOMPLETE [fdo#107718] -> PASS

  * igt@kms_chamelium@dp-edid-read:
    - fi-kbl-7500u:       FAIL -> PASS

  * igt@kms_pipe_crc_basic@hang-read-crc-pipe-a:
    - fi-byt-clapper:     FAIL [fdo#103191] / [fdo#107362] -> PASS

  * igt@prime_vgem@basic-fence-flip:
    - fi-gdg-551:         FAIL [fdo#103182] -> PASS

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#103182]: https://bugs.freedesktop.org/show_bug.cgi?id=103182
  [fdo#103191]: https://bugs.freedesktop.org/show_bug.cgi?id=103191
  [fdo#107362]: https://bugs.freedesktop.org/show_bug.cgi?id=107362
  [fdo#107718]: https://bugs.freedesktop.org/show_bug.cgi?id=107718
  [fdo#108569]: https://bugs.freedesktop.org/show_bug.cgi?id=108569
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
  [fdo#109485]: https://bugs.freedesktop.org/show_bug.cgi?id=109485


Participating hosts (47 -> 42)
------------------------------

  Missing    (5): fi-ilk-m540 fi-hsw-4200u fi-bsw-cyan fi-ctg-p8600 fi-icl-y 


Build changes
-------------

    * IGT: IGT_4816 -> IGTPW_2371

  CI_DRM_5586: e54b6a76e1a6d0e4ba8b56f149673ea9907b2c59 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_2371: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2371/
  IGT_4816: f62577c85c9ef0539d468d6fad105b706a15139c @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2371/
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [igt-dev] [IGT 1/2] tools/intel_gpu_top: Add support for stdout logging
  2019-02-11 11:45 [igt-dev] [IGT 1/2] tools/intel_gpu_top: Add support for stdout logging Tvrtko Ursulin
  2019-02-11 11:45 ` [igt-dev] [IGT 2/2] tools/intel_gpu_top: Add file output capability Tvrtko Ursulin
  2019-02-11 12:12 ` [igt-dev] ✓ Fi.CI.BAT: success for series starting with [1/2] tools/intel_gpu_top: Add support for stdout logging Patchwork
@ 2019-02-11 12:21 ` Chris Wilson
  2019-02-11 17:08   ` [Intel-gfx] " Tvrtko Ursulin
  2019-02-11 14:09 ` [igt-dev] ✓ Fi.CI.IGT: success for series starting with [1/2] " Patchwork
  3 siblings, 1 reply; 7+ messages in thread
From: Chris Wilson @ 2019-02-11 12:21 UTC (permalink / raw)
  To: Tvrtko Ursulin, igt-dev; +Cc: Intel-gfx, Eero Tamminen, 3.14pi, Tvrtko Ursulin

Quoting Tvrtko Ursulin (2019-02-11 11:45:22)
> +static enum {
> +       INTERACTIVE,
> +       STDOUT,
> +       JSON
> +} output_mode;
> +
> +struct cnt_item {
> +       struct pmu_counter *pmu;

/* "%*.*f", fmt_d, fmt_dd, X */

I tried fmt_d == fmt_width and fmt_dd == fmt_decimals

It's called field width and precision in the manpage, so
maybe fmt_width and fmt_precision.

Having figured that out, the use makes sense.

> +       unsigned int fmt_d;
> +       unsigned int fmt_dd;
> +       double d;
> +       double t;
> +       double s;
> +       const char *name;
> +       const char *unit;
> +
> +       /* Internal fields. */
> +       char buf[16];
> +};
> +
> +struct cnt_group {
> +       const char *name;
> +       const char *display_name;
> +       struct cnt_item *items;
> +};
> +
> +static unsigned int json_indent_level;
> +
> +static const char *json_indent[] = {
> +       "",
> +       "\t",
> +       "\t\t",
> +       "\t\t\t",
> +       "\t\t\t\t",
> +       "\t\t\t\t\t",
> +};
> +
> +#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
> +
> +static unsigned int json_prev_struct_members;
> +static unsigned int json_struct_members;
> +
> +static void
> +json_open_struct(const char *name)
> +{
> +       assert(json_indent_level < ARRAY_SIZE(json_indent));
> +
> +       json_prev_struct_members = json_struct_members;
> +       json_struct_members = 0;
> +
> +       if (name)
> +               printf("%s%s\"%s\": {\n",
> +                      json_prev_struct_members ? ",\n" : "",
> +                      json_indent[json_indent_level],

"%*s", json_indent_level, "\t\t\t\t\t"
didn't stick?

I could follow the flow, dug into a few of the details, and only have
some nits. One thing, could we feed in a perf record? I was thinking for
testing the various output modes with known data, but may also be useful
for replay.

Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [igt-dev] ✓ Fi.CI.IGT: success for series starting with [1/2] tools/intel_gpu_top: Add support for stdout logging
  2019-02-11 11:45 [igt-dev] [IGT 1/2] tools/intel_gpu_top: Add support for stdout logging Tvrtko Ursulin
                   ` (2 preceding siblings ...)
  2019-02-11 12:21 ` [igt-dev] [IGT 1/2] " Chris Wilson
@ 2019-02-11 14:09 ` Patchwork
  3 siblings, 0 replies; 7+ messages in thread
From: Patchwork @ 2019-02-11 14:09 UTC (permalink / raw)
  To: Tvrtko Ursulin; +Cc: igt-dev

== Series Details ==

Series: series starting with [1/2] tools/intel_gpu_top: Add support for stdout logging
URL   : https://patchwork.freedesktop.org/series/56490/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_5586_full -> IGTPW_2371_full
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/56490/revisions/1/mbox/

Known issues
------------

  Here are the changes found in IGTPW_2371_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_isolation@vecs0-s3:
    - shard-kbl:          PASS -> INCOMPLETE [fdo#103665]

  * igt@gem_exec_schedule@preempt-self-blt:
    - shard-apl:          PASS -> INCOMPLETE [fdo#103927]

  * igt@kms_atomic_transition@plane-all-modeset-transition-fencing:
    - shard-hsw:          PASS -> DMESG-WARN [fdo#102614] / [fdo#109225]

  * igt@kms_busy@extended-modeset-hang-newfb-render-a:
    - shard-hsw:          PASS -> DMESG-WARN [fdo#107956]

  * igt@kms_busy@extended-pageflip-modeset-hang-oldfb-render-b:
    - shard-snb:          PASS -> DMESG-WARN [fdo#107956]

  * igt@kms_ccs@pipe-b-crc-sprite-planes-basic:
    - shard-kbl:          PASS -> FAIL [fdo#107725] / [fdo#108145]

  * igt@kms_cursor_crc@cursor-128x128-sliding:
    - shard-kbl:          PASS -> FAIL [fdo#103232] +2

  * igt@kms_cursor_crc@cursor-256x256-random:
    - shard-apl:          PASS -> FAIL [fdo#103232] +3
    - shard-kbl:          NOTRUN -> FAIL [fdo#103232]

  * igt@kms_cursor_crc@cursor-64x64-suspend:
    - shard-apl:          PASS -> FAIL [fdo#103191] / [fdo#103232]
    - shard-kbl:          PASS -> FAIL [fdo#103191] / [fdo#103232]

  * igt@kms_cursor_crc@cursor-alpha-opaque:
    - shard-kbl:          PASS -> FAIL [fdo#109350]
    - shard-apl:          PASS -> FAIL [fdo#109350]

  * igt@kms_cursor_crc@cursor-size-change:
    - shard-glk:          PASS -> FAIL [fdo#103232]

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-pwrite:
    - shard-apl:          PASS -> FAIL [fdo#103167] +2

  * igt@kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-mmap-cpu:
    - shard-glk:          PASS -> FAIL [fdo#103167] +6

  * igt@kms_plane@plane-position-covered-pipe-c-planes:
    - shard-apl:          PASS -> FAIL [fdo#103166] +2

  * igt@kms_plane_alpha_blend@pipe-b-constant-alpha-max:
    - shard-glk:          PASS -> FAIL [fdo#108145] +2

  * igt@kms_plane_alpha_blend@pipe-c-alpha-opaque-fb:
    - shard-apl:          PASS -> FAIL [fdo#108145]

  * igt@kms_plane_multiple@atomic-pipe-b-tiling-x:
    - shard-glk:          PASS -> FAIL [fdo#103166] +4

  * igt@kms_setmode@basic:
    - shard-hsw:          PASS -> FAIL [fdo#99912]
    - shard-kbl:          PASS -> FAIL [fdo#99912]

  
#### Possible fixes ####

  * igt@gem_exec_blt@dumb-buf-max:
    - shard-glk:          DMESG-WARN [fdo#105763] / [fdo#106538] -> PASS

  * igt@i915_suspend@fence-restore-untiled:
    - shard-snb:          INCOMPLETE [fdo#105411] -> PASS

  * igt@kms_busy@extended-pageflip-modeset-hang-oldfb-render-c:
    - shard-apl:          DMESG-WARN [fdo#107956] -> PASS

  * igt@kms_cursor_crc@cursor-128x128-random:
    - shard-apl:          FAIL [fdo#103232] -> PASS +6
    - shard-kbl:          FAIL [fdo#103232] -> PASS +2

  * igt@kms_cursor_crc@cursor-128x128-suspend:
    - shard-apl:          FAIL [fdo#103191] / [fdo#103232] -> PASS +1
    - shard-kbl:          FAIL [fdo#103191] / [fdo#103232] -> PASS

  * igt@kms_cursor_legacy@cursor-vs-flip-atomic:
    - shard-hsw:          FAIL [fdo#103355] -> PASS

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-move:
    - shard-glk:          FAIL [fdo#103167] -> PASS +2

  * igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-onoff:
    - shard-apl:          FAIL [fdo#103167] -> PASS +2

  * igt@kms_plane_multiple@atomic-pipe-b-tiling-y:
    - shard-kbl:          FAIL [fdo#103166] -> PASS +1

  * igt@kms_plane_multiple@atomic-pipe-c-tiling-yf:
    - shard-apl:          FAIL [fdo#103166] -> PASS +6

  * igt@kms_setmode@basic:
    - shard-apl:          FAIL [fdo#99912] -> PASS

  * igt@pm_rc6_residency@rc6-accuracy:
    - shard-snb:          {SKIP} [fdo#109271] -> PASS

  
#### Warnings ####

  * igt@i915_suspend@shrink:
    - shard-hsw:          DMESG-WARN [fdo#109244] -> INCOMPLETE [fdo#103540] / [fdo#106886]

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#102614]: https://bugs.freedesktop.org/show_bug.cgi?id=102614
  [fdo#103166]: https://bugs.freedesktop.org/show_bug.cgi?id=103166
  [fdo#103167]: https://bugs.freedesktop.org/show_bug.cgi?id=103167
  [fdo#103191]: https://bugs.freedesktop.org/show_bug.cgi?id=103191
  [fdo#103232]: https://bugs.freedesktop.org/show_bug.cgi?id=103232
  [fdo#103355]: https://bugs.freedesktop.org/show_bug.cgi?id=103355
  [fdo#103540]: https://bugs.freedesktop.org/show_bug.cgi?id=103540
  [fdo#103665]: https://bugs.freedesktop.org/show_bug.cgi?id=103665
  [fdo#103927]: https://bugs.freedesktop.org/show_bug.cgi?id=103927
  [fdo#105411]: https://bugs.freedesktop.org/show_bug.cgi?id=105411
  [fdo#105763]: https://bugs.freedesktop.org/show_bug.cgi?id=105763
  [fdo#106538]: https://bugs.freedesktop.org/show_bug.cgi?id=106538
  [fdo#106886]: https://bugs.freedesktop.org/show_bug.cgi?id=106886
  [fdo#107725]: https://bugs.freedesktop.org/show_bug.cgi?id=107725
  [fdo#107956]: https://bugs.freedesktop.org/show_bug.cgi?id=107956
  [fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
  [fdo#109225]: https://bugs.freedesktop.org/show_bug.cgi?id=109225
  [fdo#109244]: https://bugs.freedesktop.org/show_bug.cgi?id=109244
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109278]: https://bugs.freedesktop.org/show_bug.cgi?id=109278
  [fdo#109350]: https://bugs.freedesktop.org/show_bug.cgi?id=109350
  [fdo#99912]: https://bugs.freedesktop.org/show_bug.cgi?id=99912


Participating hosts (7 -> 5)
------------------------------

  Missing    (2): shard-skl shard-iclb 


Build changes
-------------

    * IGT: IGT_4816 -> IGTPW_2371
    * Piglit: piglit_4509 -> None

  CI_DRM_5586: e54b6a76e1a6d0e4ba8b56f149673ea9907b2c59 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_2371: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2371/
  IGT_4816: f62577c85c9ef0539d468d6fad105b706a15139c @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2371/
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Intel-gfx] [IGT 1/2] tools/intel_gpu_top: Add support for stdout logging
  2019-02-11 12:21 ` [igt-dev] [IGT 1/2] " Chris Wilson
@ 2019-02-11 17:08   ` Tvrtko Ursulin
  0 siblings, 0 replies; 7+ messages in thread
From: Tvrtko Ursulin @ 2019-02-11 17:08 UTC (permalink / raw)
  To: Chris Wilson, igt-dev; +Cc: Intel-gfx, Eero Tamminen, 3.14pi


On 11/02/2019 12:21, Chris Wilson wrote:
> Quoting Tvrtko Ursulin (2019-02-11 11:45:22)
>> +static enum {
>> +       INTERACTIVE,
>> +       STDOUT,
>> +       JSON
>> +} output_mode;
>> +
>> +struct cnt_item {
>> +       struct pmu_counter *pmu;
> 
> /* "%*.*f", fmt_d, fmt_dd, X */
> 
> I tried fmt_d == fmt_width and fmt_dd == fmt_decimals
> 
> It's called field width and precision in the manpage, so
> maybe fmt_width and fmt_precision.

Makes sense indeed.

> Having figured that out, the use makes sense.
> 
>> +       unsigned int fmt_d;
>> +       unsigned int fmt_dd;
>> +       double d;
>> +       double t;
>> +       double s;
>> +       const char *name;
>> +       const char *unit;
>> +
>> +       /* Internal fields. */
>> +       char buf[16];
>> +};
>> +
>> +struct cnt_group {
>> +       const char *name;
>> +       const char *display_name;
>> +       struct cnt_item *items;
>> +};
>> +
>> +static unsigned int json_indent_level;
>> +
>> +static const char *json_indent[] = {
>> +       "",
>> +       "\t",
>> +       "\t\t",
>> +       "\t\t\t",
>> +       "\t\t\t\t",
>> +       "\t\t\t\t\t",
>> +};
>> +
>> +#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
>> +
>> +static unsigned int json_prev_struct_members;
>> +static unsigned int json_struct_members;
>> +
>> +static void
>> +json_open_struct(const char *name)
>> +{
>> +       assert(json_indent_level < ARRAY_SIZE(json_indent));
>> +
>> +       json_prev_struct_members = json_struct_members;
>> +       json_struct_members = 0;
>> +
>> +       if (name)
>> +               printf("%s%s\"%s\": {\n",
>> +                      json_prev_struct_members ? ",\n" : "",
>> +                      json_indent[json_indent_level],
> 
> "%*s", json_indent_level, "\t\t\t\t\t"
> didn't stick?

No, I lost patience trying to make it do what I want. AFAIR it insisted 
on right justifying and the negative count also did not work.

> I could follow the flow, dug into a few of the details, and only have
> some nits. One thing, could we feed in a perf record? I was thinking for
> testing the various output modes with known data, but may also be useful
> for replay.

Could do, should be too hard. Writing tests for tool output though 
sounds like something I won't have time to do in the near future.

> Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>

Thanks, I'll keep it when I fix the asprintf return value inspection 
which I butchered in a hasty copy and paste work.

Regards,

Tvrtko
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-02-11 17:08 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-02-11 11:45 [igt-dev] [IGT 1/2] tools/intel_gpu_top: Add support for stdout logging Tvrtko Ursulin
2019-02-11 11:45 ` [igt-dev] [IGT 2/2] tools/intel_gpu_top: Add file output capability Tvrtko Ursulin
2019-02-11 12:12 ` [igt-dev] ✓ Fi.CI.BAT: success for series starting with [1/2] tools/intel_gpu_top: Add support for stdout logging Patchwork
2019-02-11 12:21 ` [igt-dev] [IGT 1/2] " Chris Wilson
2019-02-11 17:08   ` [Intel-gfx] " Tvrtko Ursulin
2019-02-11 14:09 ` [igt-dev] ✓ Fi.CI.IGT: success for series starting with [1/2] " Patchwork
  -- strict thread matches above, loose matches on Subject: below --
2019-02-08 12:03 [igt-dev] [IGT 1/2] " Tvrtko Ursulin
2019-02-08 14:11 ` [igt-dev] ✓ Fi.CI.IGT: success for series starting with [1/2] " Patchwork

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox