/* -*- c -*-
 *
 * This is a list of system calls we invoke "directly".  These
 * are generated into syscall stubs in their own files, so the
 * linker can do its job properly.
 *
 * The full description of a line is:
 * [<[?][!]arch,...>] type [sysname,...][@systype][::funcname](args);
 *
 * ? means only instantiate this system call if present in asm/unistd.h
 */

#include <asm/unistd.h>
#include <klibc/sysconfig.h>
#include <bitsize.h>

/*
 * Process-related syscalls
 */
void _exit,exit::_exit(int);
<?!ia64> pid_t clone::__clone(unsigned long, void *);
<?ia64> pid_t clone::__clone2(unsigned long, void *, void *);
# if ! _KLIBC_NO_MMU
<!sparc,sparc64,ia64,arm64> pid_t fork();
<sparc,sparc64> pid_t fork@forkish();
#endif
#if _KLIBC_REAL_VFORK
/*
 * A lot of architectures need architecture-specific vfork
 * stubs, due to the no-stack requirement.  These are the
 * architectures which do not.
 */
<alpha,m32r,ppc,ppc64,sh,s390,s390x> pid_t vfork();
<sparc,sparc64> pid_t vfork@forkish();
#endif
<!alpha> pid_t getpid();
<alpha> pid_t getxpid@dual0::getpid();
int setpgid(pid_t, pid_t);
pid_t getpgid(pid_t);
<!alpha> pid_t getppid();
<alpha> pid_t getxpid@dual1::getppid();
pid_t setsid();
pid_t getsid(pid_t);
pid_t wait4(pid_t, int *, int, struct rusage *);
int execve(const char *, char * const *, char * const *);
<?> int nice(int);
<alpha,ia64> int getpriority(int, int);
<!alpha,ia64> int getpriority::__getpriority(int, int);
int setpriority(int, int, int);
int getrusage(int, struct rusage *);
int sched_setscheduler(pid_t, int, const struct sched_param *);
<?> int sched_setaffinity(pid_t, unsigned int, unsigned long *);
<?> int sched_getaffinity(pid_t, unsigned int, unsigned long *);
int sched_yield();
<i386> int prctl@varadic(int, unsigned long, unsigned long, unsigned long, unsigned long);
<!i386> int prctl(int, unsigned long, unsigned long, unsigned long, unsigned long);

/*
 * User and group IDs
 */
int setuid32,setuid::setuid(uid_t);
int setgid32,setgid::setgid(gid_t);
<!alpha> uid_t getuid32,getuid::getuid();
<alpha>  uid_t getxuid@dual0::getuid();
<!alpha> gid_t getgid32,getgid::getgid();
<alpha> gid_t getxgid@dual0::getgid();
<!alpha> uid_t geteuid32,geteuid::geteuid();
<alpha> uid_t getxuid@dual1::geteuid();
<!alpha> gid_t getegid32,getegid::getegid();
<alpha> gid_t getxgid@dual1::getegid();
int getgroups32,getgroups::getgroups(int, gid_t *);
int setgroups32,setgroups::setgroups(size_t, const gid_t *);
int setreuid32,setreuid::setreuid(uid_t, uid_t);
int setregid32,setregid::setregid(gid_t, gid_t);
int setfsuid32,setfsuid::setfsuid(uid_t);
int setfsgid32,setfsgid::setfsgid(gid_t);
int setresuid32,setresuid::setresuid(int, uid_t, uid_t, uid_t);

/*
 * POSIX Capabilities
 */
int capget(cap_user_header_t, cap_user_data_t);
int capset(cap_user_header_t, cap_user_data_t);

/*
 * Filesystem-related system calls
 */
int mount(const char *, const char *, const char *, unsigned long, const void *);
<!alpha,ia64> int umount2(const char *, int);
<alpha,ia64> int umount::umount2(const char *, int);
<?> int pivot_root(const char *, const char *);
int sync();
#ifdef __NR_statfs64
int statfs64::__statfs64(const char *, size_t, struct statfs *);
#else
int statfs(const char *, struct statfs *);
#endif
#ifdef __NR_fstatfs64
int fstatfs64::__fstatfs64(int, size_t, struct statfs *);
#else
int fstatfs(int, struct statfs *);
#endif
int swapon(const char *, int);
int swapoff(const char *);

/*
 * Inode-related system calls
 */
<?> int access(const char *, int);
int faccessat(int, const char *, int, int);
<?> int link(const char *, const char *);
<?> int linkat(int, const char *, int, const char *, int);
<?> int unlink(const char *);
<?> int unlinkat(int, const char *, int);
int chdir(const char *);
int fchdir(int);
<?> int rename(const char *, const char *);
<?> int renameat(int, const char *, int, const char *);
<?> int mknod(const char *, mode_t, dev_t);
<?> int mknodat(int, const char *, mode_t, dev_t);
<?> int chmod(const char *, mode_t);
int fchmod(int, mode_t);
<?> int fchmodat(int, const char *, mode_t, int);
<?> int mkdir(const char *, mode_t);
<?> int mkdirat(int, const char *, mode_t);
<?> int rmdir(const char *);
<?!alpha,ia64,mips,mips64,sh,sparc,sparc64> int pipe(int *);
int pipe2(int *, int);
mode_t umask(mode_t);
int chroot(const char *);
<?> int symlink(const char *, const char *);
<?> int symlinkat(const char *, int, const char *);
<?> int readlink(const char *, char *, size_t);
<?> int readlinkat(int, const char *, char *, int);
<?!ppc64> int stat64,stat::stat(const char *, struct stat *);
<?!ppc64> int lstat64,lstat::lstat(const char *, struct stat *);
<!ppc64> int fstat64,fstat::fstat(int, struct stat *);
<ppc64> int stat::stat(const char *, struct stat *);
<ppc64> int lstat::lstat(const char *, struct stat *);
<ppc64> int fstat::fstat(int, struct stat *);
/* XXX: Is this right?! */
<?> int fstatat64,newfstatat,fstatat::fstatat(int, const char *, struct stat *, int);
int getdents64,getdents::getdents(unsigned int, struct dirent *, unsigned int);
<?> int chown32,chown::chown(const char *, uid_t, gid_t);
int fchown32,fchown::fchown(int, uid_t, gid_t);
<?> int fchownat(int, const char *, uid_t, gid_t, int);
<?> int lchown32,lchown::lchown(const char *, uid_t, gid_t);
int getcwd::__getcwd(char *, size_t);
<?> int utime(const char *, const struct utimbuf *);
<?> int utimes(const char *, const struct timeval *);
<?> int futimesat(int, const char *, const struct timeval *);
<?> int utimensat(int, const char *, const struct timespec *, int);
<?> int inotify_init();
<?> int inotify_add_watch(int, const char *, __u32);
<?> int inotify_rm_watch(int, __u32);

/*
 * I/O operations
 */
<!i386,m68k,64> int open::__open(const char *, int, mode_t);
<?!i386,m68k,64> int openat::__openat(int, const char *, int, mode_t);
<?64> int open(const char *, int, mode_t);
<64> int openat(int, const char *, int, mode_t);
ssize_t read(int, void *, size_t);
ssize_t write(int, const void *, size_t);
int close(int);
<64> off_t lseek(int, off_t, int);
<32> int _llseek::__llseek(int, unsigned long, unsigned long, off_t *, int);
int dup(int);
<?> int dup2(int, int);
int dup3(int, int, int);
<i386> int fcntl64@varadic::fcntl(int, int, unsigned long);
<ppc64> int fcntl(int, int, unsigned long);
<!i386,ppc64> int fcntl64,fcntl::fcntl(int, int, unsigned long);
int ioctl(int, int, void *);
int flock(int, int);
<?> int _newselect,select::select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
#if defined(__NR_pselect) && !_KLIBC_USE_RT_SIG
int pselect(int, fd_set *, fd_set *, fd_set *, const struct timespec *, const sigset_t *);
#elif defined(__NR_pselect7)
int pselect7::__pselect7(int, fd_set *, fd_set *, fd_set *, struct timespec *, const sigset_t *, size_t);
#elif defined(__NR_pselect6)
int pselect6::__pselect6(int, fd_set *, fd_set *, fd_set *, struct timespec *, const struct __pselect6 *);
#endif
<?> int poll(struct pollfd *, nfds_t, long);
<?> int ppoll::__ppoll(struct pollfd *, nfds_t, struct timespec *, const sigset_t *, size_t);
int fsync(int);
int fdatasync,fsync::fdatasync(int);
int readv(int, const struct iovec *, int);
int writev(int, const struct iovec *, int);
int ftruncate64,ftruncate::ftruncate(int, off_t);
ssize_t pread64,pread::pread(int, void *, size_t, off_t);
ssize_t pwrite64,pwrite::pwrite(int, void *, size_t, off_t);
int sync_file_range,fdatasync,fsync::sync_file_range(int, off_t, off_t, unsigned int);
<?> int splice(int, off_t *, int, off_t *, size_t, unsigned int);
<?> int tee(int, int, size_t, unsigned int);
ssize_t sendfile64,sendfile::sendfile(int, int, off_t *, size_t, off_t);

/*
 * Signal operations
 *
 * We really should get rid of the non-rt_* of these, but that takes
 * sanitizing <signal.h> for all architectures, sigh.  See <klibc/config.h>.
 */
#if _KLIBC_USE_RT_SIG
<!sparc,sparc64,alpha> int rt_sigaction::__rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t);
<sparc,sparc64> int rt_sigaction::__rt_sigaction(int, const struct sigaction *, struct sigaction *, void *, size_t);
<alpha> int rt_sigaction::__rt_sigaction(int, const struct sigaction *, struct sigaction *, size_t, void *);
int rt_sigsuspend::__rt_sigsuspend(const sigset_t *, size_t);
int rt_sigpending::__rt_sigpending(sigset_t *, size_t);
int rt_sigprocmask::__rt_sigprocmask(int, const sigset_t *, sigset_t *, size_t);
<sparc64> void rt_sigreturn::__sigreturn();
#else
int sigaction::__sigaction(int, const struct sigaction *, struct sigaction *);
int sigpending(sigset_t *);
int sigprocmask(int, const sigset_t *, sigset_t *);
/*
 * There is no single calling convention for the old sigsuspend.
 * If your architecture is not listed here, building klibc shall
 * rather fail than use a broken calling convention.
 * You better switch to RT signals on those architectures:
 * blackfin h8300 microblaze mips.
 *
 * The arguments other than the sigset_t are assumed ignored.
 */
<cris,sh,sparc,alpha,ppc,sparc64> int sigsuspend::__sigsuspend_s(sigset_t);
<arm,frv,i386,m68k,mn10300,s390,s390x> int sigsuspend::__sigsuspend_xxs(int, int, sigset_t);
#endif
int kill(pid_t, int);
<?> unsigned int alarm(unsigned int);
int getitimer(int, struct itimerval *);
int setitimer(int, const struct itimerval *, struct itimerval *);

/*
 * Time-related system calls
 */
<?> time_t time(time_t *);
clock_t times(struct tms *);
int gettimeofday(struct timeval *, struct timezone *);
int settimeofday(const struct timeval *, const struct timezone *);
int nanosleep(const struct timespec *, struct timespec *);
<?> int pause();

/*
 * Memory
 */
<?> void * brk::__brk(void *);
int munmap(void *, size_t);
void * mremap(void *, size_t, size_t, unsigned long);
int msync(const void *, size_t, int);
int mprotect(const void *, size_t, int);
# if _KLIBC_USE_MMAP2
<!s390> void * mmap2::__mmap2(void *, size_t, int, int, int, long);
# else
<!s390x> void * mmap(void *, size_t, int, int, int, long);
int mlockall(int);
int munlockall();
int mlock(const void *, size_t);
int munlock(const void *, size_t);
#endif

/*
 * System stuff
 */
int uname(struct utsname *);
int setdomainname(const char *, size_t);
int sethostname(const char *, size_t);
long init_module(void *, unsigned long, const char *);
long delete_module(const char *, unsigned int);
int reboot::__reboot(int, int, int, void *);
int syslog::klogctl(int, char *, int);
int sysinfo(struct sysinfo *);
long kexec_load(void *, unsigned long, struct kexec_segment *, unsigned long);

/*
 * Low-level I/O (generally architecture-specific);
 */
<i386,x86_64> int iopl(int);
<i386,x86_64> int ioperm(unsigned long, unsigned long, int);
<i386> int vm86(struct vm86_struct *);

/*
 * Most architectures have the socket interfaces using regular
 * system calls.
 */
<?!i386> long socketcall::__socketcall(int, const unsigned long *);
#if ! _KLIBC_SYS_SOCKETCALL
#include "SOCKETCALLS.def"
#endif
