Notice: We have migrated to GitLab launching 2024-05-01 see here: https://gitlab.rtems.org/

Ticket #1620: privateenv_v1.c

File privateenv_v1.c, 4.7 KB (added by Bharath Suri, on 07/29/10 at 20:48:38)

Version with changes

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: privateenv.c,v 1.14 2010/07/26 22:03:17 joel Exp $
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  /*
57   * Malloc is necessary whenever the current task does not
58   * have its own environment in place. This could be:
59   * a) it never had one
60   * OR
61   * b) it shared another task's environment
62   */
63
64  /*
65   * Bharath: I'm not sure if the check can be reduced to
66   * if( rtems_current_user_env->task_id != task_id ) {
67   */
68
69  if (rtems_current_user_env==&rtems_global_user_env ||
70      rtems_current_user_env->task_id != task_id ) {
71   rtems_user_env_t *tmp = malloc(sizeof(rtems_user_env_t));
72   if (!tmp)
73     return RTEMS_NO_MEMORY;
74
75#ifdef HAVE_USERENV_REFCNT
76   tmp->refcnt = 1;
77#endif
78
79   sc = rtems_task_variable_add(
80    RTEMS_SELF,
81    (void*)&rtems_current_user_env,
82    (void(*)(void *))free_user_env
83   );
84   if (sc != RTEMS_SUCCESSFUL) {
85    /* don't use free_user_env because the pathlocs are
86     * not initialized yet
87     */
88     free(tmp);
89     return sc;
90   }
91   rtems_current_user_env = tmp;
92  }
93
94  *rtems_current_user_env = rtems_global_user_env; /* get the global values*/
95  rtems_current_user_env->task_id=task_id;         /* mark the local values*/
96
97  /* Clone the pathlocs. In contrast to most other
98   * code we must _not_ free the original locs because
99   * what we are trying to do here is forking off
100   * clones. The reason is a pathloc can be allocated by the
101   * file system and needs to be freed when deleting the environment.
102   */
103
104  rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0);
105  rtems_filesystem_root    = loc;
106  rtems_filesystem_evaluate_path("/", 1, 0, &loc, 0);
107  rtems_filesystem_current = loc;
108
109  return RTEMS_SUCCESSFUL;
110}
111
112/*
113 *  Share a same private environment beetween two task:
114 *   Task_id (remote) and RTEMS_SELF(current).
115 */
116
117/* NOTE:
118 *
119 * THIS CODE HAS NO PROTECTION IMPLEMENTED
120 *
121 * Tasks who wish to share their environments must
122 *
123 *  a) assert that no participants are concurrently
124 *     executing
125 *     libio_share_private_env() and/or libio_set_private_env()
126 *
127 *  b) mutex access to rtems_filesystem_current, rtems_filesytem_root
128 *     while changing any of those (chdir(), chroot()).
129 */
130
131rtems_status_code rtems_libio_share_private_env(rtems_id task_id)
132{
133  rtems_status_code  sc;
134  rtems_user_env_t * shared_user_env;
135  rtems_id           current_task_id;
136
137  /*
138   * get current task id
139   */
140  current_task_id = rtems_task_self();
141
142  /*
143   * If this was an attempt to share the task with self,
144   * if somebody wanted to do it... Lets tell them, its shared
145   */
146
147  if( task_id == current_task_id )
148    return RTEMS_SUCCESSFUL;
149  /*
150   * Try to get the requested user environment
151   */
152  sc = rtems_task_variable_get(
153         task_id,
154         (void*)&rtems_current_user_env,
155         (void*)&shared_user_env );
156
157  /*
158   * If it was not successful, return the error code
159   */
160    if (sc != RTEMS_SUCCESSFUL)
161      return sc;
162
163    /*
164     * If we are here, we have the required environment to be
165     * shared with the current task
166    */
167
168    /*
169     * If we have a current environment in place, we need to
170     * free it, since we will be sharing the variable with the
171     * shared_user_env
172     */
173
174  if (rtems_current_user_env->task_id==current_task_id) {
175    rtems_user_env_t  *tmp = rtems_current_user_env;
176    free_user_env( tmp );
177  }
178
179  /* the current_user_env is the same pointer that remote env */
180  rtems_current_user_env = shared_user_env;
181
182  /* increase the reference count */
183#ifdef HAVE_USERENV_REFCNT
184  rtems_current_user_env->refcnt++;
185#endif
186
187  return RTEMS_SUCCESSFUL;
188}