aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/vt/vt_buf.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/vt/vt_buf.c')
-rw-r--r--sys/dev/vt/vt_buf.c56
1 files changed, 48 insertions, 8 deletions
diff --git a/sys/dev/vt/vt_buf.c b/sys/dev/vt/vt_buf.c
index e1e4ebc23491..ec08967232f4 100644
--- a/sys/dev/vt/vt_buf.c
+++ b/sys/dev/vt/vt_buf.c
@@ -45,6 +45,7 @@ static MALLOC_DEFINE(M_VTBUF, "vtbuf", "vt buffer");
#define VTBUF_LOCK(vb) mtx_lock_spin(&(vb)->vb_lock)
#define VTBUF_UNLOCK(vb) mtx_unlock_spin(&(vb)->vb_lock)
+#define VTBUF_LOCK_OWNED(vb) mtx_owned(&(vb)->vb_lock)
#define POS_INDEX(c, r) (((r) << 12) + (c))
#define POS_COPY(d, s) do { \
@@ -202,6 +203,36 @@ vtbuf_in_this_range(int begin, int test, int end, int sz)
else
return (test >= begin && test < end);
}
+
+void
+vtbuf_unmark(struct vt_buf *vb)
+{
+
+ vtbuf_set_mark(vb, VTB_MARK_START, 0, 0);
+}
+
+void
+vtbuf_unmark_on_cross(struct vt_buf *vb, int target_begin, int target_end)
+{
+ int hsz, mb, me, tb, te;
+
+ tb = vtbuf_wth(vb, target_begin);
+ te = vtbuf_wth(vb, target_end);
+ mb = vb->vb_mark_start.tp_row;
+ me = vb->vb_mark_end.tp_row;
+ hsz = vb->vb_history_size;
+
+ /*
+ * Test intersection with vtbuf_in_this_range due to use of
+ * the circular buffer.
+ */
+ if (vtbuf_in_this_range(tb, mb, te, hsz) ||
+ vtbuf_in_this_range(tb, me, te, hsz) ||
+ vtbuf_in_this_range(mb, tb, me, hsz) ||
+ vtbuf_in_this_range(mb, te, me, hsz)) {
+ vtbuf_unmark(vb);
+ }
+}
#endif
int
@@ -499,7 +530,6 @@ vtbuf_grow(struct vt_buf *vb, const term_pos_t *p, unsigned int history_size)
{
term_char_t *old, *new, **rows, **oldrows, **copyrows, *row, *oldrow;
unsigned int w, h, c, r, old_history_size;
- size_t bufsize, rowssize;
int history_full;
const teken_attr_t *a;
term_char_t ch;
@@ -510,10 +540,10 @@ vtbuf_grow(struct vt_buf *vb, const term_pos_t *p, unsigned int history_size)
history_size = MAX(history_size, p->tp_row);
/* Allocate new buffer. */
- bufsize = history_size * p->tp_col * sizeof(term_char_t);
- new = malloc(bufsize, M_VTBUF, M_WAITOK | M_ZERO);
- rowssize = history_size * sizeof(term_pos_t *);
- rows = malloc(rowssize, M_VTBUF, M_WAITOK | M_ZERO);
+ new = mallocarray(history_size, p->tp_col * sizeof(term_char_t),
+ M_VTBUF, M_WAITOK | M_ZERO);
+ rows = mallocarray(history_size, sizeof(term_pos_t *), M_VTBUF,
+ M_WAITOK | M_ZERO);
/* Toggle it. */
VTBUF_LOCK(vb);
@@ -711,9 +741,19 @@ vtbuf_flush_mark(struct vt_buf *vb)
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);
+ /*
+ * If the request originates from a keyboard, the vtbuf is
+ * locked by teken for the entire duration of the request.
+ * For all other sources, we avoid holding the spinlock for
+ * extended periods.
+ */
+ if (VTBUF_LOCK_OWNED(vb)) {
+ vtbuf_dirty(vb, &area);
+ } else {
+ VTBUF_LOCK(vb);
+ vtbuf_dirty(vb, &area);
+ VTBUF_UNLOCK(vb);
+ }
}
}