source: rtems/cpukit/libcsupport/src/privateenv.c @ e77a1934

4.115
Last change on this file since e77a1934 was e77a1934, checked in by Joel Sherrill <joel.sherrill@…>, on 07/15/10 at 21:31:10

2010-07-15 Joel Sherrill <joel.sherrill@…>

  • libcsupport/src/privateenv.c: Fix bug.
  • Property mode set to 100644
File size: 4.2 KB
Line 
1/*
2 *  Instantiate a private user environment for the calling thread.
3 *
4 *  Submitted by: fernando.ruiz@ctv.es (correo@fernando-ruiz.com)
5 *
6 *  COPYRIGHT (c) 1989-2010.
7 *  On-Line Applications Research Corporation (OAR).
8 *
9 *  The license and distribution terms for this file may be
10 *  found in the file LICENSE in this distribution or at
11 *  http://www.rtems.com/license/LICENSE.
12 *
13 *  $Id$
14 */
15
16#if HAVE_CONFIG_H
17#include "config.h"
18#endif
19
20#include <stdlib.h> /* free */
21
22#include <rtems.h>
23#include <rtems/chain.h>
24#include <rtems/libio.h>
25#include <rtems/libio_.h>
26
27/* cleanup a user environment
28 * NOTE: this must be called with
29 *       thread dispatching disabled!
30 */
31static void
32free_user_env(void *venv)
33{
34  rtems_user_env_t *env = (rtems_user_env_t*) venv ;
35
36 if (env != &rtems_global_user_env
37#ifdef HAVE_USERENV_REFCNT
38  && --env->refcnt <= 0
39#endif
40  ) {
41  rtems_filesystem_freenode( &env->current_directory);
42  rtems_filesystem_freenode( &env->root_directory);
43  free(env);
44 }
45}
46
47rtems_status_code rtems_libio_set_private_env(void)
48{
49  rtems_status_code      sc;
50  rtems_id               task_id;
51  rtems_filesystem_location_info_t  loc;
52
53  sc=rtems_task_ident(RTEMS_SELF,0,&task_id);
54  if (sc != RTEMS_SUCCESSFUL) return sc;
55
56  /* Only for the first time a malloc is necesary */
57  if (rtems_current_user_env==&rtems_global_user_env) {
58   rtems_user_env_t *tmp = malloc(sizeof(rtems_user_env_t));
59   if (!tmp)
60     return RTEMS_NO_MEMORY;
61
62#ifdef HAVE_USERENV_REFCNT
63   tmp->refcnt = 1;
64#endif
65
66   sc = rtems_task_variable_add(
67    RTEMS_SELF,
68    (void*)&rtems_current_user_env,
69    (void(*)(void *))free_user_env
70   );
71   if (sc != RTEMS_SUCCESSFUL) {
72    /* don't use free_user_env because the pathlocs are
73     * not initialized yet
74     */
75     free(tmp);
76     return sc;
77   }
78   rtems_current_user_env = tmp;
79  }
80
81  *rtems_current_user_env = rtems_global_user_env; /* get the global values*/
82  rtems_current_user_env->task_id=task_id;         /* mark the local values*/
83
84  /* Clone the pathlocs. In contrast to most other
85   * code we must _not_ free the original locs because
86   * what we are trying to do here is forking off
87   * clones. The reason is a pathloc can be allocated by the
88   * file system and needs to be freed when deleting the environment.
89   */
90
91  rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0);
92  rtems_filesystem_root    = loc;
93  rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0);
94  rtems_filesystem_current = loc;
95
96  return RTEMS_SUCCESSFUL;
97}
98
99/*
100 *  Share a same private environment beetween two task:
101 *   Task_id (remote) and RTEMS_SELF(current).
102 */
103
104/* NOTE:
105 *
106 * THIS CODE HAS NO PROTECTION IMPLEMENTED
107 *
108 * Tasks who wish to share their environments must
109 *
110 *  a) assert that no participants are concurrently
111 *     executing
112 *     libio_share_private_env() and/or libio_set_private_env()
113 *
114 *  b) mutex access to rtems_filesystem_current, rtems_filesytem_root
115 *     while changing any of those (chdir(), chroot()).
116 */
117
118#ifndef HAVE_USERENV_REFCNT
119rtems_status_code rtems_libio_share_private_env(rtems_id task_id)
120{
121  rtems_status_code  sc;
122  rtems_user_env_t * shared_user_env;
123  rtems_id           current_task_id;
124
125  sc=rtems_task_ident(RTEMS_SELF,0,&current_task_id);
126  if (sc != RTEMS_SUCCESSFUL) return sc;
127
128  if (rtems_current_user_env->task_id==current_task_id) {
129   /* kill the current user env & task_var*/
130   rtems_user_env_t  *tmp = rtems_current_user_env;
131   sc = rtems_task_variable_delete(RTEMS_SELF,(void*)&rtems_current_user_env);
132   if (sc != RTEMS_SUCCESSFUL) return sc;
133   free_user_env(tmp);
134  } else {
135    sc = rtems_task_variable_get(
136      task_id,(void*)&rtems_current_user_env, (void*)&shared_user_env );
137    if (sc != RTEMS_SUCCESSFUL)
138      goto bailout;
139  }
140
141  /* AT THIS POINT, rtems_current_user_env is DANGLING */
142
143  sc = rtems_task_variable_add(
144    RTEMS_SELF,(void*)&rtems_current_user_env,free_user_env);
145  if (sc != RTEMS_SUCCESSFUL)
146    goto bailout;
147
148  /* the current_user_env is the same pointer that remote env */
149  rtems_current_user_env = shared_user_env;
150
151  /* increase the reference count */
152#ifdef HAVE_USERENV_REFCNT
153  rtems_current_user_env->refcnt++;
154#endif
155
156  return RTEMS_SUCCESSFUL;
157
158bailout:
159  /* fallback to the global env */
160  rtems_current_user_env = &rtems_global_user_env;
161  return sc;
162}
163#endif
Note: See TracBrowser for help on using the repository browser.