1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
/*
* Author: Till Straumann <strauman@slac.stanford.edu>, 3/2002
*
* $Id$
*/
/* 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 :-(
*
* Used by the following functions:
* findenv_r(), setenv_r(), and unsetenv_r() which are called by
* getenv(), getenv_r(), setenv(), and unsetenv().
*
*/
#if defined(ENVLOCK_DEDIDCATED_MUTEX)
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);
}
#else
/*
* Reuse the libio mutex -- it is always initialized before we
* could possibly run.
*/
#include <rtems/libio_.h>
void
__env_lock(struct _reent *r)
{
rtems_semaphore_obtain( rtems_libio_semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT );
}
void
__env_unlock(struct _reent *r)
{
rtems_semaphore_release( rtems_libio_semaphore );
}
#endif
|