74
74
#define ECHO_OP_SET_CANON_COL 0x81
75
75
#define ECHO_OP_ERASE_TAB 0x82
76
76
77
+ #define ECHO_COMMIT_WATERMARK 256
78
+ #define ECHO_BLOCK 256
79
+ #define ECHO_DISCARD_WATERMARK N_TTY_BUF_SIZE - (ECHO_BLOCK + 32)
80
+
81
+
77
82
#undef N_TTY_TRACE
78
83
#ifdef N_TTY_TRACE
79
84
# define n_tty_trace (f , args ...) trace_printk(f, ##args)
@@ -766,15 +771,40 @@ static void __process_echoes(struct tty_struct *tty)
766
771
}
767
772
}
768
773
774
+ /* If the echo buffer is nearly full (so that the possibility exists
775
+ * of echo overrun before the next commit), then discard enough
776
+ * data at the tail to prevent a subsequent overrun */
777
+ while (ldata -> echo_commit - tail >= ECHO_DISCARD_WATERMARK ) {
778
+ if (echo_buf (ldata , tail == ECHO_OP_START )) {
779
+ if (echo_buf (ldata , tail ) == ECHO_OP_ERASE_TAB )
780
+ tail += 3 ;
781
+ else
782
+ tail += 2 ;
783
+ } else
784
+ tail ++ ;
785
+ }
786
+
769
787
ldata -> echo_tail = tail ;
770
788
}
771
789
772
790
static void commit_echoes (struct tty_struct * tty )
773
791
{
774
792
struct n_tty_data * ldata = tty -> disc_data ;
793
+ size_t nr , old ;
794
+ size_t head ;
795
+
796
+ head = ldata -> echo_head ;
797
+ old = ldata -> echo_commit - ldata -> echo_tail ;
798
+
799
+ /* Process committed echoes if the accumulated # of bytes
800
+ * is over the threshold (and try again each time another
801
+ * block is accumulated) */
802
+ nr = head - ldata -> echo_tail ;
803
+ if (nr < ECHO_COMMIT_WATERMARK || (nr % ECHO_BLOCK > old % ECHO_BLOCK ))
804
+ return ;
775
805
776
806
mutex_lock (& ldata -> output_lock );
777
- ldata -> echo_commit = ldata -> echo_head ;
807
+ ldata -> echo_commit = head ;
778
808
__process_echoes (tty );
779
809
mutex_unlock (& ldata -> output_lock );
780
810
@@ -797,37 +827,29 @@ static void process_echoes(struct tty_struct *tty)
797
827
tty -> ops -> flush_chars (tty );
798
828
}
799
829
830
+ static void flush_echoes (struct tty_struct * tty )
831
+ {
832
+ struct n_tty_data * ldata = tty -> disc_data ;
833
+
834
+ if (!L_ECHO (tty ) || ldata -> echo_commit == ldata -> echo_head )
835
+ return ;
836
+
837
+ mutex_lock (& ldata -> output_lock );
838
+ ldata -> echo_commit = ldata -> echo_head ;
839
+ __process_echoes (tty );
840
+ mutex_unlock (& ldata -> output_lock );
841
+ }
842
+
800
843
/**
801
844
* add_echo_byte - add a byte to the echo buffer
802
845
* @c: unicode byte to echo
803
846
* @ldata: n_tty data
804
847
*
805
848
* Add a character or operation byte to the echo buffer.
806
- *
807
- * Locks: may claim output_lock to prevent concurrent modify of
808
- * echo_tail by process_echoes().
809
849
*/
810
850
811
- static void add_echo_byte (unsigned char c , struct n_tty_data * ldata )
851
+ static inline void add_echo_byte (unsigned char c , struct n_tty_data * ldata )
812
852
{
813
- if (ldata -> echo_head - ldata -> echo_tail == N_TTY_BUF_SIZE ) {
814
- size_t head = ldata -> echo_head ;
815
-
816
- mutex_lock (& ldata -> output_lock );
817
- /*
818
- * Since the buffer start position needs to be advanced,
819
- * be sure to step by a whole operation byte group.
820
- */
821
- if (echo_buf (ldata , head ) == ECHO_OP_START ) {
822
- if (echo_buf (ldata , head + 1 ) == ECHO_OP_ERASE_TAB )
823
- ldata -> echo_tail += 3 ;
824
- else
825
- ldata -> echo_tail += 2 ;
826
- } else
827
- ldata -> echo_tail ++ ;
828
- mutex_unlock (& ldata -> output_lock );
829
- }
830
-
831
853
* echo_buf_addr (ldata , ldata -> echo_head ++ ) = c ;
832
854
}
833
855
@@ -1515,6 +1537,8 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
1515
1537
break ;
1516
1538
}
1517
1539
}
1540
+
1541
+ flush_echoes (tty );
1518
1542
if (tty -> ops -> flush_chars )
1519
1543
tty -> ops -> flush_chars (tty );
1520
1544
}
0 commit comments