Ticket #212: envlock.diff

File envlock.diff, 3.7 KB (added by strauman, on 12/03/06 at 13:31:13)

envlock.diff

Line 
1This patch (against rtems-ss20020301) adds support
2for libc environment locking by implementing
3
4__ENV_LOCK() / __ENV_UNLOCK().
5
6Author: Till Straumann <strauman@slac.stanford.edu>, 3/2002
7
8Index: c/src/lib/libc/Makefile.am
9===================================================================
10RCS file: /afs/slac/g/spear/cvsrep/rtems/src/c/src/lib/libc/Makefile.am,v
11retrieving revision 1.1.1.2
12retrieving revision 1.2
13diff -c -r1.1.1.2 -r1.2
14*** c/src/lib/libc/Makefile.am  2002/03/07 01:53:46     1.1.1.2
15--- c/src/lib/libc/Makefile.am  2002/03/28 20:59:16     1.2
16***************
17*** 32,37 ****
18--- 32,39 ----
19 
20  MALLOC_C_FILES = malloc.c mallocfreespace.c __brk.c __sbrk.c
21 
22+ ENVIRON_C_FILES = envlock.c
23+
24  PASSWORD_GROUP_C_FILES = getpwent.c getgrent.c
25 
26  TERMINAL_IDENTIFICATION_C_FILES = ctermid.c isatty.c ttyname.c ttyname_r.c
27***************
28*** 42,48 ****
29  UNIX_LIBC_C_FILES = unixlibc.c hosterr.c
30 
31  COMMON_C_FILES = gxx_wrappers.c printk.c $(BASE_FS_C_FILES) \
32!     $(MALLOC_C_FILES) $(TERMIOS_C_FILES) $(ERROR_C_FILES) \
33      $(ASSOCIATION_C_FILES)
34 
35  UNIX_C_FILES = $(UNIX_LIBC_C_FILES)
36--- 44,50 ----
37  UNIX_LIBC_C_FILES = unixlibc.c hosterr.c
38 
39  COMMON_C_FILES = gxx_wrappers.c printk.c $(BASE_FS_C_FILES) \
40!     $(MALLOC_C_FILES) $(ENVIRON_C_FILES) $(TERMIOS_C_FILES) $(ERROR_C_FILES) \
41      $(ASSOCIATION_C_FILES)
42 
43  UNIX_C_FILES = $(UNIX_LIBC_C_FILES)
44Index: c/src/lib/libc/envlock.c
45===================================================================
46RCS file: envlock.c
47diff -N envlock.c
48*** /dev/null   Thu Aug 24 02:00:32 2000
49--- /tmp/cvsdJUa8N      Sun May  5 11:22:32 2002
50***************
51*** 0 ****
52--- 1,79 ----
53+ /*
54+  *  $Id: envlock.c,v 1.2 2002/04/16 01:32:48 till Exp $
55+  *
56+  *  Author: Till Straumann <strauman@slac.stanford.edu>, 3/2002
57+  */
58+
59+ /* provide locking for the global environment 'environ' */
60+
61+ #if HAVE_CONFIG_H
62+ #include "config.h"
63+ #endif
64+
65+ #include <rtems.h>
66+ #include <sys/reent.h>
67+
68+ #include <assert.h>
69+
70+ /*
71+  * NOTES:
72+  *  - although it looks like a classical multiple-readers / single writer (MRSW)
73+  *    locking problem, we still use a single lock for the following reasons:
74+  *     1) newlib has no provision / hook for calling different locking routines
75+  *        from setenv/putenv and getenv, respectively.
76+  *     2) MRSW involves calling several semaphore-primitives, even in the most likely
77+  *        case of a first-reader's access. This probably takes more CPU
78+  *        time than just waiting until another reader is done; environment
79+  *        access is fast.
80+  *  - the lock implementation must allow nesting (same thread may call
81+  *    lock-lock-unlock-unlock).
82+  *  - NEWLIB-1.8.2 has an ugly BUG: if environ is NULL, _findenv_r() bails
83+  *    out leaving the lock held :-(
84+  * 
85+  */
86+
87+ static rtems_id envLock=0;
88+
89+ static void
90+ __rtems_envlock_init(void)
91+ {
92+ extern char                   **environ;
93+ rtems_status_code     rc;
94+
95+       if (envLock) /* already initialized */
96+               return;
97+
98+       assert(environ && "MUST have non-NULL 'environ' due to newlib bug");
99+
100+       rc = rtems_semaphore_create(
101+               rtems_build_name('E','N','V','S'),
102+               1,
103+               RTEMS_BINARY_SEMAPHORE | RTEMS_PRIORITY | RTEMS_INHERIT_PRIORITY,
104+               0,
105+               &envLock);
106+       if (RTEMS_SUCCESSFUL!=rc)
107+               rtems_fatal_error_occurred(rc);
108+ }
109+
110+ void
111+ __env_lock(struct _reent *r)
112+ {
113+ /* Do lazy init */
114+ if (!envLock)
115+       __rtems_envlock_init();
116+ /* Must not use a semaphore before multitasking is up
117+  * - it will corrupt memory :-(
118+  */
119+ if (_Thread_Executing)
120+       rtems_semaphore_obtain(envLock, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
121+ }
122+
123+ void
124+ __env_unlock(struct _reent *r)
125+ {
126+ /* Must not use a semaphore before multitasking is up
127+  * - it will corrupt memory :-(
128+  */
129+ if (_Thread_Executing)
130+       rtems_semaphore_release(envLock);
131+ }