Skip to content
This repository was archived by the owner on Nov 9, 2017. It is now read-only.

Commit 10f5056

Browse files
kbleeskasal
authored andcommitted
Win32: reduce environment array reallocations
Move environment array reallocation from do_putenv to the respective callers. Keep track of the environment size in a global variable. Use ALLOC_GROW in mingw_putenv to reduce reallocations. Allocate a sufficiently sized environment array in make_environment_block to prevent reallocations. Signed-off-by: Karsten Blees <[email protected]>
1 parent e6e3f76 commit 10f5056

File tree

1 file changed

+34
-26
lines changed

1 file changed

+34
-26
lines changed

compat/mingw.c

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -734,33 +734,40 @@ static int lookupenv(char **env, const char *name, size_t nmln)
734734

735735
/*
736736
* If name contains '=', then sets the variable, otherwise it unsets it
737+
* Size includes the terminating NULL. Env must have room for size + 1 entries
738+
* (in case of insert). Returns the new size. Optionally frees removed entries.
737739
*/
738-
static char **do_putenv(char **env, const char *name, int free_old)
740+
static int do_putenv(char **env, const char *name, int size, int free_old)
739741
{
740742
char *eq = strchrnul(name, '=');
741743
int i = lookupenv(env, name, eq-name);
742744

743745
if (i < 0) {
744746
if (*eq) {
745-
for (i = 0; env[i]; i++)
746-
;
747-
env = xrealloc(env, (i+2)*sizeof(*env));
748-
env[i] = (char*) name;
749-
env[i+1] = NULL;
747+
env[size - 1] = (char*) name;
748+
env[size] = NULL;
749+
size++;
750750
}
751751
}
752752
else {
753753
if (free_old)
754754
free(env[i]);
755755
if (*eq)
756756
env[i] = (char*) name;
757-
else
757+
else {
758758
for (; env[i]; i++)
759759
env[i] = env[i+1];
760+
size--;
761+
}
760762
}
761-
return env;
763+
return size;
762764
}
763765

766+
/* used number of elements of environ array, including terminating NULL */
767+
static int environ_size = 0;
768+
/* allocated size of environ array, in bytes */
769+
static int environ_alloc = 0;
770+
764771
#undef getenv
765772
char *mingw_getenv(const char *name)
766773
{
@@ -780,7 +787,8 @@ char *mingw_getenv(const char *name)
780787

781788
int mingw_putenv(const char *namevalue)
782789
{
783-
environ = do_putenv(environ, namevalue, 1);
790+
ALLOC_GROW(environ, (environ_size + 1) * sizeof(char*), environ_alloc);
791+
environ_size = do_putenv(environ, namevalue, environ_size, 1);
784792
return 0;
785793
}
786794

@@ -973,31 +981,28 @@ static char *path_lookup(const char *cmd, char **path, int exe_only)
973981
static wchar_t *make_environment_block(char **deltaenv)
974982
{
975983
wchar_t *wenvblk = NULL;
976-
int count = 0;
977-
char **e, **tmpenv;
978-
int size = 0, wenvsz = 0, wenvpos = 0;
984+
char **tmpenv;
985+
int i = 0, size = environ_size, wenvsz = 0, wenvpos = 0;
979986

980-
while (environ[count])
981-
count++;
987+
while (deltaenv && deltaenv[i])
988+
i++;
982989

983-
/* copy the environment */
984-
tmpenv = xmalloc(sizeof(*tmpenv) * (count + 1));
985-
memcpy(tmpenv, environ, sizeof(*tmpenv) * (count + 1));
990+
/* copy the environment, leaving space for changes */
991+
tmpenv = xmalloc((size + i) * sizeof(char*));
992+
memcpy(tmpenv, environ, size * sizeof(char*));
986993

987994
/* merge supplied environment changes into the temporary environment */
988-
for (e = deltaenv; e && *e; e++)
989-
tmpenv = do_putenv(tmpenv, *e, 0);
995+
for (i = 0; deltaenv && deltaenv[i]; i++)
996+
size = do_putenv(tmpenv, deltaenv[i], size, 0);
990997

991998
/* environment must be sorted */
992-
for (count = 0; tmpenv[count]; )
993-
count++;
994-
qsort(tmpenv, count, sizeof(*tmpenv), compareenv);
999+
qsort(tmpenv, size - 1, sizeof(char*), compareenv);
9951000

9961001
/* create environment block from temporary environment */
997-
for (e = tmpenv; *e; e++) {
998-
size = 2 * strlen(*e) + 2; /* +2 for final \0 */
1002+
for (i = 0; tmpenv[i]; i++) {
1003+
size = 2 * strlen(tmpenv[i]) + 2; /* +2 for final \0 */
9991004
ALLOC_GROW(wenvblk, (wenvpos + size) * sizeof(wchar_t), wenvsz);
1000-
wenvpos += xutftowcs(&wenvblk[wenvpos], *e, size) + 1;
1005+
wenvpos += xutftowcs(&wenvblk[wenvpos], tmpenv[i], size) + 1;
10011006
}
10021007
/* add final \0 terminator */
10031008
wenvblk[wenvpos] = 0;
@@ -2015,7 +2020,9 @@ void mingw_startup()
20152020
maxlen = max(maxlen, wcslen(wenv[i]));
20162021

20172022
/* nedmalloc can't free CRT memory, allocate resizable environment list */
2018-
environ = xcalloc(i + 1, sizeof(char*));
2023+
environ = NULL;
2024+
environ_size = i + 1;
2025+
ALLOC_GROW(environ, environ_size * sizeof(char*), environ_alloc);
20192026

20202027
/* allocate buffer (wchar_t encodes to max 3 UTF-8 bytes) */
20212028
maxlen = 3 * maxlen + 1;
@@ -2032,6 +2039,7 @@ void mingw_startup()
20322039
len = xwcstoutf(buffer, wenv[i], maxlen);
20332040
environ[i] = xmemdupz(buffer, len);
20342041
}
2042+
environ[i] = NULL;
20352043
free(buffer);
20362044

20372045
/* initialize critical section for waitpid pinfo_t list */

0 commit comments

Comments
 (0)