From patchwork Thu Sep 17 16:35:41 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?C=C3=A9dric_Le_Goater?= X-Patchwork-Id: 1366264 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BsjMJ0t26z9sRR for ; Fri, 18 Sep 2020 02:38:20 +1000 (AEST) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 4BsjMH6xpMzDqdD for ; Fri, 18 Sep 2020 02:38:19 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=kaod.org (client-ip=79.137.123.220; helo=smtpout1.mo804.mail-out.ovh.net; envelope-from=clg@kaod.org; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=kaod.org Received: from smtpout1.mo804.mail-out.ovh.net (smtpout1.mo804.mail-out.ovh.net [79.137.123.220]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4BsjJX2tW4zDqc9 for ; Fri, 18 Sep 2020 02:35:56 +1000 (AEST) Received: from mxplan5.mail.ovh.net (unknown [10.108.20.54]) by mo804.mail-out.ovh.net (Postfix) with ESMTPS id C191962BFFD4; Thu, 17 Sep 2020 18:35:47 +0200 (CEST) Received: from kaod.org (37.59.142.96) by DAG4EX1.mxp5.local (172.16.2.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2044.4; Thu, 17 Sep 2020 18:35:47 +0200 Authentication-Results: garm.ovh; auth=pass (GARM-96R0017dd1148a-3952-48ca-8d60-73116934a7a7, FF1720B74B3888C93CA5040C1F5ACCC945AC33B8) smtp.auth=clg@kaod.org From: =?utf-8?q?C=C3=A9dric_Le_Goater?= To: Date: Thu, 17 Sep 2020 18:35:41 +0200 Message-ID: <20200917163544.142593-5-clg@kaod.org> X-Mailer: git-send-email 2.25.4 In-Reply-To: <20200917163544.142593-1-clg@kaod.org> References: <20200917163544.142593-1-clg@kaod.org> MIME-Version: 1.0 X-Originating-IP: [37.59.142.96] X-ClientProxiedBy: DAG1EX1.mxp5.local (172.16.2.1) To DAG4EX1.mxp5.local (172.16.2.31) X-Ovh-Tracer-GUID: f042f58c-beef-40e2-aab2-8c3b406eff95 X-Ovh-Tracer-Id: 10404159565598002141 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedujedrtdeggddutdehucetufdoteggodetrfdotffvucfrrhhofhhilhgvmecuqfggjfdpvefjgfevmfevgfenuceurghilhhouhhtmecuhedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhephffvufffkffojghfgggtgfhisehtkeertdertdejnecuhfhrohhmpeevrogurhhitgcunfgvucfiohgrthgvrhcuoegtlhhgsehkrghougdrohhrgheqnecuggftrfgrthhtvghrnhepheehfeegjeeitdfffeetjeduveejueefuefgtdefueelueetveeliefhhffgtdelnecukfhppedtrddtrddtrddtpdefjedrheelrddugedvrdelieenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhhouggvpehsmhhtphdqohhuthdphhgvlhhopehmgihplhgrnhehrdhmrghilhdrohhvhhdrnhgvthdpihhnvghtpedtrddtrddtrddtpdhmrghilhhfrhhomheptghlgheskhgrohgurdhorhhgpdhrtghpthhtoheptghlgheskhgrohgurdhorhhg Subject: [Skiboot] [RFC PATCH 4/6] core: Add statistics framework X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?C=C3=A9dric_Le_Goater?= Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" This is a set of simple routines to collect statistics on function calls. It can used to measure low level HW operations and track possible issues in locking, polling, etc. Signed-off-by: Cédric Le Goater --- include/stat.h | 49 ++++++++++++++++++++++++ core/stat.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++ core/Makefile.inc | 2 +- 3 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 include/stat.h create mode 100644 core/stat.c diff --git a/include/stat.h b/include/stat.h new file mode 100644 index 000000000000..dc020862b199 --- /dev/null +++ b/include/stat.h @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Statistics + * + * Copyright 2020 IBM Corp. + */ + +#ifndef __STAT_H +#define __STAT_H + +#include + +#define STAT_NR_RANGES 10 +#define STAT_RANGE_WIDTH 200 /* values */ +#define STAT_MAX_CALL_TIME 10 /* usecs */ + +struct stat_range { + uint64_t count; + uint64_t sum; + uint64_t min; + uint64_t max; +}; + +struct stat { + const char *name; + uint64_t max_call_time; + uint64_t nr_ranges; + uint64_t count; + struct stat_range all; + struct stat_range ranges[STAT_NR_RANGES]; + + struct lock lock; +}; + + +extern void stat_init(struct stat *s, const char *name, uint64_t max_call_time); +extern void stat_update(struct stat *s, uint64_t call_time); +extern int stat_printf(struct stat *s, void *buf, int size); + +#define stat_call(expr, s) \ +({ \ + uint64_t before = mftb(); \ + int64_t __rc = (expr); \ + uint64_t call_time = tb_to_usecs(mftb() - before); \ + stat_update(s, call_time); \ + __rc; \ +}) + +#endif /* __STAT_H */ diff --git a/core/stat.c b/core/stat.c new file mode 100644 index 000000000000..6d1ddf2f1a80 --- /dev/null +++ b/core/stat.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: Apache-2.0 +/* + * Statistics + * + * Copyright 2020 IBM Corp. + */ + +#define pr_fmt(fmt) "STAT: " fmt + +#include +#include +#include +#include + +static void stat_range_reset(struct stat_range *r) +{ + r->count = 0; + r->sum = 0; + r->max = 0; + r->min = 0xFFFFFFFFF; +} + +void stat_init(struct stat *s, const char *name, uint64_t max_call_time) +{ + int i; + + s->name = name; + s->max_call_time = max_call_time; + s->nr_ranges = ARRAY_SIZE(s->ranges); + for (i = 0; i < s->nr_ranges; i++) + stat_range_reset(&s->ranges[i]); + stat_range_reset(&s->all); + init_lock(&s->lock); +} + +static void stat_range_update(struct stat_range *r, uint64_t call_time) +{ + r->sum += call_time; + if (call_time > r->max) + r->max = call_time; + if (call_time < r->min) + r->min = call_time; + r->count++; +} + +#define stat_range_index(s) \ + ((((s)->count) / STAT_RANGE_WIDTH) % (s)->nr_ranges) + +void stat_update(struct stat *s, uint64_t call_time) +{ + int ridx; + struct stat_range *r; + + lock(&s->lock); + + ridx = stat_range_index(s); + r = &s->ranges[ridx]; + + if (!(r->count % STAT_RANGE_WIDTH)) + stat_range_reset(r); + + stat_range_update(r, call_time); + if (s->max_call_time && call_time > s->max_call_time && + call_time > s->all.max) { + /* TODO: simulators need more time */ + prlog(PR_WARNING, "CPU 0x%04x new %s maximum %lld at #%lld\n", + this_cpu()->pir, s->name, r->max, s->count); + backtrace(); + } + stat_range_update(&s->all, call_time); + s->count++; + + unlock(&s->lock); +} + +static int stat_range_printf(struct stat_range *r, void *buf, int size) +{ + return snprintf(buf, size, "#%lld %lld/%lld/%lld - ", + r->count, + r->count ? r->min : 0, + r->sum / r->count, + r->max); +} + +int stat_printf(struct stat *s, void *buf, int size) +{ + int n = 0; + int i; + + if (s->count) { + n += snprintf(buf + n, size - n, "%35s: ", s->name); + n += stat_range_printf(&s->all, buf + n, size - n); + for (i = 0; i < s->nr_ranges; i++) + n += stat_range_printf(&s->ranges[i], buf + n, size - n); + n += snprintf(buf + n, size - n,"\n"); + } + return n; +} diff --git a/core/Makefile.inc b/core/Makefile.inc index ed7003ed7a7a..326fc7917631 100644 --- a/core/Makefile.inc +++ b/core/Makefile.inc @@ -13,7 +13,7 @@ CORE_OBJS += timer.o i2c.o rtc.o flash.o sensor.o ipmi-opal.o CORE_OBJS += flash-subpartition.o bitmap.o buddy.o pci-quirk.o powercap.o psr.o CORE_OBJS += pci-dt-slot.o direct-controls.o cpufeatures.o CORE_OBJS += flash-firmware-versions.o opal-dump.o -CORE_OBJS += opal-debug.o +CORE_OBJS += opal-debug.o stat.o ifeq ($(SKIBOOT_GCOV),1) CORE_OBJS += gcov-profiling.o