From 60ca8343589ff6edb5a447551718e816555af494 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 30 Sep 2016 11:21:21 +0200 Subject: [PATCH] ash: [MEMALLOC] Add pushstackmark Upstream commit: Author: Herbert Xu Date: Sat Oct 6 00:45:52 2007 +0800 [MEMALLOC] Add pushstackmark This patch gets rid of the stack mark tracking hack by allocating a little bit of stack memory if we're at risk of planting a stack mark which may be grown later. To do this a new function pushstackmark is added which lets the user pick a bigger amount to allocate since some users do that anyway after setting a stack mark. Signed-off-by: Denys Vlasenko --- shell/ash.c | 53 +++++++++++++++++++---------------------------------- 1 file changed, 19 insertions(+), 34 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 97f8d9377..f7ce698a3 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -1371,13 +1371,11 @@ struct stackmark { struct stack_block *stackp; char *stacknxt; size_t stacknleft; - struct stackmark *marknext; }; struct globals_memstack { struct stack_block *g_stackp; // = &stackbase; - struct stackmark *markp; char *g_stacknxt; // = stackbase.space; char *sstrend; // = stackbase.space + MINSIZE; size_t g_stacknleft; // = MINSIZE; @@ -1387,7 +1385,6 @@ struct globals_memstack { extern struct globals_memstack *const ash_ptr_to_globals_memstack; #define G_memstack (*ash_ptr_to_globals_memstack) #define g_stackp (G_memstack.g_stackp ) -#define markp (G_memstack.markp ) #define g_stacknxt (G_memstack.g_stacknxt ) #define sstrend (G_memstack.sstrend ) #define g_stacknleft (G_memstack.g_stacknleft) @@ -1478,13 +1475,26 @@ sstrdup(const char *p) } static void -setstackmark(struct stackmark *mark) +grabstackblock(size_t len) +{ + len = SHELL_ALIGN(len); + g_stacknxt += len; + g_stacknleft -= len; +} + +static void +pushstackmark(struct stackmark *mark, size_t len) { mark->stackp = g_stackp; mark->stacknxt = g_stacknxt; mark->stacknleft = g_stacknleft; - mark->marknext = markp; - markp = mark; + grabstackblock(len); +} + +static void +setstackmark(struct stackmark *mark) +{ + pushstackmark(mark, g_stacknxt == g_stackp->space && g_stackp != &stackbase); } static void @@ -1496,7 +1506,6 @@ popstackmark(struct stackmark *mark) return; INT_OFF; - markp = mark->marknext; while (g_stackp != mark->stackp) { sp = g_stackp; g_stackp = sp->prev; @@ -1530,7 +1539,6 @@ growstackblock(void) if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) { struct stack_block *oldstackp; - struct stackmark *xmark; struct stack_block *sp; struct stack_block *prevstackp; size_t grosslen; @@ -1546,18 +1554,6 @@ growstackblock(void) g_stacknxt = sp->space; g_stacknleft = newlen; sstrend = sp->space + newlen; - - /* - * Stack marks pointing to the start of the old block - * must be relocated to point to the new block - */ - xmark = markp; - while (xmark != NULL && xmark->stackp == oldstackp) { - xmark->stackp = g_stackp; - xmark->stacknxt = g_stacknxt; - xmark->stacknleft = g_stacknleft; - xmark = xmark->marknext; - } INT_ON; } else { char *oldspace = g_stacknxt; @@ -1570,14 +1566,6 @@ growstackblock(void) } } -static void -grabstackblock(size_t len) -{ - len = SHELL_ALIGN(len); - g_stacknxt += len; - g_stacknleft -= len; -} - /* * The following routines are somewhat easier to use than the above. * The user declares a variable of type STACKSTR, which may be declared @@ -2482,8 +2470,7 @@ setprompt_if(smallint do_set, int whichprompt) prompt = nullstr; } #if ENABLE_ASH_EXPAND_PRMT - setstackmark(&smark); - stalloc(stackblocksize()); + pushstackmark(&smark, stackblocksize()); #endif putprompt(expandstr(prompt)); #if ENABLE_ASH_EXPAND_PRMT @@ -5938,10 +5925,8 @@ expbackq(union node *cmd, int flag) struct stackmark smark; INT_OFF; - setstackmark(&smark); - dest = expdest; - startloc = dest - (char *)stackblock(); - grabstackstr(dest); + startloc = expdest - (char *)stackblock(); + pushstackmark(&smark, startloc); evalbackcmd(cmd, &in); popstackmark(&smark);