C Library Re-entrancy/Thread-Safety

Comments

12 comments

  • Avatar
    Michael Johnson

    The fp math code is re-entrant - the math.h functions set errno which is implemented using TLS.

    Did you try changing stack sizes?

    0
    Comment actions Permalink
  • Avatar
    Jerry Gardner

    Yes, I tried changing stack sizes to sizes much larger than necessary. I also have a stack probe mechanism implemented and it shows that no task stack is ever growing to occupy more than about 25% of allocated space.

    0
    Comment actions Permalink
  • Avatar
    Jerry Gardner

    Okay, here's some more info:

    I whittled my code down to the bare minimum necessary to reproduce this issue. The offending line of code is this one:

    sprintf(cptr, "%3.2f\r", z);

     

    The variable "z" is declared as a double auto variable in the function containing the sprintf(). cptr is declared as an auto "uint8_t cptr[40]". When this line executes, an unrelated global variable in my app is corrupted. It's corrupted by the C library routine __putc (called from vfprintf, which is called from sprintf). I have interrupts disabled before executing this code (by setting PRIMASK to 1) to prevent any interrupt handlers from running.

    I have the project properties set as follows:

    Treat double as float: No

    Include standard libraries: Yes

    Library optimization: Fast

    Use GCC libraries: Yes

    Printf floating point supoprted: Yes

    Use multithreaded libraries: Yes or No (it doesn't matter--the issue occurs no matter what this is set to)

    I have the Cortex-M4 hardware FPU disabled. I have it disabled in the properties as well, and the compiler is not generating any floating point instructions, nor are there any in the libraries.

    What's going on here? Why is this call to sprintf corrupting an unrelated global variable in my application?

    0
    Comment actions Permalink
  • Avatar
    Jerry Gardner

    Well, I found why sprintf was corrupting another variable: it was generating more character output than the string could hold.

    I changed the sprintf to a snprintf and limited the output size to less than the size of the character array passed as the first parameter and this fixed the corruption of the global variable problem.

    Now the question becomes "why does snprintf generate wrong results?" For example, when I print the string generated by the following code

     

    uint8_t cptr[82];

    snprintf(cptr, 80, "z=%f\r", 3.14159);

    I get:

    z=-106833101327820180000000000000000000000000000000000000000000000000000000000000

    which is clearly bogus. I get the same result if I do

    snprintf(cptr, 80, "z=%f\r", (double)3.14159);

    or

    double z = 3.14159;

    snprintf(cptr, 80, "z=%f\r", z);

     

    As I mentioned in a previous comment, I do have "Printf Floating Point Supported" set to "YES" in the properties of my project.

     

    0
    Comment actions Permalink
  • Avatar
    Michael Johnson

    #include <__cross_studio_io.h>
    #include <stdint.h>
    #include <stdio.h>
    void
    main(void)
    {
      uint8_t cptr[82];
      snprintf(cptr, 80, "z=%f\r", 3.14159);
      debug_printf(cptr);
      debug_exit(0);
    }

    Seems to work on version 3.3 and 2.3

    0
    Comment actions Permalink
  • Avatar
    Jerry Gardner

    Michael,

    Can you post the project config options used to build the code you posted above? Even better if you can post a complete archived project file.

    I must have some subtle configuration settings mismatch that's causing my problem, but I just can't find it.

    Thanks.

    0
    Comment actions Permalink
  • Avatar
    Jerry Gardner

    Ah, I see that somewhere in the CrossWorks 3.x series you switched the default C compiler from gcc to clang. If I change my project properties to use gcc instead of clang, snprintf works as expected and I get "z=3.141590" on the output.

    I would actually prefer to use clang. What libraries do I need to specify when using it to get snprintf to work properly? I've already tried setting "Use GCC Libraries" to both YES and NO and that doesn't seem to affect the problem I'm seeing with snprintf when my code is compiled with clang.

    I'm using CrossWorks 3.2 by the way. I haven't updated to 3.3 yet.

    0
    Comment actions Permalink
  • Avatar
    Michael Johnson

    Did you

    #include <stdio.h>

    0
    Comment actions Permalink
  • Avatar
    Jerry Gardner

    Yes, I have included <stdio.h>

    0
    Comment actions Permalink
  • Avatar
    Michael Johnson

    Did you try 3.3 yet?

    0
    Comment actions Permalink
  • Avatar
    Jerry Gardner

    Not yet. I'll try it on Friday.

    0
    Comment actions Permalink
  • Avatar
    Jerry Gardner

    I finally got around to trying 3.3 (3.3.1 actually) and snprintf is now working properly, both with GCC and clang. No changes to my code.

    0
    Comment actions Permalink

Please sign in to leave a comment.