Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'rework/preempt-legacy-kthread' into for-linus

+123 -71
+123 -71
kernel/printk/printk.c
··· 3134 3134 3135 3135 #endif /* CONFIG_PRINTK */ 3136 3136 3137 + 3138 + /* 3139 + * Print out one record for each console. 3140 + * 3141 + * @do_cond_resched is set by the caller. It can be true only in schedulable 3142 + * context. 3143 + * 3144 + * @next_seq is set to the sequence number after the last available record. 3145 + * The value is valid only when all usable consoles were flushed. It is 3146 + * when the function returns true (can do the job) and @try_again parameter 3147 + * is set to false, see below. 3148 + * 3149 + * @handover will be set to true if a printk waiter has taken over the 3150 + * console_lock, in which case the caller is no longer holding the 3151 + * console_lock. Otherwise it is set to false. 3152 + * 3153 + * @try_again will be set to true when it still makes sense to call this 3154 + * function again. The function could do the job, see the return value. 3155 + * And some consoles still make progress. 3156 + * 3157 + * Returns true when the function could do the job. Some consoles are usable, 3158 + * and there was no takeover and no panic_on_other_cpu(). 3159 + * 3160 + * Requires the console_lock. 3161 + */ 3162 + static bool console_flush_one_record(bool do_cond_resched, u64 *next_seq, bool *handover, 3163 + bool *try_again) 3164 + { 3165 + struct console_flush_type ft; 3166 + bool any_usable = false; 3167 + struct console *con; 3168 + int cookie; 3169 + 3170 + *try_again = false; 3171 + 3172 + printk_get_console_flush_type(&ft); 3173 + 3174 + cookie = console_srcu_read_lock(); 3175 + for_each_console_srcu(con) { 3176 + short flags = console_srcu_read_flags(con); 3177 + u64 printk_seq; 3178 + bool progress; 3179 + 3180 + /* 3181 + * console_flush_one_record() is only responsible for 3182 + * nbcon consoles when the nbcon consoles cannot print via 3183 + * their atomic or threaded flushing. 3184 + */ 3185 + if ((flags & CON_NBCON) && (ft.nbcon_atomic || ft.nbcon_offload)) 3186 + continue; 3187 + 3188 + if (!console_is_usable(con, flags, !do_cond_resched)) 3189 + continue; 3190 + any_usable = true; 3191 + 3192 + if (flags & CON_NBCON) { 3193 + progress = nbcon_legacy_emit_next_record(con, handover, cookie, 3194 + !do_cond_resched); 3195 + printk_seq = nbcon_seq_read(con); 3196 + } else { 3197 + progress = console_emit_next_record(con, handover, cookie); 3198 + printk_seq = con->seq; 3199 + } 3200 + 3201 + /* 3202 + * If a handover has occurred, the SRCU read lock 3203 + * is already released. 3204 + */ 3205 + if (*handover) 3206 + goto fail; 3207 + 3208 + /* Track the next of the highest seq flushed. */ 3209 + if (printk_seq > *next_seq) 3210 + *next_seq = printk_seq; 3211 + 3212 + if (!progress) 3213 + continue; 3214 + 3215 + /* 3216 + * An usable console made a progress. There might still be 3217 + * pending messages. 3218 + */ 3219 + *try_again = true; 3220 + 3221 + /* Allow panic_cpu to take over the consoles safely. */ 3222 + if (panic_on_other_cpu()) 3223 + goto fail_srcu; 3224 + 3225 + if (do_cond_resched) 3226 + cond_resched(); 3227 + } 3228 + console_srcu_read_unlock(cookie); 3229 + 3230 + return any_usable; 3231 + 3232 + fail_srcu: 3233 + console_srcu_read_unlock(cookie); 3234 + fail: 3235 + *try_again = false; 3236 + return false; 3237 + } 3238 + 3137 3239 /* 3138 3240 * Print out all remaining records to all consoles. 3139 3241 * ··· 3261 3159 */ 3262 3160 static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handover) 3263 3161 { 3264 - struct console_flush_type ft; 3265 - bool any_usable = false; 3266 - struct console *con; 3267 - bool any_progress; 3268 - int cookie; 3162 + bool try_again; 3163 + bool ret; 3269 3164 3270 3165 *next_seq = 0; 3271 3166 *handover = false; 3272 3167 3273 3168 do { 3274 - any_progress = false; 3169 + ret = console_flush_one_record(do_cond_resched, next_seq, 3170 + handover, &try_again); 3171 + } while (try_again); 3275 3172 3276 - printk_get_console_flush_type(&ft); 3277 - 3278 - cookie = console_srcu_read_lock(); 3279 - for_each_console_srcu(con) { 3280 - short flags = console_srcu_read_flags(con); 3281 - u64 printk_seq; 3282 - bool progress; 3283 - 3284 - /* 3285 - * console_flush_all() is only responsible for nbcon 3286 - * consoles when the nbcon consoles cannot print via 3287 - * their atomic or threaded flushing. 3288 - */ 3289 - if ((flags & CON_NBCON) && (ft.nbcon_atomic || ft.nbcon_offload)) 3290 - continue; 3291 - 3292 - if (!console_is_usable(con, flags, !do_cond_resched)) 3293 - continue; 3294 - any_usable = true; 3295 - 3296 - if (flags & CON_NBCON) { 3297 - progress = nbcon_legacy_emit_next_record(con, handover, cookie, 3298 - !do_cond_resched); 3299 - printk_seq = nbcon_seq_read(con); 3300 - } else { 3301 - progress = console_emit_next_record(con, handover, cookie); 3302 - printk_seq = con->seq; 3303 - } 3304 - 3305 - /* 3306 - * If a handover has occurred, the SRCU read lock 3307 - * is already released. 3308 - */ 3309 - if (*handover) 3310 - return false; 3311 - 3312 - /* Track the next of the highest seq flushed. */ 3313 - if (printk_seq > *next_seq) 3314 - *next_seq = printk_seq; 3315 - 3316 - if (!progress) 3317 - continue; 3318 - any_progress = true; 3319 - 3320 - /* Allow panic_cpu to take over the consoles safely. */ 3321 - if (panic_on_other_cpu()) 3322 - goto abandon; 3323 - 3324 - if (do_cond_resched) 3325 - cond_resched(); 3326 - } 3327 - console_srcu_read_unlock(cookie); 3328 - } while (any_progress); 3329 - 3330 - return any_usable; 3331 - 3332 - abandon: 3333 - console_srcu_read_unlock(cookie); 3334 - return false; 3173 + return ret; 3335 3174 } 3336 3175 3337 3176 static void __console_flush_and_unlock(void) ··· 3640 3597 3641 3598 static int legacy_kthread_func(void *unused) 3642 3599 { 3643 - for (;;) { 3644 - wait_event_interruptible(legacy_wait, legacy_kthread_should_wakeup()); 3600 + bool try_again; 3601 + 3602 + wait_for_event: 3603 + wait_event_interruptible(legacy_wait, legacy_kthread_should_wakeup()); 3604 + 3605 + do { 3606 + bool handover = false; 3607 + u64 next_seq = 0; 3645 3608 3646 3609 if (kthread_should_stop()) 3647 - break; 3610 + return 0; 3648 3611 3649 3612 console_lock(); 3650 - __console_flush_and_unlock(); 3651 - } 3613 + console_flush_one_record(true, &next_seq, &handover, &try_again); 3614 + if (!handover) 3615 + __console_unlock(); 3652 3616 3653 - return 0; 3617 + } while (try_again); 3618 + 3619 + goto wait_for_event; 3654 3620 } 3655 3621 3656 3622 static bool legacy_kthread_create(void)