All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <20180112160837.GD24497@linux.suse>

diff --git a/a/1.txt b/N1/1.txt
index de2f97c..1630a82 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -7,3 +7,339 @@ On Fri 2018-01-12 10:37:54, Steven Rostedt wrote:
 
 Please, find below the updated version. If I get Ack at least from
 Steven and no nack's, I will put it into linux-next next week.
+
+
+>From f67f70d910d9cf310a7bc73e97bf14097d31b059 Mon Sep 17 00:00:00 2001
+From: Petr Mladek <pmladek@suse.com>
+Date: Fri, 22 Dec 2017 18:58:46 +0100
+Subject: [PATCH v6 2/4] printk: Hide console waiter logic into helpers
+
+The commit ("printk: Add console owner and waiter logic to load balance
+console writes") made vprintk_emit() and console_unlock() even more
+complicated.
+
+This patch extracts the new code into 3 helper functions. They should
+help to keep it rather self-contained. It will be easier to use and
+maintain.
+
+This patch just shuffles the existing code. It does not change
+the functionality.
+
+Signed-off-by: Petr Mladek <pmladek@suse.com>
+---
+Changes against v5:
+ 
+  + updated some comments (Steven)
+  + do console_trylock() in console_trylock_spinning() (Steven)
+
+ kernel/printk/printk.c | 245 +++++++++++++++++++++++++++++--------------------
+ 1 file changed, 148 insertions(+), 97 deletions(-)
+
+diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
+index 7e6459abba43..3057dbc69b4f 100644
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -86,15 +86,8 @@ EXPORT_SYMBOL_GPL(console_drivers);
+ static struct lockdep_map console_lock_dep_map = {
+ 	.name = "console_lock"
+ };
+-static struct lockdep_map console_owner_dep_map = {
+-	.name = "console_owner"
+-};
+ #endif
+ 
+-static DEFINE_RAW_SPINLOCK(console_owner_lock);
+-static struct task_struct *console_owner;
+-static bool console_waiter;
+-
+ enum devkmsg_log_bits {
+ 	__DEVKMSG_LOG_BIT_ON = 0,
+ 	__DEVKMSG_LOG_BIT_OFF,
+@@ -1551,6 +1544,146 @@ SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
+ }
+ 
+ /*
++ * Special console_lock variants that help to reduce the risk of soft-lockups.
++ * They allow to pass console_lock to another printk() call using a busy wait.
++ */
++
++#ifdef CONFIG_LOCKDEP
++static struct lockdep_map console_owner_dep_map = {
++	.name = "console_owner"
++};
++#endif
++
++static DEFINE_RAW_SPINLOCK(console_owner_lock);
++static struct task_struct *console_owner;
++static bool console_waiter;
++
++/**
++ * console_lock_spinning_enable - mark beginning of code where another
++ *	thread might safely busy wait
++ *
++ * This basically converts console_lock into a spinlock. This marks
++ * the section where the console_lock owner can not sleep, because
++ * there may be a waiter spinning (like a spinlock). Also it must be
++ * ready to hand over the lock at the end of the section.
++ */
++static void console_lock_spinning_enable(void)
++{
++	raw_spin_lock(&console_owner_lock);
++	console_owner = current;
++	raw_spin_unlock(&console_owner_lock);
++
++	/* The waiter may spin on us after setting console_owner */
++	spin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_);
++}
++
++/**
++ * console_lock_spinning_disable_and_check - mark end of code where another
++ *	thread was able to busy wait and check if there is a waiter
++ *
++ * This is called at the end of the section where spinning is allowed.
++ * It has two functions. First, it is a signal that it is not longer
++ * safe to start busy waiting for the lock. Second, it checks if
++ * there is a busy waiter and passes the lock rights to her.
++ *
++ * Important: Callers lose the lock if there was the busy waiter.
++ *	They must not touch items synchronized by console_lock
++ *	in this case.
++ *
++ * Return: 1 if the lock rights were passed, 0 otherwise.
++ */
++static int console_lock_spinning_disable_and_check(void)
++{
++	int waiter;
++
++	raw_spin_lock(&console_owner_lock);
++	waiter = READ_ONCE(console_waiter);
++	console_owner = NULL;
++	raw_spin_unlock(&console_owner_lock);
++
++	if (!waiter) {
++		spin_release(&console_owner_dep_map, 1, _THIS_IP_);
++		return 0;
++	}
++
++	/* The waiter is now free to continue */
++	WRITE_ONCE(console_waiter, false);
++
++	spin_release(&console_owner_dep_map, 1, _THIS_IP_);
++
++	/*
++	 * Hand off console_lock to waiter. The waiter will perform
++	 * the up(). After this, the waiter is the console_lock owner.
++	 */
++	mutex_release(&console_lock_dep_map, 1, _THIS_IP_);
++	return 1;
++}
++
++/**
++ * console_trylock_spinning - try to get console_lock by busy waiting
++ *
++ * This allows to busy wait for the console_lock when the current
++ * owner is running in a special marked sections. It means that
++ * the current owner is running and cannot reschedule until it
++ * is ready to loose the lock.
++ *
++ * Return: 1 if we got the lock, 0 othrewise
++ */
++static int console_trylock_spinning(void)
++{
++	struct task_struct *owner = NULL;
++	bool waiter;
++	bool spin = false;
++	unsigned long flags;
++
++	if (console_trylock())
++		return 1;
++
++	printk_safe_enter_irqsave(flags);
++
++	raw_spin_lock(&console_owner_lock);
++	owner = READ_ONCE(console_owner);
++	waiter = READ_ONCE(console_waiter);
++	if (!waiter && owner && owner != current) {
++		WRITE_ONCE(console_waiter, true);
++		spin = true;
++	}
++	raw_spin_unlock(&console_owner_lock);
++
++	/*
++	 * If there is an active printk() writing to the
++	 * consoles, instead of having it write our data too,
++	 * see if we can offload that load from the active
++	 * printer, and do some printing ourselves.
++	 * Go into a spin only if there isn't already a waiter
++	 * spinning, and there is an active printer, and
++	 * that active printer isn't us (recursive printk?).
++	 */
++	if (!spin) {
++		printk_safe_exit_irqrestore(flags);
++		return 0;
++	}
++
++	/* We spin waiting for the owner to release us */
++	spin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_);
++	/* Owner will clear console_waiter on hand off */
++	while (READ_ONCE(console_waiter))
++		cpu_relax();
++	spin_release(&console_owner_dep_map, 1, _THIS_IP_);
++
++	printk_safe_exit_irqrestore(flags);
++	/*
++	 * The owner passed the console lock to us.
++	 * Since we did not spin on console lock, annotate
++	 * this as a trylock. Otherwise lockdep will
++	 * complain.
++	 */
++	mutex_acquire(&console_lock_dep_map, 0, 1, _THIS_IP_);
++
++	return 1;
++}
++
++/*
+  * Call the console drivers, asking them to write out
+  * log_buf[start] to log_buf[end - 1].
+  * The console_lock must be held.
+@@ -1760,56 +1893,8 @@ asmlinkage int vprintk_emit(int facility, int level,
+ 		 * semaphore.  The release will print out buffers and wake up
+ 		 * /dev/kmsg and syslog() users.
+ 		 */
+-		if (console_trylock()) {
++		if (console_trylock_spinning())
+ 			console_unlock();
+-		} else {
+-			struct task_struct *owner = NULL;
+-			bool waiter;
+-			bool spin = false;
+-
+-			printk_safe_enter_irqsave(flags);
+-
+-			raw_spin_lock(&console_owner_lock);
+-			owner = READ_ONCE(console_owner);
+-			waiter = READ_ONCE(console_waiter);
+-			if (!waiter && owner && owner != current) {
+-				WRITE_ONCE(console_waiter, true);
+-				spin = true;
+-			}
+-			raw_spin_unlock(&console_owner_lock);
+-
+-			/*
+-			 * If there is an active printk() writing to the
+-			 * consoles, instead of having it write our data too,
+-			 * see if we can offload that load from the active
+-			 * printer, and do some printing ourselves.
+-			 * Go into a spin only if there isn't already a waiter
+-			 * spinning, and there is an active printer, and
+-			 * that active printer isn't us (recursive printk?).
+-			 */
+-			if (spin) {
+-				/* We spin waiting for the owner to release us */
+-				spin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_);
+-				/* Owner will clear console_waiter on hand off */
+-				while (READ_ONCE(console_waiter))
+-					cpu_relax();
+-
+-				spin_release(&console_owner_dep_map, 1, _THIS_IP_);
+-				printk_safe_exit_irqrestore(flags);
+-
+-				/*
+-				 * The owner passed the console lock to us.
+-				 * Since we did not spin on console lock, annotate
+-				 * this as a trylock. Otherwise lockdep will
+-				 * complain.
+-				 */
+-				mutex_acquire(&console_lock_dep_map, 0, 1, _THIS_IP_);
+-				console_unlock();
+-				printk_safe_enter_irqsave(flags);
+-			}
+-			printk_safe_exit_irqrestore(flags);
+-
+-		}
+ 	}
+ 
+ 	return printed_len;
+@@ -1910,6 +1995,8 @@ static ssize_t msg_print_ext_header(char *buf, size_t size,
+ static ssize_t msg_print_ext_body(char *buf, size_t size,
+ 				  char *dict, size_t dict_len,
+ 				  char *text, size_t text_len) { return 0; }
++static void console_lock_spinning_enable(void) { }
++static int console_lock_spinning_disable_and_check(void) { return 0; }
+ static void call_console_drivers(const char *ext_text, size_t ext_len,
+ 				 const char *text, size_t len) {}
+ static size_t msg_print_text(const struct printk_log *msg,
+@@ -2196,7 +2283,6 @@ void console_unlock(void)
+ 	static u64 seen_seq;
+ 	unsigned long flags;
+ 	bool wake_klogd = false;
+-	bool waiter = false;
+ 	bool do_cond_resched, retry;
+ 
+ 	if (console_suspended) {
+@@ -2291,31 +2377,16 @@ void console_unlock(void)
+ 		 * finish. This task can not be preempted if there is a
+ 		 * waiter waiting to take over.
+ 		 */
+-		raw_spin_lock(&console_owner_lock);
+-		console_owner = current;
+-		raw_spin_unlock(&console_owner_lock);
+-
+-		/* The waiter may spin on us after setting console_owner */
+-		spin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_);
++		console_lock_spinning_enable();
+ 
+ 		stop_critical_timings();	/* don't trace print latency */
+ 		call_console_drivers(ext_text, ext_len, text, len);
+ 		start_critical_timings();
+ 
+-		raw_spin_lock(&console_owner_lock);
+-		waiter = READ_ONCE(console_waiter);
+-		console_owner = NULL;
+-		raw_spin_unlock(&console_owner_lock);
+-
+-		/*
+-		 * If there is a waiter waiting for us, then pass the
+-		 * rest of the work load over to that waiter.
+-		 */
+-		if (waiter)
+-			break;
+-
+-		/* There was no waiter, and nothing will spin on us here */
+-		spin_release(&console_owner_dep_map, 1, _THIS_IP_);
++		if (console_lock_spinning_disable_and_check()) {
++			printk_safe_exit_irqrestore(flags);
++			return;
++		}
+ 
+ 		printk_safe_exit_irqrestore(flags);
+ 
+@@ -2323,26 +2394,6 @@ void console_unlock(void)
+ 			cond_resched();
+ 	}
+ 
+-	/*
+-	 * If there is an active waiter waiting on the console_lock.
+-	 * Pass off the printing to the waiter, and the waiter
+-	 * will continue printing on its CPU, and when all writing
+-	 * has finished, the last printer will wake up klogd.
+-	 */
+-	if (waiter) {
+-		WRITE_ONCE(console_waiter, false);
+-		/* The waiter is now free to continue */
+-		spin_release(&console_owner_dep_map, 1, _THIS_IP_);
+-		/*
+-		 * Hand off console_lock to waiter. The waiter will perform
+-		 * the up(). After this, the waiter is the console_lock owner.
+-		 */
+-		mutex_release(&console_lock_dep_map, 1, _THIS_IP_);
+-		printk_safe_exit_irqrestore(flags);
+-		/* Note, if waiter is set, logbuf_lock is not held */
+-		return;
+-	}
+-
+ 	console_locked = 0;
+ 
+ 	/* Release the exclusive_console once it is used */
+-- 
+2.13.6
diff --git a/a/content_digest b/N1/content_digest
index e866f0f..f7a4a9d 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -37,6 +37,342 @@
  "> Great.\n"
  "\n"
  "Please, find below the updated version. If I get Ack at least from\n"
- Steven and no nack's, I will put it into linux-next next week.
+ "Steven and no nack's, I will put it into linux-next next week.\n"
+ "\n"
+ "\n"
+ ">From f67f70d910d9cf310a7bc73e97bf14097d31b059 Mon Sep 17 00:00:00 2001\n"
+ "From: Petr Mladek <pmladek@suse.com>\n"
+ "Date: Fri, 22 Dec 2017 18:58:46 +0100\n"
+ "Subject: [PATCH v6 2/4] printk: Hide console waiter logic into helpers\n"
+ "\n"
+ "The commit (\"printk: Add console owner and waiter logic to load balance\n"
+ "console writes\") made vprintk_emit() and console_unlock() even more\n"
+ "complicated.\n"
+ "\n"
+ "This patch extracts the new code into 3 helper functions. They should\n"
+ "help to keep it rather self-contained. It will be easier to use and\n"
+ "maintain.\n"
+ "\n"
+ "This patch just shuffles the existing code. It does not change\n"
+ "the functionality.\n"
+ "\n"
+ "Signed-off-by: Petr Mladek <pmladek@suse.com>\n"
+ "---\n"
+ "Changes against v5:\n"
+ " \n"
+ "  + updated some comments (Steven)\n"
+ "  + do console_trylock() in console_trylock_spinning() (Steven)\n"
+ "\n"
+ " kernel/printk/printk.c | 245 +++++++++++++++++++++++++++++--------------------\n"
+ " 1 file changed, 148 insertions(+), 97 deletions(-)\n"
+ "\n"
+ "diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c\n"
+ "index 7e6459abba43..3057dbc69b4f 100644\n"
+ "--- a/kernel/printk/printk.c\n"
+ "+++ b/kernel/printk/printk.c\n"
+ "@@ -86,15 +86,8 @@ EXPORT_SYMBOL_GPL(console_drivers);\n"
+ " static struct lockdep_map console_lock_dep_map = {\n"
+ " \t.name = \"console_lock\"\n"
+ " };\n"
+ "-static struct lockdep_map console_owner_dep_map = {\n"
+ "-\t.name = \"console_owner\"\n"
+ "-};\n"
+ " #endif\n"
+ " \n"
+ "-static DEFINE_RAW_SPINLOCK(console_owner_lock);\n"
+ "-static struct task_struct *console_owner;\n"
+ "-static bool console_waiter;\n"
+ "-\n"
+ " enum devkmsg_log_bits {\n"
+ " \t__DEVKMSG_LOG_BIT_ON = 0,\n"
+ " \t__DEVKMSG_LOG_BIT_OFF,\n"
+ "@@ -1551,6 +1544,146 @@ SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)\n"
+ " }\n"
+ " \n"
+ " /*\n"
+ "+ * Special console_lock variants that help to reduce the risk of soft-lockups.\n"
+ "+ * They allow to pass console_lock to another printk() call using a busy wait.\n"
+ "+ */\n"
+ "+\n"
+ "+#ifdef CONFIG_LOCKDEP\n"
+ "+static struct lockdep_map console_owner_dep_map = {\n"
+ "+\t.name = \"console_owner\"\n"
+ "+};\n"
+ "+#endif\n"
+ "+\n"
+ "+static DEFINE_RAW_SPINLOCK(console_owner_lock);\n"
+ "+static struct task_struct *console_owner;\n"
+ "+static bool console_waiter;\n"
+ "+\n"
+ "+/**\n"
+ "+ * console_lock_spinning_enable - mark beginning of code where another\n"
+ "+ *\tthread might safely busy wait\n"
+ "+ *\n"
+ "+ * This basically converts console_lock into a spinlock. This marks\n"
+ "+ * the section where the console_lock owner can not sleep, because\n"
+ "+ * there may be a waiter spinning (like a spinlock). Also it must be\n"
+ "+ * ready to hand over the lock at the end of the section.\n"
+ "+ */\n"
+ "+static void console_lock_spinning_enable(void)\n"
+ "+{\n"
+ "+\traw_spin_lock(&console_owner_lock);\n"
+ "+\tconsole_owner = current;\n"
+ "+\traw_spin_unlock(&console_owner_lock);\n"
+ "+\n"
+ "+\t/* The waiter may spin on us after setting console_owner */\n"
+ "+\tspin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_);\n"
+ "+}\n"
+ "+\n"
+ "+/**\n"
+ "+ * console_lock_spinning_disable_and_check - mark end of code where another\n"
+ "+ *\tthread was able to busy wait and check if there is a waiter\n"
+ "+ *\n"
+ "+ * This is called at the end of the section where spinning is allowed.\n"
+ "+ * It has two functions. First, it is a signal that it is not longer\n"
+ "+ * safe to start busy waiting for the lock. Second, it checks if\n"
+ "+ * there is a busy waiter and passes the lock rights to her.\n"
+ "+ *\n"
+ "+ * Important: Callers lose the lock if there was the busy waiter.\n"
+ "+ *\tThey must not touch items synchronized by console_lock\n"
+ "+ *\tin this case.\n"
+ "+ *\n"
+ "+ * Return: 1 if the lock rights were passed, 0 otherwise.\n"
+ "+ */\n"
+ "+static int console_lock_spinning_disable_and_check(void)\n"
+ "+{\n"
+ "+\tint waiter;\n"
+ "+\n"
+ "+\traw_spin_lock(&console_owner_lock);\n"
+ "+\twaiter = READ_ONCE(console_waiter);\n"
+ "+\tconsole_owner = NULL;\n"
+ "+\traw_spin_unlock(&console_owner_lock);\n"
+ "+\n"
+ "+\tif (!waiter) {\n"
+ "+\t\tspin_release(&console_owner_dep_map, 1, _THIS_IP_);\n"
+ "+\t\treturn 0;\n"
+ "+\t}\n"
+ "+\n"
+ "+\t/* The waiter is now free to continue */\n"
+ "+\tWRITE_ONCE(console_waiter, false);\n"
+ "+\n"
+ "+\tspin_release(&console_owner_dep_map, 1, _THIS_IP_);\n"
+ "+\n"
+ "+\t/*\n"
+ "+\t * Hand off console_lock to waiter. The waiter will perform\n"
+ "+\t * the up(). After this, the waiter is the console_lock owner.\n"
+ "+\t */\n"
+ "+\tmutex_release(&console_lock_dep_map, 1, _THIS_IP_);\n"
+ "+\treturn 1;\n"
+ "+}\n"
+ "+\n"
+ "+/**\n"
+ "+ * console_trylock_spinning - try to get console_lock by busy waiting\n"
+ "+ *\n"
+ "+ * This allows to busy wait for the console_lock when the current\n"
+ "+ * owner is running in a special marked sections. It means that\n"
+ "+ * the current owner is running and cannot reschedule until it\n"
+ "+ * is ready to loose the lock.\n"
+ "+ *\n"
+ "+ * Return: 1 if we got the lock, 0 othrewise\n"
+ "+ */\n"
+ "+static int console_trylock_spinning(void)\n"
+ "+{\n"
+ "+\tstruct task_struct *owner = NULL;\n"
+ "+\tbool waiter;\n"
+ "+\tbool spin = false;\n"
+ "+\tunsigned long flags;\n"
+ "+\n"
+ "+\tif (console_trylock())\n"
+ "+\t\treturn 1;\n"
+ "+\n"
+ "+\tprintk_safe_enter_irqsave(flags);\n"
+ "+\n"
+ "+\traw_spin_lock(&console_owner_lock);\n"
+ "+\towner = READ_ONCE(console_owner);\n"
+ "+\twaiter = READ_ONCE(console_waiter);\n"
+ "+\tif (!waiter && owner && owner != current) {\n"
+ "+\t\tWRITE_ONCE(console_waiter, true);\n"
+ "+\t\tspin = true;\n"
+ "+\t}\n"
+ "+\traw_spin_unlock(&console_owner_lock);\n"
+ "+\n"
+ "+\t/*\n"
+ "+\t * If there is an active printk() writing to the\n"
+ "+\t * consoles, instead of having it write our data too,\n"
+ "+\t * see if we can offload that load from the active\n"
+ "+\t * printer, and do some printing ourselves.\n"
+ "+\t * Go into a spin only if there isn't already a waiter\n"
+ "+\t * spinning, and there is an active printer, and\n"
+ "+\t * that active printer isn't us (recursive printk?).\n"
+ "+\t */\n"
+ "+\tif (!spin) {\n"
+ "+\t\tprintk_safe_exit_irqrestore(flags);\n"
+ "+\t\treturn 0;\n"
+ "+\t}\n"
+ "+\n"
+ "+\t/* We spin waiting for the owner to release us */\n"
+ "+\tspin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_);\n"
+ "+\t/* Owner will clear console_waiter on hand off */\n"
+ "+\twhile (READ_ONCE(console_waiter))\n"
+ "+\t\tcpu_relax();\n"
+ "+\tspin_release(&console_owner_dep_map, 1, _THIS_IP_);\n"
+ "+\n"
+ "+\tprintk_safe_exit_irqrestore(flags);\n"
+ "+\t/*\n"
+ "+\t * The owner passed the console lock to us.\n"
+ "+\t * Since we did not spin on console lock, annotate\n"
+ "+\t * this as a trylock. Otherwise lockdep will\n"
+ "+\t * complain.\n"
+ "+\t */\n"
+ "+\tmutex_acquire(&console_lock_dep_map, 0, 1, _THIS_IP_);\n"
+ "+\n"
+ "+\treturn 1;\n"
+ "+}\n"
+ "+\n"
+ "+/*\n"
+ "  * Call the console drivers, asking them to write out\n"
+ "  * log_buf[start] to log_buf[end - 1].\n"
+ "  * The console_lock must be held.\n"
+ "@@ -1760,56 +1893,8 @@ asmlinkage int vprintk_emit(int facility, int level,\n"
+ " \t\t * semaphore.  The release will print out buffers and wake up\n"
+ " \t\t * /dev/kmsg and syslog() users.\n"
+ " \t\t */\n"
+ "-\t\tif (console_trylock()) {\n"
+ "+\t\tif (console_trylock_spinning())\n"
+ " \t\t\tconsole_unlock();\n"
+ "-\t\t} else {\n"
+ "-\t\t\tstruct task_struct *owner = NULL;\n"
+ "-\t\t\tbool waiter;\n"
+ "-\t\t\tbool spin = false;\n"
+ "-\n"
+ "-\t\t\tprintk_safe_enter_irqsave(flags);\n"
+ "-\n"
+ "-\t\t\traw_spin_lock(&console_owner_lock);\n"
+ "-\t\t\towner = READ_ONCE(console_owner);\n"
+ "-\t\t\twaiter = READ_ONCE(console_waiter);\n"
+ "-\t\t\tif (!waiter && owner && owner != current) {\n"
+ "-\t\t\t\tWRITE_ONCE(console_waiter, true);\n"
+ "-\t\t\t\tspin = true;\n"
+ "-\t\t\t}\n"
+ "-\t\t\traw_spin_unlock(&console_owner_lock);\n"
+ "-\n"
+ "-\t\t\t/*\n"
+ "-\t\t\t * If there is an active printk() writing to the\n"
+ "-\t\t\t * consoles, instead of having it write our data too,\n"
+ "-\t\t\t * see if we can offload that load from the active\n"
+ "-\t\t\t * printer, and do some printing ourselves.\n"
+ "-\t\t\t * Go into a spin only if there isn't already a waiter\n"
+ "-\t\t\t * spinning, and there is an active printer, and\n"
+ "-\t\t\t * that active printer isn't us (recursive printk?).\n"
+ "-\t\t\t */\n"
+ "-\t\t\tif (spin) {\n"
+ "-\t\t\t\t/* We spin waiting for the owner to release us */\n"
+ "-\t\t\t\tspin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_);\n"
+ "-\t\t\t\t/* Owner will clear console_waiter on hand off */\n"
+ "-\t\t\t\twhile (READ_ONCE(console_waiter))\n"
+ "-\t\t\t\t\tcpu_relax();\n"
+ "-\n"
+ "-\t\t\t\tspin_release(&console_owner_dep_map, 1, _THIS_IP_);\n"
+ "-\t\t\t\tprintk_safe_exit_irqrestore(flags);\n"
+ "-\n"
+ "-\t\t\t\t/*\n"
+ "-\t\t\t\t * The owner passed the console lock to us.\n"
+ "-\t\t\t\t * Since we did not spin on console lock, annotate\n"
+ "-\t\t\t\t * this as a trylock. Otherwise lockdep will\n"
+ "-\t\t\t\t * complain.\n"
+ "-\t\t\t\t */\n"
+ "-\t\t\t\tmutex_acquire(&console_lock_dep_map, 0, 1, _THIS_IP_);\n"
+ "-\t\t\t\tconsole_unlock();\n"
+ "-\t\t\t\tprintk_safe_enter_irqsave(flags);\n"
+ "-\t\t\t}\n"
+ "-\t\t\tprintk_safe_exit_irqrestore(flags);\n"
+ "-\n"
+ "-\t\t}\n"
+ " \t}\n"
+ " \n"
+ " \treturn printed_len;\n"
+ "@@ -1910,6 +1995,8 @@ static ssize_t msg_print_ext_header(char *buf, size_t size,\n"
+ " static ssize_t msg_print_ext_body(char *buf, size_t size,\n"
+ " \t\t\t\t  char *dict, size_t dict_len,\n"
+ " \t\t\t\t  char *text, size_t text_len) { return 0; }\n"
+ "+static void console_lock_spinning_enable(void) { }\n"
+ "+static int console_lock_spinning_disable_and_check(void) { return 0; }\n"
+ " static void call_console_drivers(const char *ext_text, size_t ext_len,\n"
+ " \t\t\t\t const char *text, size_t len) {}\n"
+ " static size_t msg_print_text(const struct printk_log *msg,\n"
+ "@@ -2196,7 +2283,6 @@ void console_unlock(void)\n"
+ " \tstatic u64 seen_seq;\n"
+ " \tunsigned long flags;\n"
+ " \tbool wake_klogd = false;\n"
+ "-\tbool waiter = false;\n"
+ " \tbool do_cond_resched, retry;\n"
+ " \n"
+ " \tif (console_suspended) {\n"
+ "@@ -2291,31 +2377,16 @@ void console_unlock(void)\n"
+ " \t\t * finish. This task can not be preempted if there is a\n"
+ " \t\t * waiter waiting to take over.\n"
+ " \t\t */\n"
+ "-\t\traw_spin_lock(&console_owner_lock);\n"
+ "-\t\tconsole_owner = current;\n"
+ "-\t\traw_spin_unlock(&console_owner_lock);\n"
+ "-\n"
+ "-\t\t/* The waiter may spin on us after setting console_owner */\n"
+ "-\t\tspin_acquire(&console_owner_dep_map, 0, 0, _THIS_IP_);\n"
+ "+\t\tconsole_lock_spinning_enable();\n"
+ " \n"
+ " \t\tstop_critical_timings();\t/* don't trace print latency */\n"
+ " \t\tcall_console_drivers(ext_text, ext_len, text, len);\n"
+ " \t\tstart_critical_timings();\n"
+ " \n"
+ "-\t\traw_spin_lock(&console_owner_lock);\n"
+ "-\t\twaiter = READ_ONCE(console_waiter);\n"
+ "-\t\tconsole_owner = NULL;\n"
+ "-\t\traw_spin_unlock(&console_owner_lock);\n"
+ "-\n"
+ "-\t\t/*\n"
+ "-\t\t * If there is a waiter waiting for us, then pass the\n"
+ "-\t\t * rest of the work load over to that waiter.\n"
+ "-\t\t */\n"
+ "-\t\tif (waiter)\n"
+ "-\t\t\tbreak;\n"
+ "-\n"
+ "-\t\t/* There was no waiter, and nothing will spin on us here */\n"
+ "-\t\tspin_release(&console_owner_dep_map, 1, _THIS_IP_);\n"
+ "+\t\tif (console_lock_spinning_disable_and_check()) {\n"
+ "+\t\t\tprintk_safe_exit_irqrestore(flags);\n"
+ "+\t\t\treturn;\n"
+ "+\t\t}\n"
+ " \n"
+ " \t\tprintk_safe_exit_irqrestore(flags);\n"
+ " \n"
+ "@@ -2323,26 +2394,6 @@ void console_unlock(void)\n"
+ " \t\t\tcond_resched();\n"
+ " \t}\n"
+ " \n"
+ "-\t/*\n"
+ "-\t * If there is an active waiter waiting on the console_lock.\n"
+ "-\t * Pass off the printing to the waiter, and the waiter\n"
+ "-\t * will continue printing on its CPU, and when all writing\n"
+ "-\t * has finished, the last printer will wake up klogd.\n"
+ "-\t */\n"
+ "-\tif (waiter) {\n"
+ "-\t\tWRITE_ONCE(console_waiter, false);\n"
+ "-\t\t/* The waiter is now free to continue */\n"
+ "-\t\tspin_release(&console_owner_dep_map, 1, _THIS_IP_);\n"
+ "-\t\t/*\n"
+ "-\t\t * Hand off console_lock to waiter. The waiter will perform\n"
+ "-\t\t * the up(). After this, the waiter is the console_lock owner.\n"
+ "-\t\t */\n"
+ "-\t\tmutex_release(&console_lock_dep_map, 1, _THIS_IP_);\n"
+ "-\t\tprintk_safe_exit_irqrestore(flags);\n"
+ "-\t\t/* Note, if waiter is set, logbuf_lock is not held */\n"
+ "-\t\treturn;\n"
+ "-\t}\n"
+ "-\n"
+ " \tconsole_locked = 0;\n"
+ " \n"
+ " \t/* Release the exclusive_console once it is used */\n"
+ "-- \n"
+ 2.13.6
 
-31b535994a49e1f798a9028fd0f3e3d0419e0f717c3974925e1bfa4ac48024f2
+a82f90847ffe916f68bade48cfee9744c902a4f93fc5d5bc107b4d11065347b1

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.