1 | /* |
---|
2 | * $Id$ |
---|
3 | * |
---|
4 | * Author: Till Straumann <strauman@slac.stanford.edu>, 3/2002 |
---|
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 | */ |
---|
34 | |
---|
35 | static rtems_id envLock=0; |
---|
36 | |
---|
37 | static void |
---|
38 | __rtems_envlock_init(void) |
---|
39 | { |
---|
40 | extern char **environ; |
---|
41 | rtems_status_code rc; |
---|
42 | |
---|
43 | if (envLock) /* already initialized */ |
---|
44 | return; |
---|
45 | |
---|
46 | assert(environ && "MUST have non-NULL 'environ' due to newlib bug"); |
---|
47 | |
---|
48 | rc = rtems_semaphore_create( |
---|
49 | rtems_build_name('E','N','V','S'), |
---|
50 | 1, |
---|
51 | RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY, |
---|
52 | 0, |
---|
53 | &envLock); |
---|
54 | if (RTEMS_SUCCESSFUL!=rc) |
---|
55 | rtems_fatal_error_occurred(rc); |
---|
56 | } |
---|
57 | |
---|
58 | void |
---|
59 | __env_lock(struct _reent *r) |
---|
60 | { |
---|
61 | /* Do lazy init */ |
---|
62 | if (!envLock) |
---|
63 | __rtems_envlock_init(); |
---|
64 | /* |
---|
65 | * Must not use a semaphore before pre-tasking hook is called. |
---|
66 | * - it will corrupt memory :-( |
---|
67 | */ |
---|
68 | |
---|
69 | if (_Thread_Executing) |
---|
70 | rtems_semaphore_obtain(envLock, RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
---|
71 | } |
---|
72 | |
---|
73 | void |
---|
74 | __env_unlock(struct _reent *r) |
---|
75 | { |
---|
76 | /* |
---|
77 | * Must not use a semaphore before pre-tasking hook is called. |
---|
78 | * - it will corrupt memory :-( |
---|
79 | */ |
---|
80 | if (_Thread_Executing) |
---|
81 | rtems_semaphore_release(envLock); |
---|
82 | } |
---|