summaryrefslogtreecommitdiffstats
path: root/sys/dev/syscons
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2006-09-13 15:48:15 +0000
committerscottl <scottl@FreeBSD.org>2006-09-13 15:48:15 +0000
commitae1ca6fd73256507ef9094b93fec5b9760349c20 (patch)
tree3f6091ef6a36694ab3df9980406f14ca618e4170 /sys/dev/syscons
parent3927aa447494d5f1b31035c64ecc9b2ae7401a52 (diff)
downloadFreeBSD-src-ae1ca6fd73256507ef9094b93fec5b9760349c20.zip
FreeBSD-src-ae1ca6fd73256507ef9094b93fec5b9760349c20.tar.gz
Introduce a spinlock for synchronizing access to the video output hardware
in syscons. This replaces a simple access semaphore that was assumed to be protected by Giant but often was not. If two threads that were otherwise SMP-safe called printf at the same time, there was a high likelyhood that the semaphore would get corrupted and result in a permanently frozen video console. This is similar to what is already done in the serial console drivers.
Diffstat (limited to 'sys/dev/syscons')
-rw-r--r--sys/dev/syscons/scmouse.c8
-rw-r--r--sys/dev/syscons/syscons.c31
-rw-r--r--sys/dev/syscons/syscons.h18
3 files changed, 38 insertions, 19 deletions
diff --git a/sys/dev/syscons/scmouse.c b/sys/dev/syscons/scmouse.c
index 73455f3..54ca2ec 100644
--- a/sys/dev/syscons/scmouse.c
+++ b/sys/dev/syscons/scmouse.c
@@ -178,13 +178,13 @@ sc_draw_mouse_image(scr_stat *scp)
if (ISGRAPHSC(scp))
return;
- ++scp->sc->videoio_in_progress;
+ SC_VIDEO_LOCK(scp->sc);
(*scp->rndr->draw_mouse)(scp, scp->mouse_xpos, scp->mouse_ypos, TRUE);
scp->mouse_oldpos = scp->mouse_pos;
scp->mouse_oldxpos = scp->mouse_xpos;
scp->mouse_oldypos = scp->mouse_ypos;
scp->status |= MOUSE_VISIBLE;
- --scp->sc->videoio_in_progress;
+ SC_VIDEO_UNLOCK(scp->sc);
}
void
@@ -196,7 +196,7 @@ sc_remove_mouse_image(scr_stat *scp)
if (ISGRAPHSC(scp))
return;
- ++scp->sc->videoio_in_progress;
+ SC_VIDEO_LOCK(scp->sc);
(*scp->rndr->draw_mouse)(scp,
(scp->mouse_oldpos%scp->xsize + scp->xoff)
* scp->font_width,
@@ -217,7 +217,7 @@ sc_remove_mouse_image(scr_stat *scp)
}
#endif /* PC98 */
scp->status &= ~MOUSE_VISIBLE;
- --scp->sc->videoio_in_progress;
+ SC_VIDEO_UNLOCK(scp->sc);
}
int
diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c
index c42fcf8..08f8e90 100644
--- a/sys/dev/syscons/syscons.c
+++ b/sys/dev/syscons/syscons.c
@@ -1578,7 +1578,7 @@ sccnupdate(scr_stat *scp)
{
/* this is a cut-down version of scrn_timer()... */
- if (scp->sc->font_loading_in_progress || scp->sc->videoio_in_progress)
+ if (scp->sc->font_loading_in_progress)
return;
if (debugger > 0 || panicstr || shutdown_in_progress) {
@@ -1628,7 +1628,7 @@ scrn_timer(void *arg)
return;
/* don't do anything when we are performing some I/O operations */
- if (sc->font_loading_in_progress || sc->videoio_in_progress) {
+ if (sc->font_loading_in_progress) {
if (again)
timeout(scrn_timer, sc, hz / 10);
return;
@@ -1722,7 +1722,7 @@ scrn_update(scr_stat *scp, int show_cursor)
/* assert(scp == scp->sc->cur_scp) */
- ++scp->sc->videoio_in_progress;
+ SC_VIDEO_LOCK(scp->sc);
#ifndef SC_NO_CUTPASTE
/* remove the previous mouse pointer image if necessary */
@@ -1792,7 +1792,7 @@ scrn_update(scr_stat *scp, int show_cursor)
if (!show_cursor) {
scp->end = 0;
scp->start = scp->xsize*scp->ysize - 1;
- --scp->sc->videoio_in_progress;
+ SC_VIDEO_UNLOCK(scp->sc);
return;
}
@@ -1831,7 +1831,7 @@ scrn_update(scr_stat *scp, int show_cursor)
scp->end = 0;
scp->start = scp->xsize*scp->ysize - 1;
- --scp->sc->videoio_in_progress;
+ SC_VIDEO_UNLOCK(scp->sc);
}
#ifdef DEV_SPLASH
@@ -2094,7 +2094,7 @@ sc_switch_scr(sc_softc_t *sc, u_int next_scr)
/* delay switch if the screen is blanked or being updated */
if ((sc->flags & SC_SCRN_BLANKED) || sc->write_in_progress
- || sc->blink_in_progress || sc->videoio_in_progress) {
+ || sc->blink_in_progress) {
sc->delayed_next_scr = next_scr + 1;
sc_touch_scrn_saver();
DPRINTF(5, ("switch delayed\n"));
@@ -2452,23 +2452,23 @@ void
sc_draw_cursor_image(scr_stat *scp)
{
/* assert(scp == scp->sc->cur_scp); */
- ++scp->sc->videoio_in_progress;
+ SC_VIDEO_LOCK(scp->sc);
(*scp->rndr->draw_cursor)(scp, scp->cursor_pos,
scp->curs_attr.flags & CONS_BLINK_CURSOR, TRUE,
sc_inside_cutmark(scp, scp->cursor_pos));
scp->cursor_oldpos = scp->cursor_pos;
- --scp->sc->videoio_in_progress;
+ SC_VIDEO_UNLOCK(scp->sc);
}
void
sc_remove_cursor_image(scr_stat *scp)
{
/* assert(scp == scp->sc->cur_scp); */
- ++scp->sc->videoio_in_progress;
+ SC_VIDEO_LOCK(scp->sc);
(*scp->rndr->draw_cursor)(scp, scp->cursor_oldpos,
scp->curs_attr.flags & CONS_BLINK_CURSOR, FALSE,
sc_inside_cutmark(scp, scp->cursor_oldpos));
- --scp->sc->videoio_in_progress;
+ SC_VIDEO_UNLOCK(scp->sc);
}
static void
@@ -2499,10 +2499,10 @@ sc_set_cursor_image(scr_stat *scp)
}
/* assert(scp == scp->sc->cur_scp); */
- ++scp->sc->videoio_in_progress;
+ SC_VIDEO_LOCK(scp->sc);
(*scp->rndr->set_cursor)(scp, scp->curs_attr.base, scp->curs_attr.height,
scp->curs_attr.flags & CONS_BLINK_CURSOR);
- --scp->sc->videoio_in_progress;
+ SC_VIDEO_UNLOCK(scp->sc);
}
static void
@@ -2606,6 +2606,9 @@ scinit(int unit, int flags)
* disappeared...
*/
sc = sc_get_softc(unit, flags & SC_KERNEL_CONSOLE);
+ if ((sc->flags & SC_INIT_DONE) == 0)
+ SC_VIDEO_LOCKINIT(sc);
+
adp = NULL;
if (sc->adapter >= 0) {
vid_release(sc->adp, (void *)&sc->adapter);
@@ -3458,9 +3461,9 @@ set_mode(scr_stat *scp)
void
sc_set_border(scr_stat *scp, int color)
{
- ++scp->sc->videoio_in_progress;
+ SC_VIDEO_LOCK(scp->sc);
(*scp->rndr->draw_border)(scp, color);
- --scp->sc->videoio_in_progress;
+ SC_VIDEO_UNLOCK(scp->sc);
}
#ifndef SC_NO_FONT_LOADING
diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h
index 1cd33b2..089adf2 100644
--- a/sys/dev/syscons/syscons.h
+++ b/sys/dev/syscons/syscons.h
@@ -34,6 +34,9 @@
#ifndef _DEV_SYSCONS_SYSCONS_H_
#define _DEV_SYSCONS_SYSCONS_H_
+#include <sys/lock.h>
+#include <sys/mutex.h>
+
/* machine-dependent part of the header */
#ifdef PC98
@@ -225,9 +228,9 @@ typedef struct sc_softc {
char font_loading_in_progress;
char switch_in_progress;
- char videoio_in_progress;
char write_in_progress;
char blink_in_progress;
+ struct mtx video_mtx;
long scrn_time_stamp;
@@ -532,6 +535,19 @@ typedef struct {
#define kbd_poll(kbd, on) \
(*kbdsw[(kbd)->kb_index]->poll)((kbd), (on))
+#define SC_VIDEO_LOCKINIT(sc) \
+ mtx_init(&(sc)->video_mtx, "syscons video lock", NULL,MTX_SPIN);
+#define SC_VIDEO_LOCK(sc) \
+ do { \
+ if (!cold) \
+ mtx_lock_spin(&(sc)->video_mtx); \
+ } while(0)
+#define SC_VIDEO_UNLOCK(sc) \
+ do { \
+ if (!cold) \
+ mtx_unlock_spin(&(sc)->video_mtx); \
+ } while(0)
+
/* syscons.c */
extern int (*sc_user_ioctl)(struct cdev *dev, u_long cmd, caddr_t data,
int flag, struct thread *td);
OpenPOWER on IntegriCloud