- 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
This commit is contained in:
Kazutaka YOKOTA 1999-07-07 13:48:50 +00:00
parent e47178acae
commit c4c9400b69
4 changed files with 89 additions and 30 deletions

View File

@ -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 */
lines = imax(lines, scp->ysize);
min_lines = imax(SC_HISTORY_SIZE, scp->ysize);
history = scp->history;
/* make it at least as large as the screen size */
lines = imax(lines, scp->ysize);
/* 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;

View File

@ -23,7 +23,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: scvidctl.c,v 1.9 1999/06/22 14:13:29 yokota Exp $
*/
#include "sc.h"
@ -132,6 +132,7 @@ sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
video_info_t info;
sc_rndr_sw_t *rndr;
u_char *font;
int prev_ysize;
int error;
int s;
@ -188,6 +189,7 @@ sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
}
/* set up scp */
prev_ysize = scp->ysize;
/*
* This is a kludge to fend off scrn_update() while we
* muck around with scp. XXX
@ -210,7 +212,7 @@ sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
sc_alloc_cut_buffer(scp, FALSE);
#endif
#ifndef SC_NO_HISTORY
sc_alloc_history_buffer(scp, 0, FALSE);
sc_alloc_history_buffer(scp, 0, prev_ysize, FALSE);
#endif
scp->rndr = rndr;
splx(s);
@ -221,6 +223,8 @@ sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
if (tp == NULL)
return 0;
DPRINTF(5, ("ws_*size (%d,%d), size (%d,%d)\n",
tp->t_winsize.ws_col, tp->t_winsize.ws_row, scp->xsize, scp->ysize));
if (tp->t_winsize.ws_col != scp->xsize
|| tp->t_winsize.ws_row != scp->ysize) {
tp->t_winsize.ws_col = scp->xsize;
@ -239,6 +243,7 @@ sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
#else
video_info_t info;
sc_rndr_sw_t *rndr;
int prev_ysize;
int error;
int s;
@ -259,6 +264,7 @@ sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
}
/* set up scp */
prev_ysize = scp->ysize;
scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE);
scp->status &= ~PIXEL_MODE;
scp->mode = mode;
@ -273,6 +279,9 @@ sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
#ifndef SC_NO_SYSMOUSE
/* move the mouse cursor at the center of the screen */
sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2);
#endif
#ifndef SC_NO_HISTORY
sc_free_history_buffer(scp, prev_ysize);
#endif
scp->rndr = rndr;
splx(s);
@ -305,6 +314,7 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
video_info_t info;
sc_rndr_sw_t *rndr;
u_char *font;
int prev_ysize;
int error;
int s;
@ -394,6 +404,7 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
}
/* set up scp */
prev_ysize = scp->ysize;
scp->status |= (UNKNOWN_MODE | PIXEL_MODE);
scp->status &= ~GRAPHICS_MODE;
scp->xsize = xsize;
@ -409,7 +420,7 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
sc_alloc_cut_buffer(scp, FALSE);
#endif
#ifndef SC_NO_HISTORY
sc_alloc_history_buffer(scp, 0, FALSE);
sc_alloc_history_buffer(scp, 0, prev_ysize, FALSE);
#endif
scp->rndr = rndr;
splx(s);

View File

@ -25,7 +25,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: syscons.c,v 1.311 1999/07/01 20:29:25 peter Exp $
* $Id: syscons.c,v 1.312 1999/07/01 20:43:03 peter Exp $
*/
#include "sc.h"
@ -420,7 +420,7 @@ scmeminit(void *arg)
#ifndef SC_NO_HISTORY
/* initialize history buffer & pointers */
sc_alloc_history_buffer(sc_console, 0, FALSE);
sc_alloc_history_buffer(sc_console, 0, 0, FALSE);
#endif
}
@ -582,11 +582,7 @@ scclose(dev_t dev, int flag, int mode, struct proc *p)
else {
sc_vtb_destroy(&scp->vtb);
sc_vtb_destroy(&scp->scr);
if (scp->history != NULL) {
/* XXX not quite correct */
sc_vtb_destroy(scp->history);
free(scp->history, M_DEVBUF);
}
sc_free_history_buffer(scp, scp->ysize);
free(scp, M_DEVBUF);
sc->console[SC_VTY(dev) - sc->first_vty] = NULL;
}
@ -3495,7 +3491,7 @@ static scr_stat
#endif
#ifndef SC_NO_HISTORY
sc_alloc_history_buffer(scp, 0, TRUE);
sc_alloc_history_buffer(scp, 0, 0, TRUE);
#endif
sc_clear_screen(scp);

View File

@ -25,7 +25,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: syscons.h,v 1.48 1999/06/22 14:13:32 yokota Exp $
* $Id: syscons.h,v 1.49 1999/06/24 13:04:33 yokota Exp $
*/
#ifndef _DEV_SYSCONS_SYSCONS_H_
@ -430,7 +430,9 @@ void sc_paste(scr_stat *scp, u_char *p, int count);
/* schistory.c */
#ifndef SC_NO_HISTORY
int sc_alloc_history_buffer(scr_stat *scp, int lines, int wait);
int sc_alloc_history_buffer(scr_stat *scp, int lines,
int prev_ysize, int wait);
void sc_free_history_buffer(scr_stat *scp, int prev_ysize);
void sc_hist_save(scr_stat *scp);
#define sc_hist_save_one_line(scp, from) \
sc_vtb_append(&(scp)->vtb, (from), (scp)->history, (scp)->xsize)