On 09/09/2020 07:56, Chris Johns wrote:
On 9/9/20 3:14 pm, Sebastian Huber wrote:
On 09/09/2020 03:37, Chris Johns wrote:
On 9/9/20 8:43 am, Joel Sherrill wrote:
On Wed, Sep 2, 2020 at 11:09 AM Sebastian Huber
<sebastian.hu...@embedded-brains.de <mailto:sebastian.hu...@embedded-brains.de>>
wrote:
+/**
+ * @brief Returns the recommended task storage area size for the
specified size
+ * and task attributes.
+ *
+ * @param _size is the size dedicated to the task stack and thread-local
+ * storage.
How does the user get the TLS size?
Need advice on that. Seems hard to get at compile time since it is a link
time aggregation.
I had not noticed this. Thank you for raising it.
The TLS size is only known after linking. The symbol _TLS_Size is defined by the
linker script.
Yes and this approach breaks dynamic loading but I cannot recall it or change
it.
This approach is defined by the ABI.
The rtems_task_create_from_config() directives is for users who
want to have full control over their memory allocation. These users have to know
what they are doing. It is not for everyone.
The API will exist without those consideration. I think that statement carries
no technical weight.
Knowing the task size is also not an easy thing. It depends an what you call and
what the compiler did.
I am with Joel on this, the accounting needs to be accurate.
The TLS size is known a link-time and the size of the user-provided task
storage area must be known at compile-time. These are the constraints we
have. From my point of view all what we can do is a sanity check at
run-time. Do you have a better approach?
Does the API call check this new size value against the size actually needed?
I think we should add a sanity check. We could for example check that after
allocating the FP context and the TLS area, the size for the stack is greater
than or equal to rtems_minimum_stack_size.
Sure.
I thought the TLS size was set by the linker based on the declared TLS variables
in the code and that value is feed into the calculation of the memory when
dynamically allocating the task's space. I am now wondering if this is accounted
for if the allocation is from the workspace (sizeof(TLS) * tasks)?
Yes, it is, see rtems_configuration_get_stack_space_size().
That looks like a runtime call? At the moment is the TLS data area allocated
from a workspace? If so is that space part of the work space size calculation?
Yes, see _Workspace_Handler_initialization(). The estimate from
confdefs.h and the actual TLS size determine the workspace size.
A linker
controlled size is fine for the statically linked only class of application
however it is broken for applications that dynamically load code with TLS
variables. There is a growing number of important applications dynamically
loading code so we need to consider it.
I would like to see us resolve how we manage TLS allocation for this case and
dynamic loading before I am OK with this change. I do not think it is fair to
have dynamic loading fit in or work around a change in this area.
FreeBSD and Linux dynamically allocate the TLS blocks and Linux resizes the
blocks when dynamically loaded code contains TLS variables. That approach is not
as easy on RTEMS for a range of reasons that are not important here.
A single allocation for all the data a task needs is attractive. It allows this
API to work and it saves the heap block overheads when using an allocator. It
however means the TLS size needs to be set to the maximum for an application
including all dynamically loaded code.
Maybe the ability to set the size in confdefs.h at the system level would be
sufficient. Defining it at the task level is misleading because it implies tasks
can have different TLS sizes and they cannot. A system level TLS size of 0 could
be used to have the linker size be the size used, this would be compatible to
what we currently have.
I think this TLS issue with dynamic linking is independent of the
rtems_task_create_from_config().
As the person who would have to add libdl support for TLS this change as it
stands makes a bunch of extra work to make this API OK and I would prefer not to
have to do that.
What kind of extra work?
It would be easy to add a
CONFIGURE_MAXIMUM_THREAD_LOCAL_STORAGE_SIZE
application configuration option. If the TLS size defined by the linker is
greater, then we would have a fatal system initialization error. An extra space
can be used by the dynamic linker.
Can CONFIGURE_MAXIMUM_THREAD_LOCAL_STORAGE_SIZE define the size of the TLS
section and if the linker overflows it we get an error?
Maybe we could make it a link-time error, but this would require some
linker script magic. We would have to define the size as a symbol (we
already do this for CONFIGURE_INTERRUPT_STACK_SIZE). I don't know you
you can force a linker error if for example the value of symbol A >
value of symbol B.
Not providing enough
space for dynamically loaded code is a runtime error returned by the dlopen call
so that is not an issue here.
A system level size of 0 for this new API call would be
a fatal error the there are TLS variables.
No, it don't think this should be an error. I think it would be enough to check
that after allocating the FP context and the TLS area, the size for the stack is
greater than or equal to rtems_minimum_stack_size.
If I understand Joel's question the user does not know the TLS size however it
is on the @param doco line so is the space accounted for in the statically
allocated task space or not? If it is not accounted for and no space is
allocated and there are TLS variables are you borrowing memory from something
else?
The user provides a size for the stack and the TLS. The stack uses what
is left by the TLS area.
If a system level TLS size is adopted it can be used to manage this API's static
allocation and if 0 is used as a default to say use the linker computed value,
ie add no extra space because there is no dynamic loading, then it should be an
error because for this API any TLS variable present will not have any allocated
space.
What about a test for this API that has a 100K char TLS array and all the other
task values as defaults? If the space allocated and reported in the link map is
not just over 100K there is a problem.
As I said before, this API is for users which want to do the memory
allocation on their own. These users must know when they have an 100K
char TLS array in their application. They just have to use in this case:
#define MY_TLS (100K + whatever)
RTEMS_TASK_STORAGE_SIZE( MY_TLS + MY_STACK_SIZE, MY_ATTRIBUTES )
TLS management in RTEMS is similar to the SDATA area the PowerPC has. The only
difference is the TLS size can be varied and the SDATA size is fixed in
hardware. If a system level TLS size is supported and that value has a suitable
interface libdl can support dynamically loaded TLS variables the same way SDATA
is handled on the PowerPC. Libdl uses a bit-allocator to track 32bit blocks of
SDATA. The statically linked usage is known and initialised and libdl assumes
ownership of the remaining space. The TLS block can be handled the same way. The
RTL lock handles the runtime set up without effecting scheduling and the same
can happen for TLS data.
Yes, this sounds good.
Great and thanks.
Chris
--
Sebastian Huber, embedded brains GmbH
Address : Dornierstr. 4, D-82178 Puchheim, Germany
Phone : +49 89 189 47 41-16
Fax : +49 89 189 47 41-09
E-Mail : sebastian.hu...@embedded-brains.de
PGP : Public key available on request.
Diese Nachricht ist keine geschäftliche Mitteilung im Sinne des EHUG.
_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel