Messages in this thread | | | From | John Ogness <> | Subject | Re: [patch RFC 20/29] printk: Add non-BKL console acquire/release logic | Date | Tue, 27 Sep 2022 15:55:24 +0206 |
| |
Below is a fix that was used for the LPC2022 demo so that a hostile takeover upon timeout is possible.
On 2022-09-11, Thomas Gleixner <tglx@linutronix.de> wrote: > --- a/kernel/printk/printk_nobkl.c > +++ b/kernel/printk/printk_nobkl.c > +/** > + * __cons_try_acquire - Try to acquire the console for printk output > + * @ctxt: Pointer to an aquire context which contains > + * all information about the acquire mode > + * > + * Returns: True if the acquire was successful. False on fail. > + * > + * In case of success @ctxt->state contains the acquisition > + * state. > + * > + * In case of fail @ctxt->old_state contains the state > + * which was read from @con->state for analysis by the caller. > + */ > +static bool __cons_try_acquire(struct cons_context *ctxt) > +{ > + struct console *con = ctxt->console; > + unsigned int cpu = smp_processor_id(); > + struct cons_state old, new; > + > + if (WARN_ON_ONCE(!(con->flags & CON_NO_BKL))) > + return false; > + > + cons_state_read(con, STATE_REAL, &old); > + > +again: > + if (cons_check_panic()) > + return false; > + > + /* Preserve it for the caller and for spinwait */ > + copy_full_state(ctxt->old_state, old); > + > + if (!cons_state_ok(old)) > + return false; > + > + /* Set up the new state for takeover */ > + copy_full_state(new, old); > + new.locked = 1; > + new.thread = ctxt->thread; > + new.cur_prio = ctxt->prio; > + new.req_prio = CONS_PRIO_NONE; > + new.cpu = cpu; > + > + /* Attempt to acquire it directly if unlocked */ > + if (!old.locked) { > + if (!cons_state_try_cmpxchg(con, STATE_REAL, &old, &new)) > + goto again; > + > + ctxt->hostile = false; > + copy_full_state(ctxt->state, new); > + goto success; > + } > + > + /* > + * Give up if the calling context is the printk thread. The > + * atomic writer will wake the thread when it is done with > + * the important output. > + */ > + if (ctxt->thread) > + return false; > + > + /* > + * If the active context is on the same CPU then there is > + * obviously no handshake possible. > + */ > + if (old.cpu == cpu) > + goto check_hostile; > + > + /* > + * If the caller did not request spin-waiting or a request with the > + * same or higher priority is pending then check whether a hostile > + * takeover is due. > + */ > + if (!ctxt->spinwait || old.req_prio >= ctxt->prio) > + goto check_hostile; > + > + /* Proceed further with spin acquire */ > + if (!cons_setup_handover(ctxt)) > + return false; > + > + /* > + * Setup the request in state[REAL]. Hand in the state, which was > + * used to make the decision to spinwait above, for comparison. > + */ > + if (!cons_setup_request(ctxt, old)) > + return false; > + > + /* Now spin on it */ > + if (!cons_try_acquire_spin(ctxt)) > + return false;
Instead of returning false here, it needs to:
goto check_hostile;
cons_try_acquire_spin() may have failed due to a timeout, in which case a hostile takeover might be necessary.
> +success: > + /* Common updates on success */ > + return true; > + > +check_hostile: > + if (!ctxt->hostile) > + return false; > + > + if (!cons_state_try_cmpxchg(con, STATE_REAL, &old, &new)) > + goto again; > + > + ctxt->hostile = true; > + copy_full_state(ctxt->state, new); > + goto success; > +}
John Ogness
| |