source: rtems/c/src/exec/libcsupport/src/envlock.c @ baf71338

4.104.114.84.95
Last change on this file since baf71338 was baf71338, checked in by Joel Sherrill <joel.sherrill@…>, on 05/14/02 at 19:02:06

2001-05-14 Till Straumann <strauman@…>

  • Per PR212, added envlock support for newlib. This is used by at least getenv()/putenv() to avoid race conditions.
  • libc/envlock.c: New file.
  • libc/Makefile.am: Modified to reflect above.
  • Property mode set to 100644
File size: 2.0 KB
Line 
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
35static rtems_id envLock=0;
36
37static 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
58void
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
73void
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}
Note: See TracBrowser for help on using the repository browser.