ash: memalloc: Avoid looping in growstackto
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 21 Feb 2020 14:25:37 +0000 (15:25 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 21 Feb 2020 14:25:37 +0000 (15:25 +0100)
Upstream commit:

    Date: Thu, 31 May 2018 01:51:48 +0800
    memalloc: Avoid looping in growstackto

    Currently growstackto will repeatedly call growstackblock until
    the requisite size is obtained.  This is wasteful.  This patch
    changes growstackblock to take a minimum size instead.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/ash.c

index fd2fc9f2381047d52328f71f7c2324c4e76a6e24..8d182284715b1d0cb65f465dfc992de7e2bb7800 100644 (file)
@@ -1678,15 +1678,16 @@ popstackmark(struct stackmark *mark)
  * part of the block that has been used.
  */
 static void
-growstackblock(void)
+growstackblock(size_t min)
 {
        size_t newlen;
 
        newlen = g_stacknleft * 2;
        if (newlen < g_stacknleft)
                ash_msg_and_raise_error(bb_msg_memory_exhausted);
-       if (newlen < 128)
-               newlen += 128;
+       min = SHELL_ALIGN(min | 128);
+       if (newlen < min)
+               newlen += min;
 
        if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
                struct stack_block *sp;
@@ -1736,16 +1737,15 @@ static void *
 growstackstr(void)
 {
        size_t len = stackblocksize();
-       growstackblock();
+       growstackblock(0);
        return (char *)stackblock() + len;
 }
 
 static char *
 growstackto(size_t len)
 {
-       while (stackblocksize() < len)
-               growstackblock();
-
+       if (stackblocksize() < len)
+               growstackblock(len);
        return stackblock();
 }