1 | /** |
---|
2 | * @file |
---|
3 | * |
---|
4 | * @brief Global Environment Lock Support |
---|
5 | * @ingroup libcsupport |
---|
6 | */ |
---|
7 | |
---|
8 | /* |
---|
9 | * Author: Till Straumann <strauman@slac.stanford.edu>, 3/2002 |
---|
10 | */ |
---|
11 | |
---|
12 | /* provide locking for the global environment 'environ' */ |
---|
13 | |
---|
14 | #if HAVE_CONFIG_H |
---|
15 | #include "config.h" |
---|
16 | #endif |
---|
17 | |
---|
18 | #if defined(HAVE_ENVLOCK_H) \ |
---|
19 | && defined(HAVE_DECL___ENV_LOCK) && defined(HAVE_DECL___ENV_UNLOCK) |
---|
20 | |
---|
21 | #include <envlock.h> |
---|
22 | |
---|
23 | #include <rtems.h> |
---|
24 | #include <sys/reent.h> |
---|
25 | |
---|
26 | #include <assert.h> |
---|
27 | |
---|
28 | /* |
---|
29 | * NOTES: |
---|
30 | * - although it looks like a classical multiple-readers / single writer (MRSW) |
---|
31 | * locking problem, we still use a single lock for the following reasons: |
---|
32 | * 1) newlib has no provision / hook for calling different locking routines |
---|
33 | * from setenv/putenv and getenv, respectively. |
---|
34 | * 2) MRSW involves calling several semaphore-primitives, even in the most |
---|
35 | * likely case of a first-reader's access. This probably takes more CPU |
---|
36 | * time than just waiting until another reader is done; environment |
---|
37 | * access is fast. |
---|
38 | * - the lock implementation must allow nesting (same thread may call |
---|
39 | * lock-lock-unlock-unlock). |
---|
40 | * - NEWLIB-1.8.2 has an ugly BUG: if environ is NULL, _findenv_r() bails |
---|
41 | * out leaving the lock held :-( |
---|
42 | * |
---|
43 | * Used by the following functions: |
---|
44 | * findenv_r(), setenv_r(), and unsetenv_r() which are called by |
---|
45 | * getenv(), getenv_r(), setenv(), and unsetenv(). |
---|
46 | * |
---|
47 | */ |
---|
48 | |
---|
49 | #if defined(ENVLOCK_DEDICATED_MUTEX) |
---|
50 | static rtems_id envLock=0; |
---|
51 | |
---|
52 | static void |
---|
53 | __rtems_envlock_init(void) |
---|
54 | { |
---|
55 | extern char **environ; |
---|
56 | rtems_status_code rc; |
---|
57 | |
---|
58 | if (envLock) /* already initialized */ |
---|
59 | return; |
---|
60 | |
---|
61 | assert(environ && "MUST have non-NULL 'environ' due to newlib bug"); |
---|
62 | |
---|
63 | rc = rtems_semaphore_create( |
---|
64 | rtems_build_name('E','N','V','S'), |
---|
65 | 1, |
---|
66 | RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, |
---|
67 | 0, |
---|
68 | &envLock); |
---|
69 | if (RTEMS_SUCCESSFUL!=rc) |
---|
70 | rtems_fatal_error_occurred(rc); |
---|
71 | } |
---|
72 | |
---|
73 | void |
---|
74 | __env_lock(struct _reent *r) |
---|
75 | { |
---|
76 | /* Do lazy init */ |
---|
77 | if (!envLock) |
---|
78 | __rtems_envlock_init(); |
---|
79 | /* |
---|
80 | * Must not use a semaphore before pre-tasking hook is called. |
---|
81 | * - it will corrupt memory :-( |
---|
82 | */ |
---|
83 | |
---|
84 | if (_Thread_Executing) |
---|
85 | rtems_semaphore_obtain(envLock, RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
---|
86 | } |
---|
87 | |
---|
88 | void |
---|
89 | __env_unlock(struct _reent *r) |
---|
90 | { |
---|
91 | /* |
---|
92 | * Must not use a semaphore before pre-tasking hook is called. |
---|
93 | * - it will corrupt memory :-( |
---|
94 | */ |
---|
95 | if (_Thread_Executing) |
---|
96 | rtems_semaphore_release(envLock); |
---|
97 | } |
---|
98 | #else |
---|
99 | |
---|
100 | /* |
---|
101 | * Reuse the libio mutex -- it is always initialized before we |
---|
102 | * could possibly run. |
---|
103 | */ |
---|
104 | |
---|
105 | #include <rtems/libio_.h> |
---|
106 | |
---|
107 | void |
---|
108 | __env_lock(struct _reent *r RTEMS_UNUSED) |
---|
109 | { |
---|
110 | rtems_libio_lock(); |
---|
111 | } |
---|
112 | |
---|
113 | void |
---|
114 | __env_unlock(struct _reent *r RTEMS_UNUSED) |
---|
115 | { |
---|
116 | rtems_libio_unlock(); |
---|
117 | } |
---|
118 | #endif /* ENVLOCK_DEDICATED_MUTEX */ |
---|
119 | |
---|
120 | #endif /* HAVE_ENVLOCK_H ... */ |
---|