<div dir="ltr">Hi, all, as Gedare pointed out in previous post, the solution in this patch *can't* support unlimited POSIX Key well(it's exactly the case when unlimited mode enabled). After some discussion, I come up with a new solution, which can support unlimited mode, but also with some defect. <br>
<br>The idea is:<br>put all memory allocation work in POSIX Key manager to Object Manager, then we needn't allocate memory from workspace when each key value create, which is very similar to the pre-allocation approach in this patch and the other important benefit is since the memory allocation is managed by Object Manager, it can support unlimited mode automatically.<br>
And to the management of key value, let pthread_key_t type be a chain head, which keeps track of value within that key and then  set_specific() operation in POSIX Key can iterate this chain to find specific key value. However, this can be a problem when a key is used by many threads at same time(say n threads for example), in which worst case the runtime of set_specific() is O(n) and another concern is the memory overhead. Because every key value is associated with one Objects_control structure.<br>
<br><span id="result_box" class="" lang="en"><span class="">Do you have any suggestion to this idea? Is the unlimited mode very important for POSIX Key? Thanks for any reply! And If necessary</span></span>, I can add more details.<br>
<br>Best regards,<br>Zhongwei<br></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Mon, Mar 18, 2013 at 10:08 PM, Ashi <span dir="ltr"><<a href="mailto:ashi08104@gmail.com" target="_blank">ashi08104@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Hi, Gedare, I think Joel has mentioned this about unlimited problem. I remember Joel has suggested a way to deal with this when use the pre-allocation approach. But I haven't got that idea... However, I only find my problem description mail, haven't found Joel's solution... Joel, do you remember there is such a mail?</div>

<div><div>"</div><div>>Joel wrote:</div><div>>>9/12/2012 5:08 AM, Ashi wrote:<br>>>Hi, Joel. <br>      >>My work stops at the problem of how to support unlimited mode when      we <span>pre</span>-allocate all memory at key manager >>initialization, and I      still haven't got time to learn the object extend code sample as      Chris mentioned in last mail. And I >>also haven't figured out how      to write right Configuration in confdef.h, my last post in      dev-list is about this.<br>

      >>I really have a busy time these days, and really sorry for my slow      progress. Anyway I'll try my best!<br></div>    >I think it should be merged as it is. When in unlimited mode, we can    document the<br>

    >recommendation that you use a unified work space.  We can leave this    as a<br>    >future enhancement. <br><br>    >But what you did is a BIG improvement. This next step is an    integration clean up<br>    >that can occur separately.<br>

<br>    >let's move to review and merge what you have, update the project    page, check coverage<br>    >on what's there, etc.<div><div><img src="https://mail.google.com/mail/u/0/images/cleardot.gif">"<br>

<br></div></div></div><div><div class="h5"><div class="gmail_quote">On Fri, Mar 15, 2013 at 6:53 AM, Gedare Bloom <span dir="ltr"><<a href="mailto:gedare@rtems.org" target="_blank">gedare@rtems.org</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;padding-left:1ex;border-left-color:rgb(204,204,204);border-left-width:1px;border-left-style:solid">On Tue, Mar 12, 2013 at 8:34 PM, Gedare Bloom <<a href="mailto:gedare@rtems.org" target="_blank">gedare@rtems.org</a>> wrote:<br>



> From: Zhongwei Yao <<a href="mailto:ashi08104@gmail.com" target="_blank">ashi08104@gmail.com</a>><br>
<div>><br>
> diff --git a/cpukit/posix/include/rtems/posix/key.h b/cpukit/posix/include/rtems/posix/key.h<br>
> index 0bb1dbe..16aea78 100644<br>
> --- a/cpukit/posix/include/rtems/posix/key.h<br>
> +++ b/cpukit/posix/include/rtems/posix/key.h<br>
</div><div>> @@ -34,27 +37,53 @@ extern "C" {<br>
>  #endif<br>
><br>
>  /**<br>
> - * This is the data Structure used to manage a POSIX key.<br>
> - *<br>
> - * NOTE: The Values is a table indexed by the index portion of the<br>
> - *       ID of the currently executing thread.<br>
> + * @brief The rbtree node used to manage a POSIX key and value.<br>
> + */<br>
> +typedef struct {<br>
> +  /** This field is the chain node structure. */<br>
> +  Chain_Node ch_node;<br>
> +  /**<br>
> +   * This field is the chain node, which is<br>
> +   * used in pre-allocated key node chain.<br>
> +   */<br>
> +  Chain_Node pre_ch_node;<br>
</div>Is a POSIX_Keys_Rbtree_node ever on two chains (one with ch_node and<br>
one with pre_ch_node) at the same time?<br>
<br>
If not, then they can share the same Chain_Control. This would also<br>
eliminate the need below to use offsetof.<br>
<div><br>
> diff --git a/cpukit/posix/src/keysetspecific.c b/cpukit/posix/src/keysetspecific.c<br>
> index b25e44c..de96964 100644<br>
> --- a/cpukit/posix/src/keysetspecific.c<br>
> +++ b/cpukit/posix/src/keysetspecific.c<br>
</div><div>> @@ -37,18 +41,41 @@ int pthread_setspecific(<br>
>    const void    *value<br>
>  )<br>
>  {<br>
> -  register POSIX_Keys_Control *the_key;<br>
> -  uint32_t                     api;<br>
> -  uint32_t                     index;<br>
>    Objects_Locations            location;<br>
> +  POSIX_Keys_Rbtree_node      *rb_node;<br>
> +  Chain_Node                  *ch_node;<br>
> +  POSIX_API_Control           *api;<br>
><br>
> -  the_key = _POSIX_Keys_Get( key, &location );<br>
> +  _POSIX_Keys_Get( key, &location );<br>
>    switch ( location ) {<br>
><br>
>      case OBJECTS_LOCAL:<br>
> -      api   = _Objects_Get_API( _Thread_Executing->Object.id );<br>
> -      index = _Objects_Get_index( _Thread_Executing->Object.id );<br>
> -      the_key->Values[ api ][ index ] = (void *) value;<br>
> +      ch_node = _Chain_Get_unprotected( &_POSIX_Keys_Preallocation_chain );<br>
</div>What if the Preallocation chain is empty?<br>
<div><br>
> +      /* there is no _Chain_Container_of in RTEMS Chain API */<br>
> +      rb_node = ( POSIX_Keys_Rbtree_node * ) \<br>
> +        ( ( uintptr_t )( ch_node ) \<br>
> +          - offsetof( POSIX_Keys_Rbtree_node, pre_ch_node ) );<br>
</div>Might not need this if you share the chain node for the two chains. If<br>
you do need to, maybe we should implement _Chain_Container_of().<br>
<div><br>
<br>
><br>
> diff --git a/cpukit/sapi/include/confdefs.h b/cpukit/sapi/include/confdefs.h<br>
> index cc55e92..2aaf30e 100644<br>
> --- a/cpukit/sapi/include/confdefs.h<br>
> +++ b/cpukit/sapi/include/confdefs.h<br>
> @@ -1709,11 +1709,18 @@ rtems_fs_init_functions_t    rtems_fs_init_helper =<br>
><br>
>    #ifndef CONFIGURE_MAXIMUM_POSIX_KEYS<br>
>      #define CONFIGURE_MAXIMUM_POSIX_KEYS           0<br>
> -    #define CONFIGURE_MEMORY_FOR_POSIX_KEYS(_keys) 0<br>
> +    #define CONFIGURE_MAXIMUM_POSIX_KEY_PAIRS      0<br>
> +    #define CONFIGURE_MEMORY_FOR_POSIX_KEYS(_keys, _key_pairs) 0<br>
>    #else<br>
> -    #define CONFIGURE_MEMORY_FOR_POSIX_KEYS(_keys) \<br>
> +    #ifndef CONFIGURE_MAXIMUM_POSIX_KEY_PAIRS<br>
> +      #define CONFIGURE_MAXIMUM_POSIX_KEY_PAIRS \<br>
> +        CONFIGURE_MAXIMUM_POSIX_KEYS \<br>
> +        * (CONFIGURE_MAXIMUM_POSIX_THREADS + CONFIGURE_MAXIMUM_TASKS)<br>
> +    #endif<br>
> +  #define CONFIGURE_MEMORY_FOR_POSIX_KEYS(_keys, _key_pairs)       \<br>
>        (_Configure_Object_RAM(_keys, sizeof(POSIX_Keys_Control) ) \<br>
> -        + (_keys) * 3 * _Configure_From_workspace(sizeof(void *) * 2))<br>
> +      + _key_pairs                        \<br>
> +      * _Configure_From_workspace(sizeof(POSIX_Keys_Rbtree_node)))<br>
>    #endif<br>
</div>Both CONFIGURE_MAXIMUM_POSIX_KEY_PAIRS and<br>
CONFIGURE_MAXIMUM_POSIX_KEYS should ignore the unlimited bit. Well,<br>
the first should probably inherit it from either unlimited keys or<br>
unlimited threads. The second should mask it off from _key_pairs by<br>
_Configure_Max_Objects(_key_pairs).<br>
<br>
We need to discuss the case of unlimited posix key pairs a little<br>
further, because the pre-allocation strategy does not handle it<br>
properly I think. The problem here is that a "key_pair" is not an<br>
Object, and so it is not managed by the Object Manager, so it does not<br>
make use of the pre-allocation support that Objects get. One approach<br>
could be to wrap the pre-allocation of "key_pair" with the allocation<br>
of keys themselves. This could easily handle limited and unlimited<br>
keys with limited threads: allocate the number of keys * number of<br>
threads every time Object allocation for keys occurs. The tricky case<br>
is when threads is unlimited, in which case the Object allocation also<br>
needs to allocate additional key_pairs when it allocates additional<br>
threads.<br>
<span><font color="#888888"><br>
-Gedare<br>
</font></span></blockquote></div></div></div><div class="gmail_extra">Cheers,</div><div class="gmail_extra">Zhongwei<br></div></div>
</blockquote></div><br></div>