diff options
Diffstat (limited to 'system/include/libc/reent.h')
-rw-r--r-- | system/include/libc/reent.h | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/system/include/libc/reent.h b/system/include/libc/reent.h new file mode 100644 index 00000000..4617c0d9 --- /dev/null +++ b/system/include/libc/reent.h @@ -0,0 +1,183 @@ +/* This header file provides the reentrancy. */ + +/* The reentrant system calls here serve two purposes: + + 1) Provide reentrant versions of the system calls the ANSI C library + requires. + 2) Provide these system calls in a namespace clean way. + + It is intended that *all* system calls that the ANSI C library needs + be declared here. It documents them all in one place. All library access + to the system is via some form of these functions. + + The target may provide the needed syscalls by any of the following: + + 1) Define the reentrant versions of the syscalls directly. + (eg: _open_r, _close_r, etc.). Please keep the namespace clean. + When you do this, set "syscall_dir" to "syscalls" and add + -DREENTRANT_SYSCALLS_PROVIDED to newlib_cflags in configure.host. + + 2) Define namespace clean versions of the system calls by prefixing + them with '_' (eg: _open, _close, etc.). Technically, there won't be + true reentrancy at the syscall level, but the library will be namespace + clean. + When you do this, set "syscall_dir" to "syscalls" in configure.host. + + 3) Define or otherwise provide the regular versions of the syscalls + (eg: open, close, etc.). The library won't be reentrant nor namespace + clean, but at least it will work. + When you do this, add -DMISSING_SYSCALL_NAMES to newlib_cflags in + configure.host. + + 4) Define or otherwise provide the regular versions of the syscalls, + and do not supply functional interfaces for any of the reentrant + calls. With this method, the reentrant syscalls are redefined to + directly call the regular system call without the reentrancy argument. + When you do this, specify both -DREENTRANT_SYSCALLS_PROVIDED and + -DMISSING_SYSCALL_NAMES via newlib_cflags in configure.host and do + not specify "syscall_dir". + + Stubs of the reentrant versions of the syscalls exist in the libc/reent + source directory and are provided if REENTRANT_SYSCALLS_PROVIDED isn't + defined. These stubs call the native system calls: _open, _close, etc. + if MISSING_SYSCALL_NAMES is *not* defined, otherwise they call the + non-underscored versions: open, close, etc. when MISSING_SYSCALL_NAMES + *is* defined. + + By default, newlib functions call the reentrant syscalls internally, + passing a reentrancy structure as an argument. This reentrancy structure + contains data that is thread-specific. For example, the errno value is + kept in the reentrancy structure. If multiple threads exist, each will + keep a separate errno value which is intuitive since the application flow + cannot check for failure reliably otherwise. + + The reentrant syscalls are either provided by the platform, by the + libc/reent stubs, or in the case of both MISSING_SYSCALL_NAMES and + REENTRANT_SYSCALLS_PROVIDED being defined, the calls are redefined to + simply call the regular syscalls with no reentrancy struct argument. + + A single-threaded application does not need to worry about the reentrancy + structure. It is used internally. + + A multi-threaded application needs either to manually manage reentrancy + structures or use dynamic reentrancy. + + Manually managing reentrancy structures entails calling special reentrant + versions of newlib functions that have an additional reentrancy argument. + For example, _printf_r. By convention, the first argument is the + reentrancy structure. By default, the normal version of the function + uses the default reentrancy structure: _REENT. The reentrancy structure + is passed internally, eventually to the reentrant syscalls themselves. + How the structures are stored and accessed in this model is up to the + application. + + Dynamic reentrancy is specified by the __DYNAMIC_REENT__ flag. This + flag denotes setting up a macro to replace _REENT with a function call + to __getreent(). This function needs to be implemented by the platform + and it is meant to return the reentrancy structure for the current + thread. When the regular C functions (e.g. printf) go to call internal + routines with the default _REENT structure, they end up calling with + the reentrancy structure for the thread. Thus, application code does not + need to call the _r routines nor worry about reentrancy structures. */ + +/* WARNING: All identifiers here must begin with an underscore. This file is + included by stdio.h and others and we therefore must only use identifiers + in the namespace allotted to us. */ + +#ifndef _REENT_H_ +#ifdef __cplusplus +extern "C" { +#endif +#define _REENT_H_ + +#include <sys/reent.h> +#include <sys/_types.h> +#include <machine/types.h> + +#define __need_size_t +#define __need_ptrdiff_t +#include <stddef.h> + +/* FIXME: not namespace clean */ +struct stat; +struct tms; +struct timeval; +struct timezone; + +#if defined(REENTRANT_SYSCALLS_PROVIDED) && defined(MISSING_SYSCALL_NAMES) + +#define _close_r(__reent, __fd) close(__fd) +#define _execve_r(__reent, __f, __arg, __env) execve(__f, __arg, __env) +#define _fcntl_r(__reent, __fd, __cmd, __arg) fcntl(__fd, __cmd, __arg) +#define _fork_r(__reent) fork() +#define _fstat_r(__reent, __fdes, __stat) fstat(__fdes, __stat) +#define _getpid_r(__reent) getpid() +#define _isatty_r(__reent, __desc) isatty(__desc) +#define _kill_r(__reent, __pid, __signal) kill(__pid, __signal) +#define _link_r(__reent, __oldpath, __newpath) link(__oldpath, __newpath) +#define _lseek_r(__reent, __fdes, __off, __w) lseek(__fdes, __off, __w) +#define _mkdir_r(__reent, __path, __m) mkdir(__path, __m) +#define _open_r(__reent, __path, __flag, __m) open(__path, __flag, __m) +#define _read_r(__reent, __fd, __buff, __cnt) read(__fd, __buff, __cnt) +#define _rename_r(__reent, __old, __new) rename(__old, __new) +#define _sbrk_r(__reent, __incr) sbrk(__incr) +#define _stat_r(__reent, __path, __buff) stat(__path, __buff) +#define _times_r(__reent, __time) times(__time) +#define _unlink_r(__reent, __path) unlink(__path) +#define _wait_r(__reent, __status) wait(__status) +#define _write_r(__reent, __fd, __buff, __cnt) write(__fd, __buff, __cnt) +#define _gettimeofday_r(__reent, __tp, __tzp) gettimeofday(__tp, __tzp) + +#ifdef __LARGE64_FILES +#define _lseek64_r(__reent, __fd, __off, __w) lseek64(__fd, __off, __w) +#define _fstat64_r(__reent, __fd, __buff) fstat64(__fd, __buff) +#define _open64_r(__reent, __path, __flag, __m) open64(__path, __flag, __m) +#endif + +#else +/* Reentrant versions of system calls. */ + +extern int _close_r _PARAMS ((struct _reent *, int)); +extern int _execve_r _PARAMS ((struct _reent *, const char *, char *const *, char *const *)); +extern int _fcntl_r _PARAMS ((struct _reent *, int, int, int)); +extern int _fork_r _PARAMS ((struct _reent *)); +extern int _fstat_r _PARAMS ((struct _reent *, int, struct stat *)); +extern int _getpid_r _PARAMS ((struct _reent *)); +extern int _isatty_r _PARAMS ((struct _reent *, int)); +extern int _kill_r _PARAMS ((struct _reent *, int, int)); +extern int _link_r _PARAMS ((struct _reent *, const char *, const char *)); +extern _off_t _lseek_r _PARAMS ((struct _reent *, int, _off_t, int)); +extern int _mkdir_r _PARAMS ((struct _reent *, const char *, int)); +extern int _open_r _PARAMS ((struct _reent *, const char *, int, int)); +extern _ssize_t _read_r _PARAMS ((struct _reent *, int, void *, size_t)); +extern int _rename_r _PARAMS ((struct _reent *, const char *, const char *)); +extern void *_sbrk_r _PARAMS ((struct _reent *, ptrdiff_t)); +extern int _stat_r _PARAMS ((struct _reent *, const char *, struct stat *)); +extern _CLOCK_T_ _times_r _PARAMS ((struct _reent *, struct tms *)); +extern int _unlink_r _PARAMS ((struct _reent *, const char *)); +extern int _wait_r _PARAMS ((struct _reent *, int *)); +extern _ssize_t _write_r _PARAMS ((struct _reent *, int, const void *, size_t)); + +/* This one is not guaranteed to be available on all targets. */ +extern int _gettimeofday_r _PARAMS ((struct _reent *, struct timeval *__tp, void *__tzp)); + +#ifdef __LARGE64_FILES + +#if defined(__CYGWIN__) && defined(_COMPILING_NEWLIB) +#define stat64 __stat64 +#endif + +struct stat64; + +extern _off64_t _lseek64_r _PARAMS ((struct _reent *, int, _off64_t, int)); +extern int _fstat64_r _PARAMS ((struct _reent *, int, struct stat64 *)); +extern int _open64_r _PARAMS ((struct _reent *, const char *, int, int)); +extern int _stat64_r _PARAMS ((struct _reent *, const char *, struct stat64 *)); +#endif + +#endif + +#ifdef __cplusplus +} +#endif +#endif /* _REENT_H_ */ |