From patchwork Wed Aug 7 14:31:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?SsO8cmdlbiBHcm/Dnw==?= X-Patchwork-Id: 11082291 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id F01A114E5 for ; Wed, 7 Aug 2019 14:33:08 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E0C1B28A91 for ; Wed, 7 Aug 2019 14:33:08 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D2B8028A8F; Wed, 7 Aug 2019 14:33:08 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 68B0E285CE for ; Wed, 7 Aug 2019 14:33:08 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hvMyN-0000zK-0s; Wed, 07 Aug 2019 14:31:27 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hvMyL-0000y6-0Z for xen-devel@lists.xenproject.org; Wed, 07 Aug 2019 14:31:25 +0000 X-Inumbo-ID: 075622f9-b920-11e9-8980-bc764e045a96 Received: from mx1.suse.de (unknown [195.135.220.15]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 075622f9-b920-11e9-8980-bc764e045a96; Wed, 07 Aug 2019 14:31:23 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 29FDDAFE3; Wed, 7 Aug 2019 14:31:22 +0000 (UTC) From: Juergen Gross To: xen-devel@lists.xenproject.org Date: Wed, 7 Aug 2019 16:31:16 +0200 Message-Id: <20190807143119.8360-2-jgross@suse.com> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20190807143119.8360-1-jgross@suse.com> References: <20190807143119.8360-1-jgross@suse.com> Subject: [Xen-devel] [PATCH 1/4] xen/spinlocks: in debug builds store cpu holding the lock X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Juergen Gross , Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Jan Beulich MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Add the cpu currently holding the lock to struct lock_debug. This makes analysis of locking errors easier and it can be tested whether the correct cpu is releasing a lock again. Signed-off-by: Juergen Gross --- xen/common/spinlock.c | 31 +++++++++++++++++++++++++------ xen/include/xen/spinlock.h | 16 +++++++++++----- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/xen/common/spinlock.c b/xen/common/spinlock.c index 6bc52d70c0..4e681cc651 100644 --- a/xen/common/spinlock.c +++ b/xen/common/spinlock.c @@ -13,9 +13,9 @@ static atomic_t spin_debug __read_mostly = ATOMIC_INIT(0); -static void check_lock(struct lock_debug *debug) +static void check_lock(union lock_debug *debug) { - int irq_safe = !local_irq_is_enabled(); + unsigned short irq_safe = !local_irq_is_enabled(); if ( unlikely(atomic_read(&spin_debug) <= 0) ) return; @@ -43,18 +43,21 @@ static void check_lock(struct lock_debug *debug) */ if ( unlikely(debug->irq_safe != irq_safe) ) { - int seen = cmpxchg(&debug->irq_safe, -1, irq_safe); + union lock_debug seen, new = { 0 }; - if ( seen == !irq_safe ) + new.irq_safe = irq_safe; + seen.val = cmpxchg(&debug->val, 0xffff, new.val); + + if ( !seen.unused && seen.irq_safe == !irq_safe ) { printk("CHECKLOCK FAILURE: prev irqsafe: %d, curr irqsafe %d\n", - seen, irq_safe); + seen.irq_safe, irq_safe); BUG(); } } } -static void check_barrier(struct lock_debug *debug) +static void check_barrier(union lock_debug *debug) { if ( unlikely(atomic_read(&spin_debug) <= 0) ) return; @@ -73,6 +76,17 @@ static void check_barrier(struct lock_debug *debug) BUG_ON(!local_irq_is_enabled() && (debug->irq_safe == 0)); } +static void got_lock(union lock_debug *debug) +{ + debug->cpu = smp_processor_id(); +} + +static void rel_lock(union lock_debug *debug) +{ + ASSERT(debug->cpu == smp_processor_id()); + debug->cpu = SPINLOCK_NO_CPU; +} + void spin_debug_enable(void) { atomic_inc(&spin_debug); @@ -87,6 +101,8 @@ void spin_debug_disable(void) #define check_lock(l) ((void)0) #define check_barrier(l) ((void)0) +#define got_lock(l) ((void)0) +#define rel_lock(l) ((void)0) #endif @@ -150,6 +166,7 @@ void inline _spin_lock_cb(spinlock_t *lock, void (*cb)(void *), void *data) cb(data); arch_lock_relax(); } + got_lock(&lock->debug); LOCK_PROFILE_GOT; preempt_disable(); arch_lock_acquire_barrier(); @@ -181,6 +198,7 @@ void _spin_unlock(spinlock_t *lock) arch_lock_release_barrier(); preempt_enable(); LOCK_PROFILE_REL; + rel_lock(&lock->debug); add_sized(&lock->tickets.head, 1); arch_lock_signal(); } @@ -224,6 +242,7 @@ int _spin_trylock(spinlock_t *lock) if ( cmpxchg(&lock->tickets.head_tail, old.head_tail, new.head_tail) != old.head_tail ) return 0; + got_lock(&lock->debug); #ifdef CONFIG_LOCK_PROFILE if (lock->profile) lock->profile->time_locked = NOW(); diff --git a/xen/include/xen/spinlock.h b/xen/include/xen/spinlock.h index a811b73bf3..b4881ad433 100644 --- a/xen/include/xen/spinlock.h +++ b/xen/include/xen/spinlock.h @@ -7,14 +7,20 @@ #include #ifndef NDEBUG -struct lock_debug { - s16 irq_safe; /* +1: IRQ-safe; 0: not IRQ-safe; -1: don't know yet */ +union lock_debug { + unsigned short val; + struct { + unsigned short unused:1; + unsigned short irq_safe:1; + unsigned short pad:2; + unsigned short cpu:12; + }; }; -#define _LOCK_DEBUG { -1 } +#define _LOCK_DEBUG { 0xffff } void spin_debug_enable(void); void spin_debug_disable(void); #else -struct lock_debug { }; +union lock_debug { }; #define _LOCK_DEBUG { } #define spin_debug_enable() ((void)0) #define spin_debug_disable() ((void)0) @@ -143,7 +149,7 @@ typedef struct spinlock { #define SPINLOCK_NO_CPU 0xfffu u16 recurse_cnt:4; #define SPINLOCK_MAX_RECURSE 0xfu - struct lock_debug debug; + union lock_debug debug; #ifdef CONFIG_LOCK_PROFILE struct lock_profile *profile; #endif From patchwork Wed Aug 7 14:31:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?SsO8cmdlbiBHcm/Dnw==?= X-Patchwork-Id: 11082281 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BE439912 for ; Wed, 7 Aug 2019 14:32:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id ACC5928A92 for ; Wed, 7 Aug 2019 14:32:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A0D7A285CE; Wed, 7 Aug 2019 14:32:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 4FCE028A75 for ; Wed, 7 Aug 2019 14:32:43 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hvMyM-0000yT-4n; Wed, 07 Aug 2019 14:31:26 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hvMyK-0000y5-Tj for xen-devel@lists.xenproject.org; Wed, 07 Aug 2019 14:31:24 +0000 X-Inumbo-ID: 078bee50-b920-11e9-b7f8-5ba9b72e5674 Received: from mx1.suse.de (unknown [195.135.220.15]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 078bee50-b920-11e9-b7f8-5ba9b72e5674; Wed, 07 Aug 2019 14:31:23 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 84D6EB034; Wed, 7 Aug 2019 14:31:22 +0000 (UTC) From: Juergen Gross To: xen-devel@lists.xenproject.org Date: Wed, 7 Aug 2019 16:31:17 +0200 Message-Id: <20190807143119.8360-3-jgross@suse.com> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20190807143119.8360-1-jgross@suse.com> References: <20190807143119.8360-1-jgross@suse.com> Subject: [Xen-devel] [PATCH 2/4] xen: add new CONFIG_SPINLOCK_DEBUG option X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Juergen Gross , Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Jan Beulich MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Instead of enabling spinlock debugging for debug builds only add a dedicated Kconfig option for that purpose which defaults to DEBUG. Signed-off-by: Juergen Gross --- xen/Kconfig.debug | 7 +++++++ xen/common/spinlock.c | 4 ++-- xen/include/xen/spinlock.h | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/xen/Kconfig.debug b/xen/Kconfig.debug index e10e314e25..5db3e7ec25 100644 --- a/xen/Kconfig.debug +++ b/xen/Kconfig.debug @@ -44,6 +44,13 @@ config COVERAGE If unsure, say N here. +config SPINLOCK_DEBUG + bool "Spinlock debugging" + default DEBUG + ---help--- + Enable debugging features of spinlock handling. Some additional + checks will be performed when acquiring and releasing locks. + config LOCK_PROFILE bool "Lock Profiling" ---help--- diff --git a/xen/common/spinlock.c b/xen/common/spinlock.c index 4e681cc651..16356ec9b7 100644 --- a/xen/common/spinlock.c +++ b/xen/common/spinlock.c @@ -9,7 +9,7 @@ #include #include -#ifndef NDEBUG +#ifdef CONFIG_SPINLOCK_DEBUG static atomic_t spin_debug __read_mostly = ATOMIC_INIT(0); @@ -97,7 +97,7 @@ void spin_debug_disable(void) atomic_dec(&spin_debug); } -#else /* defined(NDEBUG) */ +#else /* CONFIG_SPINLOCK_DEBUG */ #define check_lock(l) ((void)0) #define check_barrier(l) ((void)0) diff --git a/xen/include/xen/spinlock.h b/xen/include/xen/spinlock.h index b4881ad433..e3458f10dd 100644 --- a/xen/include/xen/spinlock.h +++ b/xen/include/xen/spinlock.h @@ -6,7 +6,7 @@ #include #include -#ifndef NDEBUG +#ifdef CONFIG_SPINLOCK_DEBUG union lock_debug { unsigned short val; struct { From patchwork Wed Aug 7 14:31:18 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?SsO8cmdlbiBHcm/Dnw==?= X-Patchwork-Id: 11082283 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id DBC6614DB for ; Wed, 7 Aug 2019 14:32:45 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CBCD1287D3 for ; Wed, 7 Aug 2019 14:32:45 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C025C28A92; Wed, 7 Aug 2019 14:32:45 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 5DBB728A63 for ; Wed, 7 Aug 2019 14:32:45 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hvMyM-0000yl-NO; Wed, 07 Aug 2019 14:31:26 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hvMyK-0000y3-TR for xen-devel@lists.xenproject.org; Wed, 07 Aug 2019 14:31:24 +0000 X-Inumbo-ID: 07cd737a-b920-11e9-912d-ef6d3c680eca Received: from mx1.suse.de (unknown [195.135.220.15]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 07cd737a-b920-11e9-912d-ef6d3c680eca; Wed, 07 Aug 2019 14:31:23 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id E8971B035; Wed, 7 Aug 2019 14:31:22 +0000 (UTC) From: Juergen Gross To: xen-devel@lists.xenproject.org Date: Wed, 7 Aug 2019 16:31:18 +0200 Message-Id: <20190807143119.8360-4-jgross@suse.com> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20190807143119.8360-1-jgross@suse.com> References: <20190807143119.8360-1-jgross@suse.com> Subject: [Xen-devel] [PATCH 3/4] xen: print lock profile info in panic() X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Juergen Gross , Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Jan Beulich MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Print the lock profile data when the system crashes and add some more information for each lock data (lock address, cpu holding the lock). This is especially beneficial for watchdog triggered crashes in case of deadlocks. In order to have the cpu holding the lock available let the LOCK_PROFILE config option select SPINLOCK_DEBUG. As printing the lock profile data will make use of locking, too, we need to disable spinlock debugging before calling spinlock_profile_printall() from panic(). While at it remove a superfluous #ifdef CONFIG_LOCK_PROFILE. Signed-off-by: Juergen Gross --- xen/Kconfig.debug | 1 + xen/common/spinlock.c | 11 +++++++---- xen/drivers/char/console.c | 4 +++- xen/include/xen/spinlock.h | 1 + 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/xen/Kconfig.debug b/xen/Kconfig.debug index 5db3e7ec25..a7387f1630 100644 --- a/xen/Kconfig.debug +++ b/xen/Kconfig.debug @@ -53,6 +53,7 @@ config SPINLOCK_DEBUG config LOCK_PROFILE bool "Lock Profiling" + select SPINLOCK_DEBUG ---help--- Lock profiling allows you to see how often locks are taken and blocked. You can use serial console to print (and reset) using 'l' and 'L' diff --git a/xen/common/spinlock.c b/xen/common/spinlock.c index 16356ec9b7..5730076581 100644 --- a/xen/common/spinlock.c +++ b/xen/common/spinlock.c @@ -362,10 +362,13 @@ static void spinlock_profile_iterate(lock_profile_subfunc *sub, void *par) static void spinlock_profile_print_elem(struct lock_profile *data, int32_t type, int32_t idx, void *par) { - if ( type == LOCKPROF_TYPE_GLOBAL ) - printk("%s %s:\n", lock_profile_ancs[type].name, data->name); - else - printk("%s %d %s:\n", lock_profile_ancs[type].name, idx, data->name); + struct spinlock *lock = data->lock; + + printk("%s ", lock_profile_ancs[type].name); + if ( type != LOCKPROF_TYPE_GLOBAL ) + printk("%d ", idx); + printk("%s: addr=%p, lockval=%04x, cpu=%d\n", data->name, lock, + lock->tickets.head_tail, lock->debug.cpu); printk(" lock:%12"PRId64"(%08X:%08X), block:%12"PRId64"(%08X:%08X)\n", data->lock_cnt, (u32)(data->time_hold >> 32), (u32)data->time_hold, data->block_cnt, (u32)(data->time_block >> 32), diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 1680d078db..404d28a725 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -1167,7 +1167,9 @@ void panic(const char *fmt, ...) unsigned long flags; static DEFINE_SPINLOCK(lock); static char buf[128]; - + + spin_debug_disable(); + spinlock_profile_printall('\0'); debugtrace_dump(); /* Protects buf[] and ensure multi-line message prints atomically. */ diff --git a/xen/include/xen/spinlock.h b/xen/include/xen/spinlock.h index e3458f10dd..26891445fe 100644 --- a/xen/include/xen/spinlock.h +++ b/xen/include/xen/spinlock.h @@ -130,6 +130,7 @@ struct lock_profile_qhead { }; #define spin_lock_init_prof(s, l) spin_lock_init(&((s)->l)) #define lock_profile_register_struct(type, ptr, idx, print) #define lock_profile_deregister_struct(type, ptr) +#define spinlock_profile_printall(key) #endif From patchwork Wed Aug 7 14:31:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?SsO8cmdlbiBHcm/Dnw==?= X-Patchwork-Id: 11082285 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id AE64E14DB for ; Wed, 7 Aug 2019 14:32:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9DB8B287D3 for ; Wed, 7 Aug 2019 14:32:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9197928A97; Wed, 7 Aug 2019 14:32:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id AF78228A91 for ; Wed, 7 Aug 2019 14:32:49 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hvMyN-0000za-9p; Wed, 07 Aug 2019 14:31:27 +0000 Received: from us1-rack-dfw2.inumbo.com ([104.130.134.6]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1hvMyL-0000yO-Pj for xen-devel@lists.xenproject.org; Wed, 07 Aug 2019 14:31:25 +0000 X-Inumbo-ID: 0805b33a-b920-11e9-8980-bc764e045a96 Received: from mx1.suse.de (unknown [195.135.220.15]) by us1-rack-dfw2.inumbo.com (Halon) with ESMTPS id 0805b33a-b920-11e9-8980-bc764e045a96; Wed, 07 Aug 2019 14:31:24 +0000 (UTC) X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id 42685B048; Wed, 7 Aug 2019 14:31:23 +0000 (UTC) From: Juergen Gross To: xen-devel@lists.xenproject.org Date: Wed, 7 Aug 2019 16:31:19 +0200 Message-Id: <20190807143119.8360-5-jgross@suse.com> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20190807143119.8360-1-jgross@suse.com> References: <20190807143119.8360-1-jgross@suse.com> Subject: [Xen-devel] [PATCH 4/4] xen: modify lock profiling interface X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Juergen Gross , Stefano Stabellini , Wei Liu , Konrad Rzeszutek Wilk , George Dunlap , Andrew Cooper , Ian Jackson , Tim Deegan , Julien Grall , Jan Beulich MIME-Version: 1.0 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP Today adding locks located in a struct to lock profiling requires a unique type index for each structure. This makes it hard to add any new structure as the related sysctl interface needs to be changed, too. Instead of using an index the already existing struct name specified in lock_profile_register_struct() can be used as an identifier instead. Modify the sysctl interface to use the struct name instead of the type index and adapt the related coding accordingly. Instead of an array of struct anchors for lock profiling we now use a linked list for that purpose. Use the special idx value -1 for cases where the idx isn't relevant (global locks) and shouldn't be printed. Increment the sysctl.h interface version as an interface is being modified. Add the missing setting of profiling time to xc_lockprof_query(). Add freeing element data when deregistering a structure. Signed-off-by: Juergen Gross --- tools/libxc/xc_misc.c | 1 + tools/misc/xenlockprof.c | 17 ++------- xen/common/domain.c | 4 +- xen/common/spinlock.c | 92 +++++++++++++++++++++++++++++++-------------- xen/include/public/sysctl.h | 11 ++---- xen/include/xen/spinlock.h | 23 ++++++------ 6 files changed, 86 insertions(+), 62 deletions(-) diff --git a/tools/libxc/xc_misc.c b/tools/libxc/xc_misc.c index 5e6714ae2b..68c17293bd 100644 --- a/tools/libxc/xc_misc.c +++ b/tools/libxc/xc_misc.c @@ -510,6 +510,7 @@ int xc_lockprof_query(xc_interface *xch, rc = do_sysctl(xch, &sysctl); *n_elems = sysctl.u.lockprof_op.nr_elem; + *time = sysctl.u.lockprof_op.time; return rc; } diff --git a/tools/misc/xenlockprof.c b/tools/misc/xenlockprof.c index 11f43a35e3..c6aa3fe841 100644 --- a/tools/misc/xenlockprof.c +++ b/tools/misc/xenlockprof.c @@ -88,19 +88,10 @@ int main(int argc, char *argv[]) sb = 0; for ( j = 0; j < i; j++ ) { - switch ( data[j].type ) - { - case LOCKPROF_TYPE_GLOBAL: - sprintf(name, "global lock %s", data[j].name); - break; - case LOCKPROF_TYPE_PERDOM: - sprintf(name, "domain %d lock %s", data[j].idx, data[j].name); - break; - default: - sprintf(name, "unknown type(%d) %d lock %s", data[j].type, - data[j].idx, data[j].name); - break; - } + if ( data[j].idx == LOCKPROF_IDX_NONE ) + sprintf(name, "%s %s", data[j].type, data[j].name); + else + sprintf(name, "%s %d %s", data[j].type, data[j].idx, data[j].name); l = (double)(data[j].lock_time) / 1E+09; b = (double)(data[j].block_time) / 1E+09; sl += l; diff --git a/xen/common/domain.c b/xen/common/domain.c index 744b572195..1051bf38a3 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -290,7 +290,7 @@ static void _domain_destroy(struct domain *d) xsm_free_security_domain(d); - lock_profile_deregister_struct(LOCKPROF_TYPE_PERDOM, d); + lock_profile_deregister_struct(d, "Domain"); free_domain_struct(d); } @@ -369,7 +369,7 @@ struct domain *domain_create(domid_t domid, d->max_vcpus = config->max_vcpus; } - lock_profile_register_struct(LOCKPROF_TYPE_PERDOM, d, domid, "Domain"); + lock_profile_register_struct(d, domid, "Domain"); if ( (err = xsm_alloc_security_domain(d)) != 0 ) goto fail; diff --git a/xen/common/spinlock.c b/xen/common/spinlock.c index 5730076581..2582b4e340 100644 --- a/xen/common/spinlock.c +++ b/xen/common/spinlock.c @@ -330,42 +330,43 @@ void _spin_unlock_recursive(spinlock_t *lock) #ifdef CONFIG_LOCK_PROFILE struct lock_profile_anc { + struct lock_profile_anc *next; /* next type */ struct lock_profile_qhead *head_q; /* first head of this type */ - char *name; /* descriptive string for print */ + const char *name; /* descriptive string for print */ }; typedef void lock_profile_subfunc( - struct lock_profile *, int32_t, int32_t, void *); + struct lock_profile *, const char *, int32_t, void *); extern struct lock_profile *__lock_profile_start; extern struct lock_profile *__lock_profile_end; static s_time_t lock_profile_start; -static struct lock_profile_anc lock_profile_ancs[LOCKPROF_TYPE_N]; +static struct lock_profile_anc *lock_profile_ancs; static struct lock_profile_qhead lock_profile_glb_q; static spinlock_t lock_profile_lock = SPIN_LOCK_UNLOCKED; static void spinlock_profile_iterate(lock_profile_subfunc *sub, void *par) { - int i; + struct lock_profile_anc *anc; struct lock_profile_qhead *hq; struct lock_profile *eq; spin_lock(&lock_profile_lock); - for ( i = 0; i < LOCKPROF_TYPE_N; i++ ) - for ( hq = lock_profile_ancs[i].head_q; hq; hq = hq->head_q ) + for ( anc = lock_profile_ancs; anc; anc = anc->next ) + for ( hq = anc->head_q; hq; hq = hq->head_q ) for ( eq = hq->elem_q; eq; eq = eq->next ) - sub(eq, i, hq->idx, par); + sub(eq, anc->name, hq->idx, par); spin_unlock(&lock_profile_lock); } static void spinlock_profile_print_elem(struct lock_profile *data, - int32_t type, int32_t idx, void *par) + const char *type, int32_t idx, void *par) { struct spinlock *lock = data->lock; - printk("%s ", lock_profile_ancs[type].name); - if ( type != LOCKPROF_TYPE_GLOBAL ) + printk("%s ", type); + if ( idx != LOCKPROF_IDX_NONE ) printk("%d ", idx); printk("%s: addr=%p, lockval=%04x, cpu=%d\n", data->name, lock, lock->tickets.head_tail, lock->debug.cpu); @@ -387,7 +388,7 @@ void spinlock_profile_printall(unsigned char key) } static void spinlock_profile_reset_elem(struct lock_profile *data, - int32_t type, int32_t idx, void *par) + const char *type, int32_t idx, void *par) { data->lock_cnt = 0; data->block_cnt = 0; @@ -411,7 +412,7 @@ typedef struct { } spinlock_profile_ucopy_t; static void spinlock_profile_ucopy_elem(struct lock_profile *data, - int32_t type, int32_t idx, void *par) + const char *type, int32_t idx, void *par) { spinlock_profile_ucopy_t *p = par; struct xen_sysctl_lockprof_data elem; @@ -422,7 +423,7 @@ static void spinlock_profile_ucopy_elem(struct lock_profile *data, if ( p->pc->nr_elem < p->pc->max_elem ) { safe_strcpy(elem.name, data->name); - elem.type = type; + safe_strcpy(elem.type, type); elem.idx = idx; elem.lock_cnt = data->lock_cnt; elem.block_cnt = data->block_cnt; @@ -463,31 +464,67 @@ int spinlock_profile_control(struct xen_sysctl_lockprof_op *pc) return rc; } -void _lock_profile_register_struct( - int32_t type, struct lock_profile_qhead *qhead, int32_t idx, char *name) +static struct lock_profile_anc *find_prof_anc(const char *name) { - qhead->idx = idx; + struct lock_profile_anc *anc; + + for ( anc = lock_profile_ancs; anc; anc = anc->next ) + if ( !strcmp(anc->name, name) ) + return anc; + return NULL; +} + +void _lock_profile_register_struct(struct lock_profile_qhead *qhead, + int32_t idx, const char *name) +{ + struct lock_profile_anc *anc; + spin_lock(&lock_profile_lock); - qhead->head_q = lock_profile_ancs[type].head_q; - lock_profile_ancs[type].head_q = qhead; - lock_profile_ancs[type].name = name; + + anc = find_prof_anc(name); + if ( !anc ) + { + anc = xzalloc(struct lock_profile_anc); + anc->name = name; + anc->next = lock_profile_ancs; + lock_profile_ancs = anc; + } + + qhead->idx = idx; + qhead->head_q = anc->head_q; + anc->head_q = qhead; + spin_unlock(&lock_profile_lock); } -void _lock_profile_deregister_struct( - int32_t type, struct lock_profile_qhead *qhead) +void _lock_profile_deregister_struct(struct lock_profile_qhead *qhead, + const char *name) { + struct lock_profile_anc *anc; struct lock_profile_qhead **q; + struct lock_profile *elem; spin_lock(&lock_profile_lock); - for ( q = &lock_profile_ancs[type].head_q; *q; q = &(*q)->head_q ) + + anc = find_prof_anc(name); + if ( anc ) { - if ( *q == qhead ) + for ( q = &anc->head_q; *q; q = &(*q)->head_q ) { - *q = qhead->head_q; - break; + if ( *q == qhead ) + { + *q = qhead->head_q; + while ( qhead->elem_q ) + { + elem = qhead->elem_q; + qhead->elem_q = elem->next; + xfree(elem); + } + break; + } } } + spin_unlock(&lock_profile_lock); } @@ -503,9 +540,8 @@ static int __init lock_prof_init(void) (*q)->lock->profile = *q; } - _lock_profile_register_struct( - LOCKPROF_TYPE_GLOBAL, &lock_profile_glb_q, - 0, "Global lock"); + _lock_profile_register_struct(&lock_profile_glb_q, LOCKPROF_IDX_NONE, + "Global"); return 0; } diff --git a/xen/include/public/sysctl.h b/xen/include/public/sysctl.h index 91c48dcae0..fafce64f02 100644 --- a/xen/include/public/sysctl.h +++ b/xen/include/public/sysctl.h @@ -35,7 +35,7 @@ #include "domctl.h" #include "physdev.h" -#define XEN_SYSCTL_INTERFACE_VERSION 0x00000012 +#define XEN_SYSCTL_INTERFACE_VERSION 0x00000013 /* * Read console content from Xen buffer ring. @@ -433,14 +433,11 @@ struct xen_sysctl_page_offline_op { /* Sub-operations: */ #define XEN_SYSCTL_LOCKPROF_reset 1 /* Reset all profile data to zero. */ #define XEN_SYSCTL_LOCKPROF_query 2 /* Get lock profile information. */ -/* Record-type: */ -#define LOCKPROF_TYPE_GLOBAL 0 /* global lock, idx meaningless */ -#define LOCKPROF_TYPE_PERDOM 1 /* per-domain lock, idx is domid */ -#define LOCKPROF_TYPE_N 2 /* number of types */ struct xen_sysctl_lockprof_data { - char name[40]; /* lock name (may include up to 2 %d specifiers) */ - int32_t type; /* LOCKPROF_TYPE_??? */ + char name[40]; /* lock name */ + char type[20]; /* e.g. "domain" */ int32_t idx; /* index (e.g. domain id) */ +#define LOCKPROF_IDX_NONE -1 uint64_aligned_t lock_cnt; /* # of locking succeeded */ uint64_aligned_t block_cnt; /* # of wait for lock */ uint64_aligned_t lock_time; /* nsecs lock held */ diff --git a/xen/include/xen/spinlock.h b/xen/include/xen/spinlock.h index 26891445fe..fe560f5f5c 100644 --- a/xen/include/xen/spinlock.h +++ b/xen/include/xen/spinlock.h @@ -51,17 +51,16 @@ union lock_debug { }; - each structure has to be added to profiling with - lock_profile_register_struct(type, ptr, idx, print); + lock_profile_register_struct(ptr, idx, print); with: - type: something like LOCKPROF_TYPE_PERDOM ptr: pointer to the structure idx: index of that structure, e.g. domid print: descriptive string like "domain" - removing of a structure is done via - lock_profile_deregister_struct(type, ptr); + lock_profile_deregister_struct(ptr, print); */ struct spinlock; @@ -107,14 +106,14 @@ struct lock_profile_qhead { (s)->profile_head.elem_q = prof; \ } while(0) -void _lock_profile_register_struct( - int32_t, struct lock_profile_qhead *, int32_t, char *); -void _lock_profile_deregister_struct(int32_t, struct lock_profile_qhead *); +void _lock_profile_register_struct(struct lock_profile_qhead *, int32_t, + const char *); +void _lock_profile_deregister_struct(struct lock_profile_qhead *, const char *); -#define lock_profile_register_struct(type, ptr, idx, print) \ - _lock_profile_register_struct(type, &((ptr)->profile_head), idx, print) -#define lock_profile_deregister_struct(type, ptr) \ - _lock_profile_deregister_struct(type, &((ptr)->profile_head)) +#define lock_profile_register_struct(ptr, idx, print) \ + _lock_profile_register_struct(&((ptr)->profile_head), idx, print) +#define lock_profile_deregister_struct(ptr, print) \ + _lock_profile_deregister_struct(&((ptr)->profile_head), print) extern int spinlock_profile_control(struct xen_sysctl_lockprof_op *pc); extern void spinlock_profile_printall(unsigned char key); @@ -128,8 +127,8 @@ struct lock_profile_qhead { }; #define DEFINE_SPINLOCK(l) spinlock_t l = SPIN_LOCK_UNLOCKED #define spin_lock_init_prof(s, l) spin_lock_init(&((s)->l)) -#define lock_profile_register_struct(type, ptr, idx, print) -#define lock_profile_deregister_struct(type, ptr) +#define lock_profile_register_struct(ptr, idx, print) +#define lock_profile_deregister_struct(ptr, print) #define spinlock_profile_printall(key) #endif