Services and Modeling for Embedded Software Development
Embecosm divider strip
Prev  Next

3.2.  The C Namespace and Reentrant Functions

The BSP implements the system calls—functions like close, write etc. It is possible for the BSP to implement these directly, but these will then be defined in the main C namespace. It is perfectly permissible for the user to replace these functions, and the user versions take precedence, which requires some care at link time.

Newlib allows the implementer instead to provide namespace clean versions of these functions by prefixing them with an underscore. Newlib will ensure that the system calls map to these namespace clean version (i.e. a call to close becomes a call to _close) unless the user has reimplemented that function themselves.

A reentrant function may be safely called from a second thread, while a first thread of control is executing. In general a function that modifies no static or global state, will be reentrant.

Many system calls are trivially reentrant. However for some calls, reentrancy is not easy to provide automatically, so reentrant versions are provided. Thus for close, there is the reentrant version close_r. The reentrant versions take an extra argument, a reentrancy structure, which can be used to ensure correct behavior, by providing per-thread versions of global data structures.

It is worth noting that use of the global error value, errno is a common source of non-reentrancy. The standard reentrancy structure includes an entry for a per-thread value of errno.

For many systems, the issue of reentrancy does not arise. If there is only ever one thread of control, or if separate threads have their own address space there is no problem.

However it's worth remembering that even a bare metal system may encounter issues with reentrancy if event handlers are allowed to use the system calls.

Newlib gives considerable flexibility, particularly where namespace clean versions of the basic system calls are implemented. The implementer can choose to provide implementations of the reentrant versions of the functions. Alternatively newlib can provide reentrancy at the library level, but mapping the calls down the system calls, which are not themselves reentrant. This last can often prove a practical solution to the problem.

Embecosm divider strip