Keil™, An ARM® Company

RealView Libraries and Floating Point Support Guide

On-Line Manuals

RealView Libraries and Floating Point Support Guide

Preface
Introduction
The C and C++ Libraries
About the C and C++ libraries
Features of the C and C++ libraries
Namespaces
Writing reentrant and thread‑safe code
Introduction to reentrancy and thread‑safety
Use of static data in the C libraries
The __user_libspace static data area
Managing locks in multithreaded applications
Using the ARM C libraries with a multithreaded app
Thread‑safety in the ARM C libraries
Thread‑safety in the ARM C++ libraries
Building an application with the C library
Using the libraries with an application
Building an application for a semihosted environme
Building an application for a non semihosting envi
Building an application without the C library
Integer and FP helper functions
Bare machine integer C
Bare machine C with floating‑point
Exploiting the C library
The standalone C library functions
Tailoring the C library to a new execution environ
How C and C++ programs use the library functions
__rt_entry
Exiting from the program
__rt_exit()
__rt_lib_init()
__rt_lib_shutdown()
Tailoring static data access
Tailoring locale and CTYPE using assembler macros
Selecting locale at link time
Selecting locale at runtime
Defining a locale block
LC_CTYPE data block
LC_COLLATE data block
LC_MONETARY data block
LC_NUMERIC data block
LC_TIME data block
_get_lconv()
localeconv()
setlocale()
_findlocale()
The lconv structure
Tailoring locale and CTYPE using C macros
Selecting locale at link time
Selecting locale at runtime
Macros and utility functions
_get_lc_ctype()
_get_lc_collate()
_get_lc_monetary()
_get_lc_numeric()
_get_lc_time()
_get_lconv()
localeconv()
setlocale()
_findlocale()
__LC_CTYPE_DEF
__LC_COLLATE_DEF
__LC_TIME_DEF
__LC_NUMERIC_DEF
__LC_MONETARY_DEF
__LC_INDEX_END
The lconv structure
Tailoring error signaling, error handling, and pro
_sys_exit()
errno
__rt_errno_addr()
__raise()
__rt_raise()
__default_signal_handler()
_ttywrch()
__rt_fp_status_addr()
Tailoring storage management
Avoiding the ARM‑supplied heap and heap‑using
Support for malloc
Tailoring the runtime memory model
The memory models
Controlling the runtime memory model
Writing your own memory model
__user_initial_stackheap()
__user_setup_stackheap()
__user_heap_extend()
__user_heap_extent()
__user_stack_cleanup_space()
__rt_heap_extend()
__rt_stack_postlongjmp()
Tailoring the input/output functions
Dependencies on low‑level functions
Target‑dependent input/output support functions
_sys_open()
_sys_close()
_sys_read()
_sys_write()
_sys_ensure()
_sys_flen()
_sys_seek()
_sys_istty()
_sys_tmpnam()
_sys_command_string()
#pragma import(_main_redirection)
Tailoring other C library functions
clock()
_clock_init()
time()
remove()
rename()
system()
getenv()
_getenv_init()
Selecting real‑time division
ISO implementation definition
ISO C library implementation definition
Standard C++ library implementation definition
C library extensions
atoll()
strtoll()
strtoull()
printf()
snprintf()
vsnprintf()
lldiv()
llabs()
wcstombs()
alloca()
strlcpy()
strlcat()
_fisatty()
__heapstats()
__heapvalid()
Library naming conventions
Placing ARM libraries
Helper libraries
Identifying library variants
The C Micro-library
Floating‑point Support

Thread‑safety in the ARM C libraries

2.2.6. Thread‑safety in the ARM C libraries

In the ARM libraries, functions can be thread‑safe as follows:

  • Some functions are never thread‑safe, for example setlocale().

  • Some functions are always thread‑safe, for example fopen().

  • Other functions are only thread‑safe if you pass the appropriate arguments, for example tmpnam().

Threading problems might occur when your application makes use of the ARM libraries in a way that is hidden, for example, if you are using the language helper functions.

Functions that are thread‑safe

Table 2.1 shows those C library functions that are thread‑safe.

Table 2.1. Functions that are thread‑safe

FunctionsDescription
calloc(), free(), malloc(),
realloc()

The heap functions are thread‑safe.

A single heap is shared between all threads, and mutexes are used to avoid data corruption when there is concurrent access. Each heap implementation is responsible for doing its own locking. If you supply your own allocator, it must also do its own locking. This enables it to do fine‑grained locking, if required, rather than simply protecting the entire heap with a single mutex (coarse‑grained locking).

__alloca(), __alloca_finish(),
__alloca_init(),
__alloca_initialize()

The alloca functions are thread‑safe.

The alloca state for each thread is contained in the __user_perthread_libspace block. This means that multiple threads do not conflict.

Note

Be aware that the alloca functions also use the heap. However, heap functions are all thread‑safe.

abort(), raise(), signal(),
fenv.h

The ARM signal handling functions and FP exception traps are thread‑safe.

The settings for signal handlers and FP traps are global across the entire process and are protected by locks. Data corruption does not occur if multiple threads call signal() or an fenv.h function at the same time. However, be aware that the effects of the call act on all threads and not just on the calling thread.

clearerr(), fclose(), feof(),
ferror(), fflush(), fgetc(),
fgetpos(), fgets(), fopen(),
fputc(), fputs(), fread(),
freopen(), fseek(), fsetpos(),
ftell(), fwrite(), getc(),
getchar(), gets(), perror(),
putc(), putchar(), puts(),
rewind(), setbuf(), setvbuf(),
tmpfile(), tmpnam(), ungetc()

The stdio library is thread‑safe.

Each individual stream is protected by a lock, so two threads can each open their own stdio stream and use it, without interfering with one another.

If two threads both want to read or write the same stream, locking at the fgetc() and fputc() level prevents data corruption, but it is possible that the individual characters output by each thread might be interleaved in a confusing way.

Note

Be aware that tmpnam() also contains a static buffer but this is only used if the argument is NULL. To ensure that your use of tmpnam() is thread‑safe, supply your own buffer space.

fprintf(), printf(), vfprintf(),
vprintf(), fscanf(), scanf()

When using these functions:

  • The standard C printf() and scanf() functions use stdio, and so are thread‑safe.

  • The standard C printf() is susceptible to changes in the locale settings if called in a multithreaded program.

clock()
clock() contains static data that is written once at program startup and then only ever read. Therefore, clock() is thread‑safe provided no extra threads are already running at the time that the library is initialized.
errno()

errno is thread‑safe.

Each thread has its own errno stored in a __user_perthread_libspace block. This means that each thread can call errno‑setting functions independently and then check errno afterwards without fearing other threads.

atexit()

The list of exit functions maintained by atexit() is process‑global and protected by a lock.

In the worst case, if more than one thread calls atexit(), the order that exit functions are called cannot be guaranteed.

abs(), acos(), asin(),
atan(), atan2(), atof(),
atol(), atoi(), bsearch(),
ceil(), cos(), cosh(),
difftime(), div(), exp(),
fabs(), floor(), fmod(),
frexp(), labs(), ldexp(),
ldiv(), log(), log10(),
memchr(), memcmp(), memcpy(),
memmove(), memset(), mktime(),
modf(), pow(), qsort(),
sin(), sinh(), sqrt(),
strcat(), strchr(), strcmp(),
strcpy(), strcspn(), strlcat(),
strlcpy(), strlen(), strncat(),
strncmp(), strncpy(), strpbrk(),
strrchr(), strspn(), strstr(),
strxfrm(), tan(), tanh()

These functions are thread‑safe.

longjmp(), setjmp()

Although setjmp() and longjmp() keep data in __user_libspace, they call the __alloca_* functions, which are thread‑safe.

remove(), rename(), time()

These use interrupts that communicate with the ARM debugging environments. Typically, you have to re‑implement these for a real‑world application.

snprintf(), sprintf(), vsnprintf(),
vsprintf(), sscanf(), isalnum(),
isalpha(), iscntrl(), isdigit(),
isgraph(), islower(), isprint(),
ispunct(), isspace(), isupper(),
isxdigit(), tolower(), toupper(),
strcoll(), strtod(), strtol(),
strtoul(), strftime()

When using these functions, the string‑based functions read the locale settings. Typically, they are thread‑safe. However, if you change locale in mid‑session, you must ensure that these functions are not affected.

The string‑based functions, such as sprintf() and sscanf(), do not depend on the stdio library.

stdin, stdout, stderr
These are thread‑safe.
FP status word

The FP status word is safe to use in a multithreaded environment, even in software floating‑point. Here, a status word for each thread is stored in its own __user_perthread_libspace block.

Note

Be aware that, in hardware floating‑point, the FP status word is stored in a VFP register. In this case, your thread‑switching mechanism must keep a separate copy of this register for each thread.

Functions that are not thread‑safe

Table 2.2 shows the C library functions that are not thread‑safe.

Table 2.2. Functions that are not thread‑safe

FunctionsDescription
setlocale()

The locale settings are global across all threads, and are not protected by a lock. If two threads call setlocale(), there might be data corruption. Also, many other functions, for example strtod() and sprintf(), read the current locale settings. So, if one thread calls setlocale() concurrently with another thread calling such a function then there might be unexpected results.

ARM recommends that you choose the locale you want and call setlocale() once to initialize it. Do this before creating any additional threads in your program so that any number of threads can read the locale settings concurrently without interfering with one another.

Be aware that localeconv() is not thread‑safe. Call the ARM function _get_lconv() with a pointer to a user‑supplied buffer instead.

asctime(), localtime(), strtok()

These functions are all thread‑unsafe. Each contains a static buffer that might be overwritten by another thread between a call to the function and the subsequent use of its return value.

ARM supplies reentrant versions, asctime_r(), localtime_r(), and strtok_r(), as specified by POSIX. ARM recommends that you use these functions instead to ensure safety.

Note

These reentrant versions take additional parameters that are pointers to a char pointer to the next token.

gamma(), lgamma()
These extended mathlib functions, defined in math.h, use a global variable, signgam, and so are not thread‑safe. ARM recommends that you use gamma_r() and lgamma_r() instead. These write the sign of the result into memory pointed to by a supplied int * argument.
mbrlen(), mbsrtowcs(), mbrtowc(),
wcrtomb(), wcsrtombs()

The C89 multibyte conversion functions (defined in stdlib.h) are not thread‑safe, for example mblen() and mbtowc(), because they contain internal static state that is shared between all threads without locking.

However, the extended restartable versions (defined in wchar.h) are thread‑safe, for example mbrtowc() and wcrtomb(), provided you pass in a pointer to your own mbstate_t object. You must exclusively use these functions with non‑NULL mbstate_t * parameters if you want to ensure thread‑safety when handling multibyte strings.

exit()

Do not call exit() in a multithreaded program even if you have provided an implementation of the underlying _sys_exit() that actually terminates all threads.

In this case, exit() cleans up before calling _sys_exit() and so disrupts other threads.

rand(), srand()

These functions keep internal state that is both global and unprotected. This means that calls to rand() are never thread‑safe

ARM recommends that you use your own locking to ensure that only one thread ever calls rand() at a time, for example, by defining $Sub$$rand() if you want to avoid changing your code.

Alternatively, do one of the following:

  • supply your own random number generator that can have multiple independent instances

  • simply arrange that only one thread ever needs to generate random numbers.

Copyright © 2007 ARM Limited. All rights reserved.ARM DUI 0378A