Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Feb 2017 14:22:14 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r314044 - head/sys/compat/linuxkpi/common/include/linux
Message-ID:  <201702211422.v1LEMEJC012078@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Tue Feb 21 14:22:14 2017
New Revision: 314044
URL: https://svnweb.freebsd.org/changeset/base/314044

Log:
  Streamline the LinuxKPI spinlock wrappers.
  
  1) Add better spinlock debug names when WITNESS_ALL is defined.
  
  2) Make sure that the calling thread gets bound to the current CPU
  while a spinlock is locked. Some Linux kernel code depends on that the
  CPU ID doesn't change while a spinlock is locked.
  
  3) Add support for using LinuxKPI spinlocks during a panic().
  
  MFC after:		1 week
  Sponsored by:		Mellanox Technologies

Modified:
  head/sys/compat/linuxkpi/common/include/linux/spinlock.h

Modified: head/sys/compat/linuxkpi/common/include/linux/spinlock.h
==============================================================================
--- head/sys/compat/linuxkpi/common/include/linux/spinlock.h	Tue Feb 21 13:23:53 2017	(r314043)
+++ head/sys/compat/linuxkpi/common/include/linux/spinlock.h	Tue Feb 21 14:22:14 2017	(r314044)
@@ -2,7 +2,7 @@
  * Copyright (c) 2010 Isilon Systems, Inc.
  * Copyright (c) 2010 iX Systems, Inc.
  * Copyright (c) 2010 Panasas, Inc.
- * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
+ * Copyright (c) 2013-2017 Mellanox Technologies, Ltd.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -35,36 +35,126 @@
 #include <sys/kernel.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
-#include <sys/libkern.h>
+#include <sys/kdb.h>
 
 #include <linux/compiler.h>
 #include <linux/rwlock.h>
+#include <linux/bottom_half.h>
 
 typedef struct {
 	struct mtx m;
 } spinlock_t;
 
-#define	spin_lock(_l)		mtx_lock(&(_l)->m)
-#define	spin_unlock(_l)		mtx_unlock(&(_l)->m)
-#define	spin_trylock(_l)	mtx_trylock(&(_l)->m)
-#define	spin_lock_nested(_l, _n) mtx_lock_flags(&(_l)->m, MTX_DUPOK)
-#define	spin_lock_irq(lock)	spin_lock(lock)
-#define	spin_unlock_irq(lock)	spin_unlock(lock)
-#define	spin_lock_irqsave(lock, flags)   				\
-    do {(flags) = 0; spin_lock(lock); } while (0)
-#define	spin_unlock_irqrestore(lock, flags)				\
-    do { spin_unlock(lock); } while (0)
+/*
+ * By defining CONFIG_SPIN_SKIP LinuxKPI spinlocks and asserts will be
+ * skipped during panic(). By default it is disabled due to
+ * performance reasons.
+ */
+#ifdef CONFIG_SPIN_SKIP
+#define	SPIN_SKIP(void)	unlikely(SCHEDULER_STOPPED() || kdb_active)
+#else
+#define	SPIN_SKIP(void) 0
+#endif
+
+#define	spin_lock(_l) do {			\
+	if (SPIN_SKIP())			\
+		break;				\
+	mtx_lock(&(_l)->m);			\
+	local_bh_disable();			\
+} while (0)
+
+#define	spin_lock_bh(_l) do {			\
+	spin_lock(_l);				\
+} while (0)
+
+#define	spin_lock_irq(_l) do {			\
+	spin_lock(_l);				\
+} while (0)
+
+#define	spin_unlock(_l)	do {			\
+	if (SPIN_SKIP())			\
+		break;				\
+	local_bh_enable();			\
+	mtx_unlock(&(_l)->m);			\
+} while (0)
+
+#define	spin_unlock_bh(_l) do {			\
+	spin_unlock(_l);			\
+} while (0)
+
+#define	spin_unlock_irq(_l) do {		\
+	spin_unlock(_l);			\
+} while (0)
+
+#define	spin_trylock(_l) ({			\
+	int __ret;				\
+	if (SPIN_SKIP()) {			\
+		__ret = 1;			\
+	} else {				\
+		__ret = mtx_trylock(&(_l)->m);	\
+		if (likely(__ret != 0))		\
+			local_bh_disable();	\
+	}					\
+	__ret;					\
+})
+
+#define	spin_lock_nested(_l, _n) do {		\
+	if (SPIN_SKIP())			\
+		break;				\
+	mtx_lock_flags(&(_l)->m, MTX_DUPOK);	\
+	local_bh_disable();			\
+} while (0)
+
+#define	spin_lock_irqsave(_l, flags) do {	\
+	(flags) = 0;				\
+	spin_lock(_l);				\
+} while (0)
+
+#define	spin_lock_irqsave_nested(_l, flags, _n) do {	\
+	(flags) = 0;					\
+	spin_lock_nested(_l, _n);			\
+} while (0)
+
+#define	spin_unlock_irqrestore(_l, flags) do {		\
+	spin_unlock(_l);				\
+} while (0)
+
+#ifdef WITNESS_ALL
+/* NOTE: the maximum WITNESS name is 64 chars */
+#define	__spin_lock_name(name, file, line)		\
+	(((const char *){file ":" #line "-" name}) + 	\
+	(sizeof(file) > 16 ? sizeof(file) - 16 : 0))
+#else
+#define	__spin_lock_name(name, file, line)	name
+#endif
+#define	_spin_lock_name(...)		__spin_lock_name(__VA_ARGS__)
+#define	spin_lock_name(name)		_spin_lock_name(name, __FILE__, __LINE__)
+
+#define	spin_lock_init(lock)	linux_spin_lock_init(lock, spin_lock_name("lnxspin"))
+
+static inline void
+linux_spin_lock_init(spinlock_t *lock, const char *name)
+{
+
+	memset(lock, 0, sizeof(*lock));
+	mtx_init(&lock->m, name, NULL, MTX_DEF | MTX_NOWITNESS);
+}
 
 static inline void
-spin_lock_init(spinlock_t *lock)
+spin_lock_destroy(spinlock_t *lock)
 {
 
-	memset(&lock->m, 0, sizeof(lock->m));
-	mtx_init(&lock->m, "lnxspin", NULL, MTX_DEF | MTX_NOWITNESS);
+       mtx_destroy(&lock->m);
 }
 
-#define	DEFINE_SPINLOCK(lock)						\
-	spinlock_t lock;						\
-	MTX_SYSINIT(lock, &(lock).m, "lnxspin", MTX_DEF)
+#define	DEFINE_SPINLOCK(lock)					\
+	spinlock_t lock;					\
+	MTX_SYSINIT(lock, &(lock).m, spin_lock_name("lnxspin"), MTX_DEF)
+
+#define	assert_spin_locked(_l) do {		\
+	if (SPIN_SKIP())			\
+		break;				\
+	mtx_assert(&(_l)->m, MA_OWNED);		\
+} while (0)
 
-#endif	/* _LINUX_SPINLOCK_H_ */
+#endif					/* _LINUX_SPINLOCK_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201702211422.v1LEMEJC012078>