Reentrancy is achieved by providing a global reentrancy structure,
struct _reent for each thread of control, which
holds thread specific versions of global data structures, such as
errno
.
For a fully reentrant system, the BSP should implement the
reentrant versions of the system calls, having defined
syscall_dir=syscalls
and added
-DREENTRANT_SYSCALLS_PROVIDED"
to
newlib_cflags
in
configure.host
(see Section 3.3.1).
16 of the system calls have reentrant versions, which take the
suffix _r
and are passed an additional first
argument, which is a pointer to the reentrancy structure,
struct reent for the thread of control. Thus
_close
is replaced by
_close_r
. The reentrant functions are
_close_r
, _execve_r
,
_fcntl_r
, _fork_r
,
_fstat_r
, _getpid_r
,
_link_r
, _lseek_r
,
_open_r
, _read_r
,
_sbrk_r
, _stat_r
,
_times_r
, _unlink_r
,
_wait_r
and _write_r
.
Two system calls do not need reentrant versions,
_kill
and _exit
, which are
provided as with non-reentrant versions.
For many of the reentrant functions, the behavior is almost
identical to that of the non-reentrant versions, beyond ensuring the
thread specific version of errno
in the
reentrancy structure is used. Template versions can be found in the
libc/reent
directory under the
newlib
directory.
There are two ways in which the end user can be supported with these reentrancy functions. In the first it is up to the user to manage per thread reentrancy data structures and to call the reentrant functions explicitly.
However the more powerful solution is for the system to manage the reentrancy structure itself. The end user can call the standard functions, and they will be mapped to reentrant calls, passing in a reentrancy structure for the thread.
For this approach to be used, -D__DYNAMIC_REENT__
must be added to newlib_cflags
and the BSP must
define the function __getreent
, to return the
reentrancy structure for the current thread.