[PATCH 1/2] posix: Reimplement POSIX Key manager to use a red-black tree.

Gedare Bloom gedare at rtems.org
Thu Mar 14 22:53:25 UTC 2013


On Tue, Mar 12, 2013 at 8:34 PM, Gedare Bloom <gedare at rtems.org> wrote:
> From: Zhongwei Yao <ashi08104 at gmail.com>
>
> diff --git a/cpukit/posix/include/rtems/posix/key.h b/cpukit/posix/include/rtems/posix/key.h
> index 0bb1dbe..16aea78 100644
> --- a/cpukit/posix/include/rtems/posix/key.h
> +++ b/cpukit/posix/include/rtems/posix/key.h
> @@ -34,27 +37,53 @@ extern "C" {
>  #endif
>
>  /**
> - * This is the data Structure used to manage a POSIX key.
> - *
> - * NOTE: The Values is a table indexed by the index portion of the
> - *       ID of the currently executing thread.
> + * @brief The rbtree node used to manage a POSIX key and value.
> + */
> +typedef struct {
> +  /** This field is the chain node structure. */
> +  Chain_Node ch_node;
> +  /**
> +   * This field is the chain node, which is
> +   * used in pre-allocated key node chain.
> +   */
> +  Chain_Node pre_ch_node;
Is a POSIX_Keys_Rbtree_node ever on two chains (one with ch_node and
one with pre_ch_node) at the same time?

If not, then they can share the same Chain_Control. This would also
eliminate the need below to use offsetof.

> diff --git a/cpukit/posix/src/keysetspecific.c b/cpukit/posix/src/keysetspecific.c
> index b25e44c..de96964 100644
> --- a/cpukit/posix/src/keysetspecific.c
> +++ b/cpukit/posix/src/keysetspecific.c
> @@ -37,18 +41,41 @@ int pthread_setspecific(
>    const void    *value
>  )
>  {
> -  register POSIX_Keys_Control *the_key;
> -  uint32_t                     api;
> -  uint32_t                     index;
>    Objects_Locations            location;
> +  POSIX_Keys_Rbtree_node      *rb_node;
> +  Chain_Node                  *ch_node;
> +  POSIX_API_Control           *api;
>
> -  the_key = _POSIX_Keys_Get( key, &location );
> +  _POSIX_Keys_Get( key, &location );
>    switch ( location ) {
>
>      case OBJECTS_LOCAL:
> -      api   = _Objects_Get_API( _Thread_Executing->Object.id );
> -      index = _Objects_Get_index( _Thread_Executing->Object.id );
> -      the_key->Values[ api ][ index ] = (void *) value;
> +      ch_node = _Chain_Get_unprotected( &_POSIX_Keys_Preallocation_chain );
What if the Preallocation chain is empty?

> +      /* there is no _Chain_Container_of in RTEMS Chain API */
> +      rb_node = ( POSIX_Keys_Rbtree_node * ) \
> +        ( ( uintptr_t )( ch_node ) \
> +          - offsetof( POSIX_Keys_Rbtree_node, pre_ch_node ) );
Might not need this if you share the chain node for the two chains. If
you do need to, maybe we should implement _Chain_Container_of().


>
> diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h
> index cc55e92..2aaf30e 100644
> --- a/cpukit/sapi/include/confdefs.h
> +++ b/cpukit/sapi/include/confdefs.h
> @@ -1709,11 +1709,18 @@ rtems_fs_init_functions_t    rtems_fs_init_helper =
>
>    #ifndef CONFIGURE_MAXIMUM_POSIX_KEYS
>      #define CONFIGURE_MAXIMUM_POSIX_KEYS           0
> -    #define CONFIGURE_MEMORY_FOR_POSIX_KEYS(_keys) 0
> +    #define CONFIGURE_MAXIMUM_POSIX_KEY_PAIRS      0
> +    #define CONFIGURE_MEMORY_FOR_POSIX_KEYS(_keys, _key_pairs) 0
>    #else
> -    #define CONFIGURE_MEMORY_FOR_POSIX_KEYS(_keys) \
> +    #ifndef CONFIGURE_MAXIMUM_POSIX_KEY_PAIRS
> +      #define CONFIGURE_MAXIMUM_POSIX_KEY_PAIRS \
> +        CONFIGURE_MAXIMUM_POSIX_KEYS \
> +        * (CONFIGURE_MAXIMUM_POSIX_THREADS + CONFIGURE_MAXIMUM_TASKS)
> +    #endif
> +  #define CONFIGURE_MEMORY_FOR_POSIX_KEYS(_keys, _key_pairs)       \
>        (_Configure_Object_RAM(_keys, sizeof(POSIX_Keys_Control) ) \
> -        + (_keys) * 3 * _Configure_From_workspace(sizeof(void *) * 2))
> +      + _key_pairs                        \
> +      * _Configure_From_workspace(sizeof(POSIX_Keys_Rbtree_node)))
>    #endif
Both CONFIGURE_MAXIMUM_POSIX_KEY_PAIRS and
CONFIGURE_MAXIMUM_POSIX_KEYS should ignore the unlimited bit. Well,
the first should probably inherit it from either unlimited keys or
unlimited threads. The second should mask it off from _key_pairs by
_Configure_Max_Objects(_key_pairs).

We need to discuss the case of unlimited posix key pairs a little
further, because the pre-allocation strategy does not handle it
properly I think. The problem here is that a "key_pair" is not an
Object, and so it is not managed by the Object Manager, so it does not
make use of the pre-allocation support that Objects get. One approach
could be to wrap the pre-allocation of "key_pair" with the allocation
of keys themselves. This could easily handle limited and unlimited
keys with limited threads: allocate the number of keys * number of
threads every time Object allocation for keys occurs. The tricky case
is when threads is unlimited, in which case the Object allocation also
needs to allocate additional key_pairs when it allocates additional
threads.

-Gedare



More information about the devel mailing list