tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: Trivial program size inflation
> Date: Tue, 4 Jul 2023 18:30:58 +0000
> From: Taylor R Campbell <campbell+netbsd-tech-userlevel%mumble.net@localhost>
>
> Other low-hanging fruit I see would be to split getenv out of the
> other environment variable operations, to get rid of locking and
> rbtree stuff. But it's diminishing returns at this point -- not clear
> the attached patchset/diff is worth committing. Gets me down to this:
>
> text data bss dec hex filename
> 30744 3280 3376 37400 9218 main
>
> After that, maybe we could find a substitute for the syslog_ss stuff
> in stack-protector -- but that's probably not worth the trouble, for
> what is maybe another few kilobytes or so.
...actually attached
From 14201a18296b67e2e254566ce0c5f3106c0b3e67 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Tue, 4 Jul 2023 18:16:08 +0000
Subject: [PATCH 1/3] rbtree(3): New RB_TREE_INITIALIZER macro.
Allows static initialization of an rbtree.
XXX pullup-10
---
sys/sys/rbtree.h | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/sys/sys/rbtree.h b/sys/sys/rbtree.h
index b4a8ba3f7fc1..686cf2ed299a 100644
--- a/sys/sys/rbtree.h
+++ b/sys/sys/rbtree.h
@@ -125,12 +125,17 @@ TAILQ_HEAD(rb_node_qh, rb_node);
#define RB_TAILQ_INSERT_HEAD(a, b, c) TAILQ_INSERT_HEAD(a, b, c)
#define RB_TAILQ_INSERT_BEFORE(a, b, c) TAILQ_INSERT_BEFORE(a, b, c)
#define RB_TAILQ_INSERT_AFTER(a, b, c, d) TAILQ_INSERT_AFTER(a, b, c, d)
+
+#define RBDEBUG_TREE_INITIALIZER(t) \
+ .rbt_nodes = TAILQ_INITIALIZER((t).rbt_nodes),
#else
#define RB_TAILQ_REMOVE(a, b, c) do { } while (/*CONSTCOND*/0)
#define RB_TAILQ_INIT(a) do { } while (/*CONSTCOND*/0)
#define RB_TAILQ_INSERT_HEAD(a, b, c) do { } while (/*CONSTCOND*/0)
#define RB_TAILQ_INSERT_BEFORE(a, b, c) do { } while (/*CONSTCOND*/0)
#define RB_TAILQ_INSERT_AFTER(a, b, c, d) do { } while (/*CONSTCOND*/0)
+
+#define RBDEBUG_TREE_INITIALIZER(t) /* nothing */
#endif /* RBDEBUG */
/*
@@ -181,6 +186,12 @@ typedef struct rb_tree {
#define RBSTAT_DEC(v) do { } while (/*CONSTCOND*/0)
#endif
+#define RB_TREE_INITIALIZER(t, ops) (rb_tree_t) \
+{ \
+ .rbt_ops = (ops), \
+ RBDEBUG_TREE_INITIALIZER(t) \
+}
+
void rb_tree_init(rb_tree_t *, const rb_tree_ops_t *);
void * rb_tree_insert_node(rb_tree_t *, void *);
void * rb_tree_find_node(rb_tree_t *, const void *);
From ef18c568cb559da7e82e7951050cf7cd54b0a350 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Tue, 4 Jul 2023 18:17:23 +0000
Subject: [PATCH 2/3] libc: Use RB_TREE_INITIALIZER to nix initfini.c/_env.c
coupling.
XXX pullup-10
---
lib/libc/misc/initfini.c | 3 ---
lib/libc/stdlib/_env.c | 10 ++--------
2 files changed, 2 insertions(+), 11 deletions(-)
diff --git a/lib/libc/misc/initfini.c b/lib/libc/misc/initfini.c
index 9f5cec1d2cce..6d17c167c71e 100644
--- a/lib/libc/misc/initfini.c
+++ b/lib/libc/misc/initfini.c
@@ -132,7 +132,4 @@ _libc_init(void)
/* Initialize the atexit mutexes */
__libc_atexit_init();
-
- /* Initialize environment memory RB tree. */
- __libc_env_init();
}
diff --git a/lib/libc/stdlib/_env.c b/lib/libc/stdlib/_env.c
index 6608522790f8..316459356bf7 100644
--- a/lib/libc/stdlib/_env.c
+++ b/lib/libc/stdlib/_env.c
@@ -73,7 +73,8 @@ static const rb_tree_ops_t env_tree_ops = {
};
/* The single instance of above tree. */
-static rb_tree_t env_tree;
+static rb_tree_t env_tree =
+ RB_TREE_INITIALIZER(env_tree, &env_tree_ops);
/* The allocated environment. */
static char **allocated_environ;
@@ -401,10 +402,3 @@ __unlockenv(void)
}
#endif
-
-/* Initialize environment memory RB tree. */
-void __section(".text.startup")
-__libc_env_init(void)
-{
- rb_tree_init(&env_tree, &env_tree_ops);
-}
From 1d295afec1bd9645c672d8702ce6ee7ad5c32304 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Tue, 4 Jul 2023 17:26:18 +0000
Subject: [PATCH 3/3] WIP: libc: Split read-only environment logic into a
separate unit.
The idea is to prune all the locking, rb, allocation, &c., from
statically linked programs that just call getenv.
Still WIP because I can't figure out how to make statically linked
read-only access elide the locking.
XXX pullup-10 (if we work out the issues)
---
lib/libc/stdlib/Makefile.inc | 2 +-
lib/libc/stdlib/_env.c | 107 ++--------------------------------
lib/libc/stdlib/_envlock.c | 90 +++++++++++++++++++++++++++++
lib/libc/stdlib/_findenv.c | 108 +++++++++++++++++++++++++++++++++++
lib/libc/stdlib/local.h | 2 +
5 files changed, 207 insertions(+), 102 deletions(-)
create mode 100644 lib/libc/stdlib/_envlock.c
create mode 100644 lib/libc/stdlib/_findenv.c
diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc
index fcc13020a7e6..6b33e66abab5 100644
--- a/lib/libc/stdlib/Makefile.inc
+++ b/lib/libc/stdlib/Makefile.inc
@@ -4,7 +4,7 @@
# stdlib sources
.PATH: ${ARCHDIR}/stdlib ${.CURDIR}/stdlib
-SRCS+= _env.c _rand48.c \
+SRCS+= _env.c _envlock.c _findenv.c _rand48.c \
a64l.c abort.c atexit.c atof.c atoi.c atol.c atoll.c \
bsearch.c cxa_thread_atexit.c drand48.c exit.c \
getenv.c getopt.c getopt_long.c getsubopt.c \
diff --git a/lib/libc/stdlib/_env.c b/lib/libc/stdlib/_env.c
index 316459356bf7..c4576a6901c6 100644
--- a/lib/libc/stdlib/_env.c
+++ b/lib/libc/stdlib/_env.c
@@ -82,11 +82,6 @@ static size_t allocated_environ_size;
#define ENV_ARRAY_SIZE_MIN 16
-/* The lock protecting access to the environment. */
-#ifdef _REENTRANT
-static rwlock_t env_lock = RWLOCK_INITIALIZER;
-#endif
-
/* Compatibility function. */
char *__findenv(const char *name, int *offsetp);
@@ -121,33 +116,6 @@ env_tree_compare_key(void *ctx, const void *node, const void *key)
(const uint8_t *)key - offsetof(env_node_t, data));
}
-/*
- * Determine the of the name in an environment string. Return 0 if the
- * name is not valid.
- */
-size_t
-__envvarnamelen(const char *str, bool withequal)
-{
- size_t l_name;
-
- if (str == NULL)
- return 0;
-
- l_name = strcspn(str, "=");
- if (l_name == 0)
- return 0;
-
- if (withequal) {
- if (str[l_name] != '=')
- return 0;
- } else {
- if (str[l_name] == '=')
- return 0;
- }
-
- return l_name;
-}
-
/*
* Free memory occupied by environment variable if possible. This function
* must be called with the environment write locked.
@@ -247,26 +215,19 @@ __scrubenv(void)
/*
* Get a (new) slot in the environment. This function must be called with
- * the environment write locked.
+ * the environment locked, with a write-lock if allocate=true.
*/
ssize_t
__getenvslot(const char *name, size_t l_name, bool allocate)
{
- size_t new_size, num_entries, required_size;
+ ssize_t num_entries;
+ size_t new_size, required_size;
char **new_environ;
/* Search for an existing environment variable of the given name. */
- num_entries = 0;
- if (environ != NULL) {
- while (environ[num_entries] != NULL) {
- if (strncmp(environ[num_entries], name, l_name) == 0 &&
- environ[num_entries][l_name] == '=') {
- /* We found a match. */
- return num_entries;
- }
- num_entries ++;
- }
- }
+ num_entries = __findenvslot(name, l_name);
+ if (num_entries < 0)
+ return -1;
/* No match found, return if we don't want to allocate a new slot. */
if (!allocate)
@@ -328,16 +289,6 @@ __getenvslot(const char *name, size_t l_name, bool allocate)
return num_entries;
}
-/* Find a string in the environment. */
-char *
-__findenvvar(const char *name, size_t l_name)
-{
- ssize_t offset;
-
- offset = __getenvslot(name, l_name, false);
- return (offset != -1) ? environ[offset] + l_name + 1 : NULL;
-}
-
/* Compatibility interface, do *not* call this function. */
char *
__findenv(const char *name, int *offsetp)
@@ -356,49 +307,3 @@ __findenv(const char *name, int *offsetp)
*offsetp = (int)offset;
return environ[offset] + l_name + 1;
}
-
-#ifdef _REENTRANT
-
-/* Lock the environment for read. */
-bool
-__readlockenv(void)
-{
- int error;
-
- error = rwlock_rdlock(&env_lock);
- if (error == 0)
- return true;
-
- errno = error;
- return false;
-}
-
-/* Lock the environment for write. */
-bool
-__writelockenv(void)
-{
- int error;
-
- error = rwlock_wrlock(&env_lock);
- if (error == 0)
- return true;
-
- errno = error;
- return false;
-}
-
-/* Unlock the environment for write. */
-bool
-__unlockenv(void)
-{
- int error;
-
- error = rwlock_unlock(&env_lock);
- if (error == 0)
- return true;
-
- errno = error;
- return false;
-}
-
-#endif
diff --git a/lib/libc/stdlib/_envlock.c b/lib/libc/stdlib/_envlock.c
new file mode 100644
index 000000000000..27c596fbabd5
--- /dev/null
+++ b/lib/libc/stdlib/_envlock.c
@@ -0,0 +1,90 @@
+/* $NetBSD: _env.c,v 1.13 2022/03/12 17:31:39 christos Exp $ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matthias Scheler.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: _env.c,v 1.13 2022/03/12 17:31:39 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "env.h"
+#include "local.h"
+#include "namespace.h"
+
+#include <errno.h>
+
+#ifdef _REENTRANT
+
+/* The lock protecting access to the environment. */
+static rwlock_t env_lock = RWLOCK_INITIALIZER;
+
+/* Lock the environment for read. */
+bool
+__readlockenv(void)
+{
+ int error;
+
+ error = rwlock_rdlock(&env_lock);
+ if (error == 0)
+ return true;
+
+ errno = error;
+ return false;
+}
+
+/* Lock the environment for write. */
+bool
+__writelockenv(void)
+{
+ int error;
+
+ error = rwlock_wrlock(&env_lock);
+ if (error == 0)
+ return true;
+
+ errno = error;
+ return false;
+}
+
+/* Unlock the environment for write. */
+bool
+__unlockenv(void)
+{
+ int error;
+
+ error = rwlock_unlock(&env_lock);
+ if (error == 0)
+ return true;
+
+ errno = error;
+ return false;
+}
+
+#endif
diff --git a/lib/libc/stdlib/_findenv.c b/lib/libc/stdlib/_findenv.c
new file mode 100644
index 000000000000..fa2cc89cec12
--- /dev/null
+++ b/lib/libc/stdlib/_findenv.c
@@ -0,0 +1,108 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matthias Scheler.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * _findenv.c -- subroutines for read-only access to the environment
+ *
+ * Kept in a separate compilation unit from _env.c so that statically
+ * linked programs using only getenv(3) can omit code for the write
+ * access paths and skip the runtime overhead of locking.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include "env.h"
+#include "local.h"
+#include "namespace.h"
+
+#include <limits.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+/*
+ * Determine the of the name in an environment string. Return 0 if the
+ * name is not valid.
+ */
+size_t
+__envvarnamelen(const char *str, bool withequal)
+{
+ size_t l_name;
+
+ if (str == NULL)
+ return 0;
+
+ l_name = strcspn(str, "=");
+ if (l_name == 0)
+ return 0;
+
+ if (withequal) {
+ if (str[l_name] != '=')
+ return 0;
+ } else {
+ if (str[l_name] == '=')
+ return 0;
+ }
+
+ return l_name;
+}
+
+/*
+ * Get an existing slot in the environment. This function must be
+ * called with the environment locked.
+ */
+ssize_t
+__findenvslot(const char *name, size_t l_name)
+{
+ ssize_t num_entries;
+
+ for (num_entries = 0; environ[num_entries] != NULL; num_entries++) {
+ if (strncmp(environ[num_entries], name, l_name) == 0 &&
+ environ[num_entries][l_name] == '=') {
+ return num_entries;
+ }
+ if (num_entries == SSIZE_MAX) /* paranoia */
+ return -1;
+ }
+ return -1;
+}
+
+/* Find a string in the environment. */
+char *
+__findenvvar(const char *name, size_t l_name)
+{
+ ssize_t offset;
+
+ offset = __findenvslot(name, l_name);
+ return (offset != -1) ? environ[offset] + l_name + 1 : NULL;
+}
diff --git a/lib/libc/stdlib/local.h b/lib/libc/stdlib/local.h
index 285a9b448614..c18f80245f6e 100644
--- a/lib/libc/stdlib/local.h
+++ b/lib/libc/stdlib/local.h
@@ -29,6 +29,8 @@
#include <sys/types.h>
#include <stdbool.h>
+extern ssize_t __findenvslot(const char *, size_t);
+
extern size_t __envvarnamelen(const char *str, bool withequal);
extern void __freeenvvar(char *envvar);
diff --git a/lib/libc/misc/initfini.c b/lib/libc/misc/initfini.c
index 9f5cec1d2cce..6d17c167c71e 100644
--- a/lib/libc/misc/initfini.c
+++ b/lib/libc/misc/initfini.c
@@ -132,7 +132,4 @@ _libc_init(void)
/* Initialize the atexit mutexes */
__libc_atexit_init();
-
- /* Initialize environment memory RB tree. */
- __libc_env_init();
}
diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc
index fcc13020a7e6..6b33e66abab5 100644
--- a/lib/libc/stdlib/Makefile.inc
+++ b/lib/libc/stdlib/Makefile.inc
@@ -4,7 +4,7 @@
# stdlib sources
.PATH: ${ARCHDIR}/stdlib ${.CURDIR}/stdlib
-SRCS+= _env.c _rand48.c \
+SRCS+= _env.c _envlock.c _findenv.c _rand48.c \
a64l.c abort.c atexit.c atof.c atoi.c atol.c atoll.c \
bsearch.c cxa_thread_atexit.c drand48.c exit.c \
getenv.c getopt.c getopt_long.c getsubopt.c \
diff --git a/lib/libc/stdlib/_env.c b/lib/libc/stdlib/_env.c
index 6608522790f8..c4576a6901c6 100644
--- a/lib/libc/stdlib/_env.c
+++ b/lib/libc/stdlib/_env.c
@@ -73,7 +73,8 @@ static const rb_tree_ops_t env_tree_ops = {
};
/* The single instance of above tree. */
-static rb_tree_t env_tree;
+static rb_tree_t env_tree =
+ RB_TREE_INITIALIZER(env_tree, &env_tree_ops);
/* The allocated environment. */
static char **allocated_environ;
@@ -81,11 +82,6 @@ static size_t allocated_environ_size;
#define ENV_ARRAY_SIZE_MIN 16
-/* The lock protecting access to the environment. */
-#ifdef _REENTRANT
-static rwlock_t env_lock = RWLOCK_INITIALIZER;
-#endif
-
/* Compatibility function. */
char *__findenv(const char *name, int *offsetp);
@@ -120,33 +116,6 @@ env_tree_compare_key(void *ctx, const void *node, const void *key)
(const uint8_t *)key - offsetof(env_node_t, data));
}
-/*
- * Determine the of the name in an environment string. Return 0 if the
- * name is not valid.
- */
-size_t
-__envvarnamelen(const char *str, bool withequal)
-{
- size_t l_name;
-
- if (str == NULL)
- return 0;
-
- l_name = strcspn(str, "=");
- if (l_name == 0)
- return 0;
-
- if (withequal) {
- if (str[l_name] != '=')
- return 0;
- } else {
- if (str[l_name] == '=')
- return 0;
- }
-
- return l_name;
-}
-
/*
* Free memory occupied by environment variable if possible. This function
* must be called with the environment write locked.
@@ -246,26 +215,19 @@ __scrubenv(void)
/*
* Get a (new) slot in the environment. This function must be called with
- * the environment write locked.
+ * the environment locked, with a write-lock if allocate=true.
*/
ssize_t
__getenvslot(const char *name, size_t l_name, bool allocate)
{
- size_t new_size, num_entries, required_size;
+ ssize_t num_entries;
+ size_t new_size, required_size;
char **new_environ;
/* Search for an existing environment variable of the given name. */
- num_entries = 0;
- if (environ != NULL) {
- while (environ[num_entries] != NULL) {
- if (strncmp(environ[num_entries], name, l_name) == 0 &&
- environ[num_entries][l_name] == '=') {
- /* We found a match. */
- return num_entries;
- }
- num_entries ++;
- }
- }
+ num_entries = __findenvslot(name, l_name);
+ if (num_entries < 0)
+ return -1;
/* No match found, return if we don't want to allocate a new slot. */
if (!allocate)
@@ -327,16 +289,6 @@ __getenvslot(const char *name, size_t l_name, bool allocate)
return num_entries;
}
-/* Find a string in the environment. */
-char *
-__findenvvar(const char *name, size_t l_name)
-{
- ssize_t offset;
-
- offset = __getenvslot(name, l_name, false);
- return (offset != -1) ? environ[offset] + l_name + 1 : NULL;
-}
-
/* Compatibility interface, do *not* call this function. */
char *
__findenv(const char *name, int *offsetp)
@@ -355,56 +307,3 @@ __findenv(const char *name, int *offsetp)
*offsetp = (int)offset;
return environ[offset] + l_name + 1;
}
-
-#ifdef _REENTRANT
-
-/* Lock the environment for read. */
-bool
-__readlockenv(void)
-{
- int error;
-
- error = rwlock_rdlock(&env_lock);
- if (error == 0)
- return true;
-
- errno = error;
- return false;
-}
-
-/* Lock the environment for write. */
-bool
-__writelockenv(void)
-{
- int error;
-
- error = rwlock_wrlock(&env_lock);
- if (error == 0)
- return true;
-
- errno = error;
- return false;
-}
-
-/* Unlock the environment for write. */
-bool
-__unlockenv(void)
-{
- int error;
-
- error = rwlock_unlock(&env_lock);
- if (error == 0)
- return true;
-
- errno = error;
- return false;
-}
-
-#endif
-
-/* Initialize environment memory RB tree. */
-void __section(".text.startup")
-__libc_env_init(void)
-{
- rb_tree_init(&env_tree, &env_tree_ops);
-}
diff --git a/lib/libc/stdlib/_envlock.c b/lib/libc/stdlib/_envlock.c
new file mode 100644
index 000000000000..27c596fbabd5
--- /dev/null
+++ b/lib/libc/stdlib/_envlock.c
@@ -0,0 +1,90 @@
+/* $NetBSD: _env.c,v 1.13 2022/03/12 17:31:39 christos Exp $ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matthias Scheler.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: _env.c,v 1.13 2022/03/12 17:31:39 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "env.h"
+#include "local.h"
+#include "namespace.h"
+
+#include <errno.h>
+
+#ifdef _REENTRANT
+
+/* The lock protecting access to the environment. */
+static rwlock_t env_lock = RWLOCK_INITIALIZER;
+
+/* Lock the environment for read. */
+bool
+__readlockenv(void)
+{
+ int error;
+
+ error = rwlock_rdlock(&env_lock);
+ if (error == 0)
+ return true;
+
+ errno = error;
+ return false;
+}
+
+/* Lock the environment for write. */
+bool
+__writelockenv(void)
+{
+ int error;
+
+ error = rwlock_wrlock(&env_lock);
+ if (error == 0)
+ return true;
+
+ errno = error;
+ return false;
+}
+
+/* Unlock the environment for write. */
+bool
+__unlockenv(void)
+{
+ int error;
+
+ error = rwlock_unlock(&env_lock);
+ if (error == 0)
+ return true;
+
+ errno = error;
+ return false;
+}
+
+#endif
diff --git a/lib/libc/stdlib/_findenv.c b/lib/libc/stdlib/_findenv.c
new file mode 100644
index 000000000000..fa2cc89cec12
--- /dev/null
+++ b/lib/libc/stdlib/_findenv.c
@@ -0,0 +1,108 @@
+/* $NetBSD$ */
+
+/*-
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matthias Scheler.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * _findenv.c -- subroutines for read-only access to the environment
+ *
+ * Kept in a separate compilation unit from _env.c so that statically
+ * linked programs using only getenv(3) can omit code for the write
+ * access paths and skip the runtime overhead of locking.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD$");
+
+#include "env.h"
+#include "local.h"
+#include "namespace.h"
+
+#include <limits.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+/*
+ * Determine the of the name in an environment string. Return 0 if the
+ * name is not valid.
+ */
+size_t
+__envvarnamelen(const char *str, bool withequal)
+{
+ size_t l_name;
+
+ if (str == NULL)
+ return 0;
+
+ l_name = strcspn(str, "=");
+ if (l_name == 0)
+ return 0;
+
+ if (withequal) {
+ if (str[l_name] != '=')
+ return 0;
+ } else {
+ if (str[l_name] == '=')
+ return 0;
+ }
+
+ return l_name;
+}
+
+/*
+ * Get an existing slot in the environment. This function must be
+ * called with the environment locked.
+ */
+ssize_t
+__findenvslot(const char *name, size_t l_name)
+{
+ ssize_t num_entries;
+
+ for (num_entries = 0; environ[num_entries] != NULL; num_entries++) {
+ if (strncmp(environ[num_entries], name, l_name) == 0 &&
+ environ[num_entries][l_name] == '=') {
+ return num_entries;
+ }
+ if (num_entries == SSIZE_MAX) /* paranoia */
+ return -1;
+ }
+ return -1;
+}
+
+/* Find a string in the environment. */
+char *
+__findenvvar(const char *name, size_t l_name)
+{
+ ssize_t offset;
+
+ offset = __findenvslot(name, l_name);
+ return (offset != -1) ? environ[offset] + l_name + 1 : NULL;
+}
diff --git a/lib/libc/stdlib/local.h b/lib/libc/stdlib/local.h
index 285a9b448614..c18f80245f6e 100644
--- a/lib/libc/stdlib/local.h
+++ b/lib/libc/stdlib/local.h
@@ -29,6 +29,8 @@
#include <sys/types.h>
#include <stdbool.h>
+extern ssize_t __findenvslot(const char *, size_t);
+
extern size_t __envvarnamelen(const char *str, bool withequal);
extern void __freeenvvar(char *envvar);
diff --git a/sys/sys/rbtree.h b/sys/sys/rbtree.h
index b4a8ba3f7fc1..686cf2ed299a 100644
--- a/sys/sys/rbtree.h
+++ b/sys/sys/rbtree.h
@@ -125,12 +125,17 @@ TAILQ_HEAD(rb_node_qh, rb_node);
#define RB_TAILQ_INSERT_HEAD(a, b, c) TAILQ_INSERT_HEAD(a, b, c)
#define RB_TAILQ_INSERT_BEFORE(a, b, c) TAILQ_INSERT_BEFORE(a, b, c)
#define RB_TAILQ_INSERT_AFTER(a, b, c, d) TAILQ_INSERT_AFTER(a, b, c, d)
+
+#define RBDEBUG_TREE_INITIALIZER(t) \
+ .rbt_nodes = TAILQ_INITIALIZER((t).rbt_nodes),
#else
#define RB_TAILQ_REMOVE(a, b, c) do { } while (/*CONSTCOND*/0)
#define RB_TAILQ_INIT(a) do { } while (/*CONSTCOND*/0)
#define RB_TAILQ_INSERT_HEAD(a, b, c) do { } while (/*CONSTCOND*/0)
#define RB_TAILQ_INSERT_BEFORE(a, b, c) do { } while (/*CONSTCOND*/0)
#define RB_TAILQ_INSERT_AFTER(a, b, c, d) do { } while (/*CONSTCOND*/0)
+
+#define RBDEBUG_TREE_INITIALIZER(t) /* nothing */
#endif /* RBDEBUG */
/*
@@ -181,6 +186,12 @@ typedef struct rb_tree {
#define RBSTAT_DEC(v) do { } while (/*CONSTCOND*/0)
#endif
+#define RB_TREE_INITIALIZER(t, ops) (rb_tree_t) \
+{ \
+ .rbt_ops = (ops), \
+ RBDEBUG_TREE_INITIALIZER(t) \
+}
+
void rb_tree_init(rb_tree_t *, const rb_tree_ops_t *);
void * rb_tree_insert_node(rb_tree_t *, void *);
void * rb_tree_find_node(rb_tree_t *, const void *);
Home |
Main Index |
Thread Index |
Old Index