Module Name:    src
Committed By:   jmcneill
Date:           Sun Jan 17 16:51:12 UTC 2021

Modified Files:
        src/sys/dev/wscons: wsdisplay_vcons.c

Log Message:
The change from config_interrupts to a kthread for VCONS_DRAW_INTR init
unfortunately makes it easier to trigger a race that results in characters
not being erased properly at boot. Work around the original issue a
different way by creating a fake device_t and defer initialization until
we are sure that config_interrupt threads are done. This is not ideal and
the race is still present but fixing this properly would require a rewrite
to make this code MP-safe.


To generate a diff of this commit:
cvs rdiff -u -r1.45 -r1.46 src/sys/dev/wscons/wsdisplay_vcons.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/wscons/wsdisplay_vcons.c
diff -u src/sys/dev/wscons/wsdisplay_vcons.c:1.45 src/sys/dev/wscons/wsdisplay_vcons.c:1.46
--- src/sys/dev/wscons/wsdisplay_vcons.c:1.45	Sat Jan  2 03:00:56 2021
+++ src/sys/dev/wscons/wsdisplay_vcons.c	Sun Jan 17 16:51:12 2021
@@ -1,4 +1,4 @@
-/*	$NetBSD: wsdisplay_vcons.c,v 1.45 2021/01/02 03:00:56 macallan Exp $ */
+/*	$NetBSD: wsdisplay_vcons.c,v 1.46 2021/01/17 16:51:12 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2005, 2006 Michael Lorenz
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: wsdisplay_vcons.c,v 1.45 2021/01/02 03:00:56 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: wsdisplay_vcons.c,v 1.46 2021/01/17 16:51:12 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -121,7 +121,7 @@ static void vcons_unlock(struct vcons_sc
 #ifdef VCONS_DRAW_INTR
 static void vcons_intr(void *);
 static void vcons_softintr(void *);
-static void vcons_init_thread(void *);
+static int vcons_intr_enable(device_t);
 #endif
 
 int
@@ -180,11 +180,16 @@ vcons_init(struct vcons_data *vd, void *
 	callout_setfunc(&vd->intr, vcons_intr, vd);
 	vd->intr_valid = 1;
 
-	if (kthread_create(PRI_NONE, 0, NULL, vcons_init_thread, vd, NULL,
-	    "vcons_init") != 0) {
-		printf("%s: unable to create thread.\n", __func__);
-		return -1;
-	}
+	/*
+	 * Defer intr drawing until after autoconfiguration has completed
+	 * to serialize device attachment messages w/ the initial screen
+	 * redraw as a workaround for the lack of MP-safeness in this
+	 * subsystem. To register with autoconf, we need to create a fake
+	 * device_t and pass that in as a handle to config_interrupts.
+	 */
+	snprintf(vd->fake_dev.dv_xname, sizeof(vd->fake_dev.dv_xname), "vcons");
+	vd->fake_dev.dv_private = vd;
+	config_finalize_register(&vd->fake_dev, vcons_intr_enable);
 #endif
 	return 0;
 }
@@ -1493,14 +1498,15 @@ vcons_softintr(void *cookie)
 	callout_schedule(&vd->intr, mstohz(33));
 }
 
-static void
-vcons_init_thread(void *cookie)
+static int
+vcons_intr_enable(device_t fake_dev)
 {
-	struct vcons_data *vd = (struct vcons_data *)cookie;
+	struct vcons_data *vd = device_private(fake_dev);
 
 	vd->use_intr = 2;
 	callout_schedule(&vd->intr, mstohz(33));
-	kthread_exit(0);
+
+	return 0;
 }
 #endif /* VCONS_DRAW_INTR */
 

Reply via email to