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