summaryrefslogtreecommitdiffstats
path: root/sys/dev/syscons/schistory.c
diff options
context:
space:
mode:
authoryokota <yokota@FreeBSD.org>1999-07-07 13:48:50 +0000
committeryokota <yokota@FreeBSD.org>1999-07-07 13:48:50 +0000
commitdde3bd678dd648c47f2136b10cbf07f754e3be4c (patch)
treeb2eb9e67839a34f3c1138f9f2f6dce5ffb8f8e4d /sys/dev/syscons/schistory.c
parentde9b240dd7c3c1a682e04673eb1c25d2ef8c4cc5 (diff)
downloadFreeBSD-src-dde3bd678dd648c47f2136b10cbf07f754e3be4c.zip
FreeBSD-src-dde3bd678dd648c47f2136b10cbf07f754e3be4c.tar.gz
- Fixed memory leak in sc_alloc_history_buffer().
- Correctly observe the variable `extra_history_size' when changing the size of history (scroll back) buffer. - Added sc_free_history_buffer(). Pointed out by: des
Diffstat (limited to 'sys/dev/syscons/schistory.c')
-rw-r--r--sys/dev/syscons/schistory.c82
1 files changed, 66 insertions, 16 deletions
diff --git a/sys/dev/syscons/schistory.c b/sys/dev/syscons/schistory.c
index 765733c..433182d 100644
--- a/sys/dev/syscons/schistory.c
+++ b/sys/dev/syscons/schistory.c
@@ -26,7 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id:$
+ * $Id: schistory.c,v 1.1 1999/06/22 14:13:26 yokota Exp $
*/
#include "sc.h"
@@ -68,7 +68,7 @@ static void history_to_screen(scr_stat *scp);
/* allocate a history buffer */
int
-sc_alloc_history_buffer(scr_stat *scp, int lines, int wait)
+sc_alloc_history_buffer(scr_stat *scp, int lines, int prev_ysize, int wait)
{
/*
* syscons unconditionally allocates buffers upto
@@ -77,38 +77,82 @@ sc_alloc_history_buffer(scr_stat *scp, int lines, int wait)
* subject to extra_history_size.
*/
sc_vtb_t *history;
+ sc_vtb_t *prev_history;
int cur_lines; /* current buffer size */
int min_lines; /* guaranteed buffer size */
+ int delta; /* lines to put back */
if (lines <= 0)
lines = SC_HISTORY_SIZE; /* use the default value */
+
+ /* make it at least as large as the screen size */
lines = imax(lines, scp->ysize);
- min_lines = imax(SC_HISTORY_SIZE, scp->ysize);
- history = scp->history;
+ /* remove the history buffer while we update it */
+ history = prev_history = scp->history;
scp->history = NULL;
- if (history == NULL) {
- cur_lines = 0;
- } else {
+
+ /* calculate the amount of lines to put back to extra_history_size */
+ delta = 0;
+ if (prev_history) {
cur_lines = sc_vtb_rows(history);
+ min_lines = imax(SC_HISTORY_SIZE, prev_ysize);
if (cur_lines > min_lines)
- extra_history_size += cur_lines - min_lines;
- sc_vtb_destroy(history);
+ delta = cur_lines - min_lines;
}
- if (lines > min_lines)
- extra_history_size -= lines - min_lines;
- history = (sc_vtb_t *)malloc(sizeof(*history),
- M_DEVBUF, (wait) ? M_WAITOK : M_NOWAIT);
- if (history != NULL)
+ /* lines upto min_lines are always allowed. */
+ min_lines = imax(SC_HISTORY_SIZE, scp->ysize);
+ if (lines > min_lines) {
+ if (lines - min_lines > extra_history_size + delta) {
+ /* too many lines are requested */
+ scp->history = prev_history;
+ return EINVAL;
+ }
+ }
+
+ /* destroy the previous buffer and allocate a new one */
+ if (prev_history == NULL) {
+ history = (sc_vtb_t *)malloc(sizeof(*history),
+ M_DEVBUF,
+ (wait) ? M_WAITOK : M_NOWAIT);
+ } else {
+ extra_history_size += delta;
+ sc_vtb_destroy(prev_history);
+ }
+ if (history != NULL) {
+ if (lines > min_lines)
+ extra_history_size -= lines - min_lines;
sc_vtb_init(history, VTB_RINGBUFFER, scp->xsize, lines,
NULL, wait);
+ }
+
scp->history_pos = 0;
scp->history = history;
return 0;
}
+void
+sc_free_history_buffer(scr_stat *scp, int prev_ysize)
+{
+ sc_vtb_t *history;
+ int cur_lines; /* current buffer size */
+ int min_lines; /* guaranteed buffer size */
+
+ history = scp->history;
+ scp->history = NULL;
+ if (history == NULL)
+ return;
+
+ cur_lines = sc_vtb_rows(history);
+ min_lines = imax(SC_HISTORY_SIZE, prev_ysize);
+ extra_history_size += (cur_lines > min_lines) ? cur_lines - min_lines : 0;
+
+ sc_vtb_destroy(history);
+ free(history, M_DEVBUF);
+}
+
/* copy entire screen into the top of the history buffer */
void
sc_hist_save(scr_stat *scp)
@@ -200,6 +244,7 @@ sc_hist_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
struct proc *p)
{
scr_stat *scp;
+ int error;
switch (cmd) {
@@ -209,9 +254,14 @@ sc_hist_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag,
return EINVAL;
if (scp->status & BUFFER_SAVED)
return EBUSY;
- return sc_alloc_history_buffer(scp,
+ DPRINTF(5, ("lines:%d, ysize:%d, pool:%d\n",
+ *(int *)data, scp->ysize, extra_history_size));
+ error = sc_alloc_history_buffer(scp,
imax(*(int *)data, scp->ysize),
- TRUE);
+ scp->ysize, TRUE);
+ DPRINTF(5, ("error:%d, rows:%d, pool:%d\n", error,
+ sc_vtb_rows(scp->history), extra_history_size));
+ return error;
}
return ENOIOCTL;
OpenPOWER on IntegriCloud