summaryrefslogtreecommitdiffstats
path: root/c/src/exec/libcsupport/src
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2002-05-14 19:02:06 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2002-05-14 19:02:06 +0000
commitbaf7133855d07a897c5337b5860b6e9c61482d2f (patch)
tree8fa971de8e3d73a4a7a88d950566354a573f48f4 /c/src/exec/libcsupport/src
parent2002-05-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de> (diff)
downloadrtems-baf7133855d07a897c5337b5860b6e9c61482d2f.tar.bz2
2001-05-14 Till Straumann <strauman@slac.stanford.edu>
* Per PR212, added envlock support for newlib. This is used by at least getenv()/putenv() to avoid race conditions. * libc/envlock.c: New file. * libc/Makefile.am: Modified to reflect above.
Diffstat (limited to 'c/src/exec/libcsupport/src')
-rw-r--r--c/src/exec/libcsupport/src/Makefile.am4
-rw-r--r--c/src/exec/libcsupport/src/envlock.c82
2 files changed, 85 insertions, 1 deletions
diff --git a/c/src/exec/libcsupport/src/Makefile.am b/c/src/exec/libcsupport/src/Makefile.am
index 630522af4c..075f97731f 100644
--- a/c/src/exec/libcsupport/src/Makefile.am
+++ b/c/src/exec/libcsupport/src/Makefile.am
@@ -34,6 +34,8 @@ DIRECTORY_SCAN_C_FILES = opendir.c closedir.c readdir.c rewinddir.c \
MALLOC_C_FILES = malloc.c mallocfreespace.c __brk.c __sbrk.c
+ENVIRON_C_FILES = envlock.c
+
PASSWORD_GROUP_C_FILES = getpwent.c getgrent.c
TERMINAL_IDENTIFICATION_C_FILES = ctermid.c isatty.c ttyname.c ttyname_r.c
@@ -44,7 +46,7 @@ LIBC_GLUE_C_FILES = __getpid.c __gettod.c __times.c truncate.c access.c \
UNIX_LIBC_C_FILES = unixlibc.c hosterr.c
COMMON_C_FILES = gxx_wrappers.c printk.c $(BASE_FS_C_FILES) \
- $(MALLOC_C_FILES) $(TERMIOS_C_FILES) $(ERROR_C_FILES) \
+ $(MALLOC_C_FILES) $(ENVIRON_C_FILES) $(TERMIOS_C_FILES) $(ERROR_C_FILES) \
$(ASSOCIATION_C_FILES)
UNIX_C_FILES = $(UNIX_LIBC_C_FILES)
diff --git a/c/src/exec/libcsupport/src/envlock.c b/c/src/exec/libcsupport/src/envlock.c
new file mode 100644
index 0000000000..c9489b3e88
--- /dev/null
+++ b/c/src/exec/libcsupport/src/envlock.c
@@ -0,0 +1,82 @@
+/*
+ * $Id$
+ *
+ * Author: Till Straumann <strauman@slac.stanford.edu>, 3/2002
+ */
+
+/* provide locking for the global environment 'environ' */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <rtems.h>
+#include <sys/reent.h>
+
+#include <assert.h>
+
+/*
+ * NOTES:
+ * - although it looks like a classical multiple-readers / single writer (MRSW)
+ * locking problem, we still use a single lock for the following reasons:
+ * 1) newlib has no provision / hook for calling different locking routines
+ * from setenv/putenv and getenv, respectively.
+ * 2) MRSW involves calling several semaphore-primitives, even in the most
+ * likely case of a first-reader's access. This probably takes more CPU
+ * time than just waiting until another reader is done; environment
+ * access is fast.
+ * - the lock implementation must allow nesting (same thread may call
+ * lock-lock-unlock-unlock).
+ * - NEWLIB-1.8.2 has an ugly BUG: if environ is NULL, _findenv_r() bails
+ * out leaving the lock held :-(
+ *
+ */
+
+static rtems_id envLock=0;
+
+static void
+__rtems_envlock_init(void)
+{
+ extern char **environ;
+ rtems_status_code rc;
+
+ if (envLock) /* already initialized */
+ return;
+
+ assert(environ && "MUST have non-NULL 'environ' due to newlib bug");
+
+ rc = rtems_semaphore_create(
+ rtems_build_name('E','N','V','S'),
+ 1,
+ RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
+ 0,
+ &envLock);
+ if (RTEMS_SUCCESSFUL!=rc)
+ rtems_fatal_error_occurred(rc);
+}
+
+void
+__env_lock(struct _reent *r)
+{
+ /* Do lazy init */
+ if (!envLock)
+ __rtems_envlock_init();
+ /*
+ * Must not use a semaphore before pre-tasking hook is called.
+ * - it will corrupt memory :-(
+ */
+
+ if (_Thread_Executing)
+ rtems_semaphore_obtain(envLock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+}
+
+void
+__env_unlock(struct _reent *r)
+{
+ /*
+ * Must not use a semaphore before pre-tasking hook is called.
+ * - it will corrupt memory :-(
+ */
+ if (_Thread_Executing)
+ rtems_semaphore_release(envLock);
+}