/*
|
/*
|
* Author: Till Straumann <strauman@slac.stanford.edu>, 3/2002
|
* Author: Till Straumann <strauman@slac.stanford.edu>, 3/2002
|
*
|
*
|
* envlock.c,v 1.2 2002/05/17 18:03:34 joel Exp
|
* envlock.c,v 1.2 2002/05/17 18:03:34 joel Exp
|
*/
|
*/
|
|
|
/* provide locking for the global environment 'environ' */
|
/* provide locking for the global environment 'environ' */
|
|
|
#if HAVE_CONFIG_H
|
#if HAVE_CONFIG_H
|
#include "config.h"
|
#include "config.h"
|
#endif
|
#endif
|
|
|
#include <rtems.h>
|
#include <rtems.h>
|
#include <sys/reent.h>
|
#include <sys/reent.h>
|
|
|
#include <assert.h>
|
#include <assert.h>
|
|
|
/*
|
/*
|
* NOTES:
|
* NOTES:
|
* - although it looks like a classical multiple-readers / single writer (MRSW)
|
* - although it looks like a classical multiple-readers / single writer (MRSW)
|
* locking problem, we still use a single lock for the following reasons:
|
* locking problem, we still use a single lock for the following reasons:
|
* 1) newlib has no provision / hook for calling different locking routines
|
* 1) newlib has no provision / hook for calling different locking routines
|
* from setenv/putenv and getenv, respectively.
|
* from setenv/putenv and getenv, respectively.
|
* 2) MRSW involves calling several semaphore-primitives, even in the most
|
* 2) MRSW involves calling several semaphore-primitives, even in the most
|
* likely case of a first-reader's access. This probably takes more CPU
|
* likely case of a first-reader's access. This probably takes more CPU
|
* time than just waiting until another reader is done; environment
|
* time than just waiting until another reader is done; environment
|
* access is fast.
|
* access is fast.
|
* - the lock implementation must allow nesting (same thread may call
|
* - the lock implementation must allow nesting (same thread may call
|
* lock-lock-unlock-unlock).
|
* lock-lock-unlock-unlock).
|
* - NEWLIB-1.8.2 has an ugly BUG: if environ is NULL, _findenv_r() bails
|
* - NEWLIB-1.8.2 has an ugly BUG: if environ is NULL, _findenv_r() bails
|
* out leaving the lock held :-(
|
* out leaving the lock held :-(
|
*
|
*
|
* Used by the following functions:
|
* Used by the following functions:
|
* findenv_r(), setenv_r(), and unsetenv_r() which are called by
|
* findenv_r(), setenv_r(), and unsetenv_r() which are called by
|
* getenv(), getenv_r(), setenv(), and unsetenv().
|
* getenv(), getenv_r(), setenv(), and unsetenv().
|
*
|
*
|
*/
|
*/
|
|
|
#if defined(ENVLOCK_DEDIDCATED_MUTEX)
|
#if defined(ENVLOCK_DEDIDCATED_MUTEX)
|
static rtems_id envLock=0;
|
static rtems_id envLock=0;
|
|
|
static void
|
static void
|
__rtems_envlock_init(void)
|
__rtems_envlock_init(void)
|
{
|
{
|
extern char **environ;
|
extern char **environ;
|
rtems_status_code rc;
|
rtems_status_code rc;
|
|
|
if (envLock) /* already initialized */
|
if (envLock) /* already initialized */
|
return;
|
return;
|
|
|
assert(environ && "MUST have non-NULL 'environ' due to newlib bug");
|
assert(environ && "MUST have non-NULL 'environ' due to newlib bug");
|
|
|
rc = rtems_semaphore_create(
|
rc = rtems_semaphore_create(
|
rtems_build_name('E','N','V','S'),
|
rtems_build_name('E','N','V','S'),
|
1,
|
1,
|
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
|
RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
|
0,
|
0,
|
&envLock);
|
&envLock);
|
if (RTEMS_SUCCESSFUL!=rc)
|
if (RTEMS_SUCCESSFUL!=rc)
|
rtems_fatal_error_occurred(rc);
|
rtems_fatal_error_occurred(rc);
|
}
|
}
|
|
|
void
|
void
|
__env_lock(struct _reent *r)
|
__env_lock(struct _reent *r)
|
{
|
{
|
/* Do lazy init */
|
/* Do lazy init */
|
if (!envLock)
|
if (!envLock)
|
__rtems_envlock_init();
|
__rtems_envlock_init();
|
/*
|
/*
|
* Must not use a semaphore before pre-tasking hook is called.
|
* Must not use a semaphore before pre-tasking hook is called.
|
* - it will corrupt memory :-(
|
* - it will corrupt memory :-(
|
*/
|
*/
|
|
|
if (_Thread_Executing)
|
if (_Thread_Executing)
|
rtems_semaphore_obtain(envLock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
rtems_semaphore_obtain(envLock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
|
}
|
}
|
|
|
void
|
void
|
__env_unlock(struct _reent *r)
|
__env_unlock(struct _reent *r)
|
{
|
{
|
/*
|
/*
|
* Must not use a semaphore before pre-tasking hook is called.
|
* Must not use a semaphore before pre-tasking hook is called.
|
* - it will corrupt memory :-(
|
* - it will corrupt memory :-(
|
*/
|
*/
|
if (_Thread_Executing)
|
if (_Thread_Executing)
|
rtems_semaphore_release(envLock);
|
rtems_semaphore_release(envLock);
|
}
|
}
|
#else
|
#else
|
|
|
/*
|
/*
|
* Reuse the libio mutex -- it is always initialized before we
|
* Reuse the libio mutex -- it is always initialized before we
|
* could possibly run.
|
* could possibly run.
|
*/
|
*/
|
|
|
#include <rtems/libio_.h>
|
#include <rtems/libio_.h>
|
|
|
void
|
void
|
__env_lock(struct _reent *r)
|
__env_lock(struct _reent *r)
|
{
|
{
|
rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
|
rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
|
}
|
}
|
|
|
void
|
void
|
__env_unlock(struct _reent *r)
|
__env_unlock(struct _reent *r)
|
{
|
{
|
rtems_semaphore_release( rtems_libio_semaphore );
|
rtems_semaphore_release( rtems_libio_semaphore );
|
}
|
}
|
#endif
|
#endif
|
|
|