This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TI-RTOS-MCU: statically preallocation a per thread struct _reent for newlib, GCC Linaro.

Part Number: TI-RTOS-MCU
Other Parts Discussed in Thread: LAUNCHXL-CC26X2R1, CC2640R2L, SYSBIOS

Dear TI support,

I'm trying to minimize per thread stack and heap usage on my application, with the GNU GCC Linaro 9.2.1 toolchain

When using errno for the first time withing a thread, newlib allocates a dynamic buffer for the _reent struct of the thread (I'm not using any other reentrancy features, I think).

The dynamic memory allocation is a small problem I think I can live with, as hopefully it will only happen once per thread (my threads are all static).

The problem cames because the memory allocation procedure takes a bunch of stack usage, but the threads then do not need so much memory later on. I can minize this thread usage if I force an allocation on thread start (by setting errno to 0, for example) avoiding allocations later on within a nested funcion call, however, I still get stack usage of about 700 bytes per thread, while in the rest of the working scenarios the threads are using something in the 400 figure (if errno is never used, i.e: stdlib funcionts are all happy with external environment uncontrollable input like "strtoul")

I would like to know if there's a way to configure TI-RTOS to statically preallocate this structure for each thread, so no dynamic memory allocation is neccessary and both heap and stack usage can be reduced or removed.

Thank you

  • Hi Pedro,

    Do device do you use?

  • CC2640R2L and LAUNCHXL-CC26x2R1

  • Hi Pedro,

    I am routing your query to the right team.

  • Hi,

    I have assigned the proper expert to answer your question.

    Please stay tuned.

    Best regards,

  • Hi,

    I am not entirely sure I understand the issue at hand. I see you mentioned that "my threads are all static", but I am not entirely sure how you created your threads. 

    The reason of my doubt is due to the fact that, when tasks are allocated statically (i.e., directly on the .cfg file), the task stack can also be defined to a fixed size - check section 7.5.2 of the TI-RTOS User's Guide:

    https://dev.ti.com/tirex/explore/node?node=ABkZJ9XPPWiX5v5YBrJbKg__pTTHBmu__LATEST

    Does that seem something that might work for you?

    Regards,

    Rafael

  • When using errno for the first time withing a thread, newlib allocates a dynamic buffer for the _reent struct of the thread (I'm not using any other reentrancy features, I think).

    Looking at simplelink_cc2640r2_sdk_5_10_00_02 it is not newlib which allocates the dynamic buffer for the __reent struct but the SYS/BIOS Newlib RTS library re-entrancy support module

    I would like to know if there's a way to configure TI-RTOS to statically preallocate this structure for each thread, so no dynamic memory allocation is neccessary and both heap and stack usage can be reduced or removed.

    Looking at the documentation for ti.sysbios.rts.gnu.ReentSupport, or the contents of simplelink_cc2640r2_sdk_5_10_00_02/kernel/tirtos/packages/ti/sysbios/rts/gnu/ReentSupport.c, I can't see any existing option to statically preallocate the structure for each thread. Maybe a custom task creation hook could do that.

    I'm not using any other reentrancy features, I think

    One possible option to avoid the dynamic memory allocation on the first use of errno in a task is to disable the re-entrancy support with the following in the SYS/BIOS cfg file:

    var ReentSupport = xdc.useModule('ti.sysbios.rts.gnu.ReentSupport');
    ReentSupport.enableReentSupport = false;

    The above means that the __getreent() function just returns a pointer to a global __reent struct which is shared by all threads. I.e. removes the per-thread dynamic memory allocation, but means the run time library functions are no longer re-entrant. E.g. saw that the value of errno was then shared between threads.

  • Thank you very much for your reply, Chester,

    First of all, as it looks like you are a bit of guru, could you point me to references about the build flags used by TI and custom rebuilding of the TI provided newlib?. I see that theres a file named "original.patch", but I think I'm missing things here about the build options used. I'm a bit new to newlib.

    The following are just considerations just in case someone has a similar scenario / new ideas / or TI considers allowing static allocation of the _reent struct:

    I now see that the buffer is allocated by the sysbios RTS, and then magic things happen within newlib (I'm not really sure of the build flags used by TI, I think that it is compiled with _REENT_SMALL, but not sure about _REENT_GLOBAL_STDIO_STREAMS), so __sinit is called and does stuff. Anyways, looks like the path here is to modify the TI-RTOS/newlib source, and that's maybe too overkill rigth now for me.

    About the custom hook, if I'm correct, the initializacion of the _reent struct should be performed within thread context, and that's once the stack is already set up, so not really much difference on stack usage here, maybe just avoiding heap allocation which is less of a problem for me.

    Anyways, will do some tests to see if the heavy stack usage comes from Memory_alloc or _REENT_INIT_PTR/_REENT_SMALL_CHECK_INIT

    Otherwise, I will try to reduce the number of threads or avoid using stdlib at all on some of them, or consider the option of disabling the reentrancy support and use a global mutex everytime a stdlib function is called.

  • Thank you , the problem is not about statically allocating the thread's stack, but about statically allocating newlib's _reent struct for each created thread, in order to avoid high stack usage and heap memory usage whenever a reentrancy feature of newlib is used for the first time, as implemented right now in the reentrancy support module of the Sysbios RTS.

    So the answer to my original questions seems to be like right now there's no (easy) way to statically allocate and initialize the _reent struct on a per thread basis.