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.