removing taskvares (was Re: rtems_filesystem_current issues)

Chris Johns cjohns at cybertec.com.au
Mon Oct 28 03:03:47 UTC 2002


Eric Norum wrote:
> 
> On Saturday, October 26, 2002, at 06:32  PM, Chris Johns wrote:
> 
>> Till Straumann wrote:
>>
>>>
>>> Absolutely - one obvious solution would be attaching something like
>>>
>>> struct reent_rtems {
>>>     struct _reent _reent;
>>>     /* could have some padding here *7
>>>     struct userenv uenv;
>>> }
>>>
>>> to the _REENT pointer.
>>>
>>
>> I sort of agree. The introduction of a rtems_reent and a rtems_REENT
>> variable was something I was also considering. We need to keep the code
>> in the context switcher for the _REENT (_Thread_Set_libc_reent), and add
>> new code for rtems_REENT (_Thread_Set_rtems_reent). I do not think you
>> can change the meaning of _REENT without newlib being effected.
>>
>> It maybe a good time to look at the other uses of taskvars and remove
>> them. The C++ wrappers, shell, and RPC code.
>>
> 
> I've never been really happy with the addition of task variables to 
> RTEMS.   I added them a few years ago when the initial steps of moving 
> EPICS to a non-vxWorks platform were being made.  The EPICS IOC code 
> used task variables so it seemed like a good idea to add them to RTEMS. 
>  SInce then EPICS has been rewritten so that there is no longer any need 
> for task variables.  Unfortunately they've pushed their way into other 
> places, as noted above.

The taskvars API should exist as other will also have applications that 
need to move. Getting an application moved quickly onto RTEMS is 
important. Their use in the RTEMS package itself should be stopped.

> 
> I'd really like to find a good alternative that would work without 
> slowing task context switches and be efficient for application programs 
> to use without exposing too much of the RTEMS internals to the 
> application programmer.

That is a good summary of the requirements.

Moving aside for a moment, I would like to see RTEMS ship as standard 
with no User Extension switch handlers running ie ASR and POSIX signals 
support.

 >
> Perhaps a 'big-enough' array of void * inside 
> the RTEMS TCB and an agency (run by OAR somehow??) to assign 'well-known 
> indices' of these array elements?  e.g. RTEMS_TASKVAR_CXX_WRAPPER might 
> be 0, RTEMS_TASKVAR_RPC might be 1, etc.  There would be a macro/inline 
> function
> void **rtems_taskvar_get(int taskvar_index);
> Since the accessor method would be very fast, applications could for 
> example use:
> #define rtems_rpc_task_variables ((*(struct 
> _rtems_rpc_task_variables**)rtems_taskvar_get(RTEMS_TASKVAR_RPC))
> 
> This is just some early morning musing.  The idea of adding more 'magic 
> numbers' isn't very appealing to me, but neither is the existing O(n) 
> increase in context switch time for n task variables.....

I do not like magic numbers, plus adding a fixed size array is not 
great. You end up with yet another hidden configuration that uses more 
memory than it should by default to keep the support noise down and not 
enough for others.

To follow up on Till's first post, I think the idea of an RTEMS reent 
structure should be looked into.

We have a range of options, but first, to answer Fernando's concerns, 
the newlib code and support cannot be changed. In fact the kernel now 
has libc reent support in the context switcher for performance reasons. 
Look for _Thread_Set_libc_reent in the source. The libc switch is only a 
few instructions on the Coldfire now instead of the User extension 
switch handler list iteration, call overhead then pointer swap.

The User Extension create in the lastest source has a no cost impact on 
switch time. The User Extensions manager provides a "void*" slot in the 
TCB now, how-ever no API exists to access it cleanly. You can find the 
index using the "rtems_get_index" interface given the User Extension id. 
I updated the doco recently to include this. The missing piece is 
getting to the extensions array. The capture engine has this sort of 
code in it:

  task->extensions[capture_extension_index];

where task is a pointer to the TCB. This sort of code is fragle but 
fast. We need inline functions to get at the extensions array given a 
TCB pointer, or task id, and an explict:

  rtems_get_self_task_extension(index)

which references the executing thread global. Taking the address of a 
slot in the extensions array is not allowed. You need to index the array 
each time you need to access it.

Providing just a pointer array in the TCB is not enough. Typcially you 
will need to hook the create task call to allocate and setup a block of 
memory, and the delete call to release it. The User Extensions API does 
this already so a new API is not needed. The downside is the User 
Extension manager internally is not cheap on memory so allocating a 
single variable is not worth while. This is usually not a problem, for 
example RPC has a single taskvar that is a pointer to all its task 
variables.

So back to the RTEMS reent structure. My scan of the code shows we have 
libcsupport type variables, the C++ stuff and RPC. I feel RPC can access 
the User Manager directly and only use memory when a user needs RPC 
support. This leaves libc and the C++ support:

typedef struct rtems_reent_s {
     struct _reent _reent;

     struct userenv uenv;

     struct gxx_support gxx;
} rtems_reent_t;

The grouping all the libc (plus gcc) items is so the 
libcsupport/newlib.c code can perform a single allocation per task, plus 
it already creates a user extension. The &reent->_reent pointer is used 
as per the standard newlib support and is passed to 
_Thread_Set_libc_reent, while &reent is set into the extensions array. 
We can then define in a new header rtems_reent.h the structure and:

   #define rtems_REENT ((rtems_reent_t*) \
            rtems_get_self_task_extensions(libc_ext_index))

and use as:

   rtems_REENT->uenv.blah = 0;

The final issue is the User Extensions manager currently does not 
support the unlimited flag, so the number of User Extensions is fixed. 
The extensions array is allocated from the workspace for each task, so 
to support unlimited user extensions the extensions array of each task 
would need to be realloc'ed and the array copied. This is not important 
now, but explains the requirement of not taking the address of the 
extensions elements. It may be added in the future if user extension get 
more use.

-- 
  Chris Johns, cjohns at cybertec.com.au




More information about the users mailing list