diff options
author | Hidetoshi Shimokawa <simokawa@FreeBSD.org> | 2007-09-20 04:05:59 +0000 |
---|---|---|
committer | Hidetoshi Shimokawa <simokawa@FreeBSD.org> | 2007-09-20 04:05:59 +0000 |
commit | a69d19dc330fd7a70921421c89df368b72205b1a (patch) | |
tree | d4d285641f612617591a96f5e87f5577604016be | |
parent | 5bcb64f20afff21be511cc5ae2bb6d91a4eeb431 (diff) | |
download | src-a69d19dc330fd7a70921421c89df368b72205b1a.tar.gz src-a69d19dc330fd7a70921421c89df368b72205b1a.zip |
Serialize output routine of terminal emulator (te_puts()) by a lock.
- The output routine of low level console is not protected by any lock
by default.
- Increment and decrement of sc->write_in_progress are not atomic and
this may cause console hang.
- We also have many other states used by emulator that should be protected
by the lock.
- This change does not fix interspersed messages which PRINTF_BUFR_SIZE
kernel option should fix.
Approved by: re (bmah)
MFC after: 1 week
Notes
Notes:
svn path=/head/; revision=172250
-rw-r--r-- | sys/dev/syscons/syscons.c | 14 | ||||
-rw-r--r-- | sys/dev/syscons/syscons.h | 1 |
2 files changed, 14 insertions, 1 deletions
diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index 9fc4c3cc1e0f..04ad041dec3f 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -2510,14 +2510,23 @@ exchange_scr(sc_softc_t *sc) void sc_puts(scr_stat *scp, u_char *buf, int len) { + int need_unlock = 0; + #ifdef DEV_SPLASH /* make screensaver happy */ if (!sticky_splash && scp == scp->sc->cur_scp && !sc_saver_keyb_only) run_scrn_saver = FALSE; #endif - if (scp->tsw) + if (scp->tsw) { + if (!kdb_active && !mtx_owned(&scp->scr_lock)) { + need_unlock = 1; + mtx_lock_spin(&scp->scr_lock); + } (*scp->tsw->te_puts)(scp, buf, len); + if (need_unlock) + mtx_unlock_spin(&scp->scr_lock); + } if (scp->sc->delayed_next_scr) sc_switch_scr(scp->sc, scp->sc->delayed_next_scr - 1); @@ -2895,6 +2904,7 @@ scterm(int unit, int flags) (*scp->tsw->te_term)(scp, &scp->ts); if (scp->ts != NULL) free(scp->ts, M_DEVBUF); + mtx_destroy(&scp->scr_lock); /* clear the structure */ if (!(flags & SC_KERNEL_CONSOLE)) { @@ -3078,6 +3088,8 @@ init_scp(sc_softc_t *sc, int vty, scr_stat *scp) scp->history = NULL; scp->history_pos = 0; scp->history_size = 0; + + mtx_init(&scp->scr_lock, "scrlock", NULL, MTX_SPIN); } int diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h index 089adf2b1fb1..53e5ab7b4bc0 100644 --- a/sys/dev/syscons/syscons.h +++ b/sys/dev/syscons/syscons.h @@ -333,6 +333,7 @@ typedef struct scr_stat { int splash_save_mode; /* saved mode for splash screen */ int splash_save_status; /* saved status for splash screen */ + struct mtx scr_lock; /* mutex for sc_puts() */ #ifdef _SCR_MD_STAT_DECLARED_ scr_md_stat_t md; /* machine dependent vars */ #endif |