Index: sys/dev/vt/vt.h =================================================================== --- sys/dev/vt/vt.h +++ sys/dev/vt/vt.h @@ -172,7 +172,7 @@ #define VT_LOCK_ASSERT(vd, what) mtx_assert(&(vd)->vd_lock, what) void vt_resume(struct vt_device *vd); -void vt_resume_flush_timer(struct vt_device *vd, int ms); +void vt_resume_flush_timer(struct vt_window *vw, int ms); void vt_suspend(struct vt_device *vd); /* @@ -213,8 +213,10 @@ #define VBF_DEFAULT_HISTORY_SIZE 500 #endif +void vtbuf_lock(struct vt_buf *); +void vtbuf_unlock(struct vt_buf *); void vtbuf_copy(struct vt_buf *, const term_rect_t *, const term_pos_t *); -void vtbuf_fill_locked(struct vt_buf *, const term_rect_t *, term_char_t); +void vtbuf_fill(struct vt_buf *, const term_rect_t *, term_char_t); void vtbuf_init_early(struct vt_buf *); void vtbuf_init(struct vt_buf *, const term_pos_t *); void vtbuf_grow(struct vt_buf *, const term_pos_t *, unsigned int); Index: sys/dev/vt/vt_buf.c =================================================================== --- sys/dev/vt/vt_buf.c +++ sys/dev/vt/vt_buf.c @@ -253,8 +253,22 @@ return (0); } -static inline void -vtbuf_dirty_locked(struct vt_buf *vb, const term_rect_t *area) +void +vtbuf_lock(struct vt_buf *vb) +{ + + VTBUF_LOCK(vb); +} + +void +vtbuf_unlock(struct vt_buf *vb) +{ + + VTBUF_UNLOCK(vb); +} + +void +vtbuf_dirty(struct vt_buf *vb, const term_rect_t *area) { if (vb->vb_dirtyrect.tr_begin.tp_row > area->tr_begin.tp_row) @@ -267,24 +281,15 @@ vb->vb_dirtyrect.tr_end.tp_col = area->tr_end.tp_col; } -void -vtbuf_dirty(struct vt_buf *vb, const term_rect_t *area) -{ - - VTBUF_LOCK(vb); - vtbuf_dirty_locked(vb, area); - VTBUF_UNLOCK(vb); -} - static inline void -vtbuf_dirty_cell_locked(struct vt_buf *vb, const term_pos_t *p) +vtbuf_dirty_cell(struct vt_buf *vb, const term_pos_t *p) { term_rect_t area; area.tr_begin = *p; area.tr_end.tp_row = p->tp_row + 1; area.tr_end.tp_col = p->tp_col + 1; - vtbuf_dirty_locked(vb, &area); + vtbuf_dirty(vb, &area); } static void @@ -299,10 +304,8 @@ vtbuf_undirty(struct vt_buf *vb, term_rect_t *r) { - VTBUF_LOCK(vb); *r = vb->vb_dirtyrect; vtbuf_make_undirty(vb); - VTBUF_UNLOCK(vb); } void @@ -366,7 +369,7 @@ } static void -vtbuf_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c) +vtbuf_do_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c) { unsigned int pr, pc; term_char_t *row; @@ -381,26 +384,25 @@ } void -vtbuf_fill_locked(struct vt_buf *vb, const term_rect_t *r, term_char_t c) +vtbuf_fill(struct vt_buf *vb, const term_rect_t *r, term_char_t c) { + KASSERT(r->tr_begin.tp_row < vb->vb_scr_size.tp_row, - ("vtbuf_fill_locked begin.tp_row %d must be < screen height %d", + ("vtbuf_fill begin.tp_row %d must be < screen height %d", r->tr_begin.tp_row, vb->vb_scr_size.tp_row)); KASSERT(r->tr_begin.tp_col < vb->vb_scr_size.tp_col, - ("vtbuf_fill_locked begin.tp_col %d must be < screen width %d", + ("vtbuf_fill begin.tp_col %d must be < screen width %d", r->tr_begin.tp_col, vb->vb_scr_size.tp_col)); KASSERT(r->tr_end.tp_row <= vb->vb_scr_size.tp_row, - ("vtbuf_fill_locked end.tp_row %d must be <= screen height %d", + ("vtbuf_fill end.tp_row %d must be <= screen height %d", r->tr_end.tp_row, vb->vb_scr_size.tp_row)); KASSERT(r->tr_end.tp_col <= vb->vb_scr_size.tp_col, - ("vtbuf_fill_locked end.tp_col %d must be <= screen width %d", + ("vtbuf_fill end.tp_col %d must be <= screen width %d", r->tr_end.tp_col, vb->vb_scr_size.tp_col)); - VTBUF_LOCK(vb); - vtbuf_fill(vb, r, c); - vtbuf_dirty_locked(vb, r); - VTBUF_UNLOCK(vb); + vtbuf_do_fill(vb, r, c); + vtbuf_dirty(vb, r); } static void @@ -431,7 +433,7 @@ rect.tr_begin.tp_row = rect.tr_begin.tp_col = 0; rect.tr_end.tp_col = vb->vb_scr_size.tp_col; rect.tr_end.tp_row = vb->vb_history_size; - vtbuf_fill(vb, &rect, VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR)); + vtbuf_do_fill(vb, &rect, VTBUF_SPACE_CHAR(TERMINAL_NORM_ATTR)); vtbuf_make_undirty(vb); if ((vb->vb_flags & VBF_MTX_INIT) == 0) { mtx_init(&vb->vb_lock, "vtbuf", NULL, MTX_SPIN); @@ -645,23 +647,18 @@ row = vb->vb_rows[(vb->vb_curroffset + p->tp_row) % VTBUF_MAX_HEIGHT(vb)]; if (row[p->tp_col] != c) { - VTBUF_LOCK(vb); row[p->tp_col] = c; - vtbuf_dirty_cell_locked(vb, p); - VTBUF_UNLOCK(vb); + vtbuf_dirty_cell(vb, p); } } void vtbuf_cursor_position(struct vt_buf *vb, const term_pos_t *p) { - if (vb->vb_flags & VBF_CURSOR) { - VTBUF_LOCK(vb); - vtbuf_dirty_cell_locked(vb, &vb->vb_cursor); + vtbuf_dirty_cell(vb, &vb->vb_cursor); vb->vb_cursor = *p; - vtbuf_dirty_cell_locked(vb, &vb->vb_cursor); - VTBUF_UNLOCK(vb); + vtbuf_dirty_cell(vb, &vb->vb_cursor); } else { vb->vb_cursor = *p; } @@ -687,7 +684,9 @@ area.tr_end.tp_col = vb->vb_scr_size.tp_col; area.tr_end.tp_row = MAX(s, e) + 1; + VTBUF_LOCK(vb); vtbuf_dirty(vb, &area); + VTBUF_UNLOCK(vb); } } @@ -832,7 +831,7 @@ nflags = vb->vb_flags; if (oflags != nflags) - vtbuf_dirty_cell_locked(vb, &vb->vb_cursor); + vtbuf_dirty_cell(vb, &vb->vb_cursor); VTBUF_UNLOCK(vb); } @@ -850,7 +849,6 @@ nflags = vb->vb_flags; if (oflags != nflags) - vtbuf_dirty_cell_locked(vb, &vb->vb_cursor); + vtbuf_dirty_cell(vb, &vb->vb_cursor); VTBUF_UNLOCK(vb); } - Index: sys/dev/vt/vt_core.c =================================================================== --- sys/dev/vt/vt_core.c +++ sys/dev/vt/vt_core.c @@ -66,6 +66,8 @@ static tc_putchar_t vtterm_putchar; static tc_fill_t vtterm_fill; static tc_copy_t vtterm_copy; +static tc_video_lock_t vtterm_video_lock; +static tc_video_unlock_t vtterm_video_unlock; static tc_param_t vtterm_param; static tc_done_t vtterm_done; @@ -85,6 +87,8 @@ .tc_putchar = vtterm_putchar, .tc_fill = vtterm_fill, .tc_copy = vtterm_copy, + .tc_video_lock = vtterm_video_lock, + .tc_video_unlock = vtterm_video_unlock, .tc_param = vtterm_param, .tc_done = vtterm_done, @@ -285,8 +289,12 @@ } void -vt_resume_flush_timer(struct vt_device *vd, int ms) +vt_resume_flush_timer(struct vt_window *vw, int ms) { + struct vt_device *vd = vw->vw_device; + + if (vd->vd_curwindow != vw) + return; if (!(vd->vd_flags & VDF_ASYNC) || !atomic_cmpset_int(&vd->vd_timer_armed, 0, 1)) @@ -531,14 +539,14 @@ return (0); if (!(vw->vw_flags & (VWF_OPENED|VWF_CONSOLE))) return (EINVAL); - + vd->vd_curwindow = vw; vd->vd_flags |= VDF_INVALID; if (vd->vd_driver->vd_postswitch) vd->vd_driver->vd_postswitch(vd); return (0); } - + VT_LOCK(vd); if (curvw == vw) { /* Nothing to do. */ @@ -560,7 +568,7 @@ if (vd->vd_driver->vd_postswitch) vd->vd_driver->vd_postswitch(vd); - vt_resume_flush_timer(vd, 0); + vt_resume_flush_timer(vw, 0); /* Restore per-window keyboard mode. */ mtx_lock(&Giant); @@ -680,7 +688,7 @@ diff = vthistory_seek(&vw->vw_buf, offset, whence); if (diff) vw->vw_device->vd_flags |= VDF_INVALID; - vt_resume_flush_timer(vw->vw_device, 0); + vt_resume_flush_timer(vw, 0); } static int @@ -1036,7 +1044,6 @@ struct vt_window *vw = tm->tm_softc; vtbuf_cursor_position(&vw->vw_buf, p); - vt_resume_flush_timer(vw->vw_device, 0); } static void @@ -1045,7 +1052,6 @@ struct vt_window *vw = tm->tm_softc; vtbuf_putchar(&vw->vw_buf, p, c); - vt_resume_flush_timer(vw->vw_device, 0); } static void @@ -1053,8 +1059,7 @@ { struct vt_window *vw = tm->tm_softc; - vtbuf_fill_locked(&vw->vw_buf, r, c); - vt_resume_flush_timer(vw->vw_device, 0); + vtbuf_fill(&vw->vw_buf, r, c); } static void @@ -1064,7 +1069,6 @@ struct vt_window *vw = tm->tm_softc; vtbuf_copy(&vw->vw_buf, r, p); - vt_resume_flush_timer(vw->vw_device, 0); } static void @@ -1084,7 +1088,7 @@ /* FALLTHROUGH */ case TP_SHOWCURSOR: vtbuf_cursor_visibility(&vw->vw_buf, arg); - vt_resume_flush_timer(vw->vw_device, 0); + vt_resume_flush_timer(vw, 0); break; case TP_MOUSE: vw->vw_mouse_level = arg; @@ -1142,7 +1146,7 @@ } static void -vt_mark_mouse_position_as_dirty(struct vt_device *vd) +vt_mark_mouse_position_as_dirty(struct vt_device *vd, int locked) { term_rect_t area; struct vt_window *vw; @@ -1175,7 +1179,11 @@ area.tr_end.tp_row = y + 2; } + if (!locked) + vtbuf_lock(&vw->vw_buf); vtbuf_dirty(&vw->vw_buf, &area); + if (!locked) + vtbuf_unlock(&vw->vw_buf); } #endif @@ -1230,6 +1238,8 @@ if (((vd->vd_flags & VDF_TEXTMODE) == 0) && (vf == NULL)) return (0); + vtbuf_lock(&vw->vw_buf); + #ifndef SC_NO_CUTPASTE cursor_was_shown = vd->vd_mshown; cursor_moved = (vd->vd_mx != vd->vd_mx_drawn || @@ -1250,7 +1260,7 @@ */ if (cursor_was_shown != vd->vd_mshown || (vd->vd_mshown && cursor_moved)) - vt_mark_mouse_position_as_dirty(vd); + vt_mark_mouse_position_as_dirty(vd, true); /* * Save position of the mouse cursor. It's used by backends to @@ -1265,7 +1275,7 @@ * mark the new position as dirty. */ if (vd->vd_mshown && cursor_moved) - vt_mark_mouse_position_as_dirty(vd); + vt_mark_mouse_position_as_dirty(vd, true); #endif vtbuf_undirty(&vw->vw_buf, &tarea); @@ -1282,9 +1292,11 @@ if (tarea.tr_begin.tp_col < tarea.tr_end.tp_col) { vd->vd_driver->vd_bitblt_text(vd, vw, &tarea); + vtbuf_unlock(&vw->vw_buf); return (1); } + vtbuf_unlock(&vw->vw_buf); return (0); } @@ -1306,6 +1318,23 @@ } static void +vtterm_video_lock(struct terminal *tm) +{ + struct vt_window *vw = tm->tm_softc; + + vtbuf_lock(&vw->vw_buf); +} + +static void +vtterm_video_unlock(struct terminal *tm) +{ + struct vt_window *vw = tm->tm_softc; + + vtbuf_unlock(&vw->vw_buf); + vt_resume_flush_timer(vw, 0); +} + +static void vtterm_done(struct terminal *tm) { struct vt_window *vw = tm->tm_softc; @@ -1655,7 +1684,7 @@ /* Force a full redraw the next timer tick. */ if (vd->vd_curwindow == vw) { vd->vd_flags |= VDF_INVALID; - vt_resume_flush_timer(vw->vw_device, 0); + vt_resume_flush_timer(vw, 0); } vw->vw_flags &= ~VWF_BUSY; VT_UNLOCK(vd); @@ -1882,7 +1911,7 @@ vd->vd_mx / vf->vf_width, vd->vd_my / vf->vf_height); - vt_resume_flush_timer(vw->vw_device, 0); + vt_resume_flush_timer(vw, 0); return; /* Done */ case MOUSE_BUTTON_EVENT: /* Buttons */ @@ -1946,7 +1975,7 @@ * We have something marked to copy, so update pointer to * window with selection. */ - vt_resume_flush_timer(vw->vw_device, 0); + vt_resume_flush_timer(vw, 0); switch (mark) { case VTB_MARK_END: @@ -2000,8 +2029,8 @@ } /* Mark mouse position as dirty. */ - vt_mark_mouse_position_as_dirty(vd); - vt_resume_flush_timer(vw->vw_device, 0); + vt_mark_mouse_position_as_dirty(vd, false); + vt_resume_flush_timer(vw, 0); } #endif @@ -2779,7 +2808,7 @@ /* Allow to put chars now. */ terminal_mute(vd->vd_curwindow->vw_terminal, 0); /* Rerun timer for screen updates. */ - vt_resume_flush_timer(vd, 0); + vt_resume_flush_timer(vd->vd_curwindow, 0); } /* Index: sys/dev/vt/vt_cpulogos.c =================================================================== --- sys/dev/vt/vt_cpulogos.c +++ sys/dev/vt/vt_cpulogos.c @@ -194,7 +194,7 @@ if (vd->vd_curwindow == vw) { vd->vd_flags |= VDF_INVALID; - vt_resume_flush_timer(vd, 0); + vt_resume_flush_timer(vw, 0); } VT_UNLOCK(vd); } @@ -253,7 +253,7 @@ if (vd->vd_curwindow == vw) { vd->vd_flags |= VDF_INVALID; - vt_resume_flush_timer(vd, 0); + vt_resume_flush_timer(vw, 0); } callout_init(&vt_splash_cpu_callout, 1); Index: sys/kern/subr_terminal.c =================================================================== --- sys/kern/subr_terminal.c +++ sys/kern/subr_terminal.c @@ -106,6 +106,8 @@ static tf_putchar_t termteken_putchar; static tf_fill_t termteken_fill; static tf_copy_t termteken_copy; +static tf_video_lock_t termteken_video_lock; +static tf_video_unlock_t termteken_video_unlock; static tf_param_t termteken_param; static tf_respond_t termteken_respond; @@ -115,6 +117,8 @@ .tf_putchar = termteken_putchar, .tf_fill = termteken_fill, .tf_copy = termteken_copy, + .tf_video_lock = termteken_video_lock, + .tf_video_unlock = termteken_video_unlock, .tf_param = termteken_param, .tf_respond = termteken_respond, }; @@ -627,6 +631,22 @@ } static void +termteken_video_lock(void *softc) +{ + struct terminal *tm = softc; + + tm->tm_class->tc_video_lock(tm); +} + +static void +termteken_video_unlock(void *softc) +{ + struct terminal *tm = softc; + + tm->tm_class->tc_video_unlock(tm); +} + +static void termteken_param(void *softc, int cmd, unsigned int arg) { struct terminal *tm = softc; Index: sys/sys/terminal.h =================================================================== --- sys/sys/terminal.h +++ sys/sys/terminal.h @@ -151,6 +151,8 @@ term_char_t c); typedef void tc_copy_t(struct terminal *tm, const term_rect_t *r, const term_pos_t *p); +typedef void tc_video_lock_t(struct terminal *tm); +typedef void tc_video_unlock_t(struct terminal *tm); typedef void tc_param_t(struct terminal *tm, int cmd, unsigned int arg); typedef void tc_done_t(struct terminal *tm); @@ -173,6 +175,8 @@ tc_putchar_t *tc_putchar; tc_fill_t *tc_fill; tc_copy_t *tc_copy; + tc_video_lock_t *tc_video_lock; + tc_video_unlock_t *tc_video_unlock; tc_param_t *tc_param; tc_done_t *tc_done; Index: sys/teken/teken.h =================================================================== --- sys/teken/teken.h +++ sys/teken/teken.h @@ -93,6 +93,8 @@ typedef void tf_fill_t(void *, const teken_rect_t *, teken_char_t, const teken_attr_t *); typedef void tf_copy_t(void *, const teken_rect_t *, const teken_pos_t *); +typedef void tf_video_lock_t(void *); +typedef void tf_video_unlock_t(void *); typedef void tf_param_t(void *, int, unsigned int); #define TP_SHOWCURSOR 0 #define TP_KEYPADAPP 1 @@ -114,6 +116,8 @@ tf_putchar_t *tf_putchar; tf_fill_t *tf_fill; tf_copy_t *tf_copy; + tf_video_lock_t *tf_video_lock; + tf_video_unlock_t *tf_video_unlock; tf_param_t *tf_param; tf_respond_t *tf_respond; } teken_funcs_t; Index: sys/teken/teken.c =================================================================== --- sys/teken/teken.c +++ sys/teken/teken.c @@ -133,6 +133,22 @@ } static inline void +teken_funcs_video_lock(const teken_t *t) +{ + + teken_assert(t->t_funcs->tf_video_lock != NULL); + t->t_funcs->tf_video_lock(t->t_softc); +} + +static inline void +teken_funcs_video_unlock(const teken_t *t) +{ + + teken_assert(t->t_funcs->tf_video_unlock != NULL); + t->t_funcs->tf_video_unlock(t->t_softc); +} + +static inline void teken_funcs_param(const teken_t *t, int cmd, unsigned int value) { @@ -292,8 +308,10 @@ { const char *c = buf; + teken_funcs_video_lock(t); while (len-- > 0) teken_input_byte(t, *c++); + teken_funcs_video_unlock(t); } const teken_pos_t *