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.
This commit is contained in:
Joel Sherrill
2002-05-14 19:02:06 +00:00
parent deb66d121b
commit baf7133855
6 changed files with 259 additions and 2 deletions

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -1,3 +1,10 @@
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.
2002-05-03 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
* include/Makefile.am: Remove.

View File

@@ -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)

82
c/src/lib/libc/envlock.c Normal file
View File

@@ -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);
}

View File

@@ -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);
}