diff options
Diffstat (limited to 'src/linux')
| -rw-r--r-- | src/linux/cache.c | 3 | ||||
| -rw-r--r-- | src/linux/clone.c | 56 | ||||
| -rw-r--r-- | src/linux/epoll.c | 1 | ||||
| -rw-r--r-- | src/linux/fallocate.c | 3 | ||||
| -rw-r--r-- | src/linux/getdents.c | 2 | ||||
| -rw-r--r-- | src/linux/membarrier.c | 2 | ||||
| -rw-r--r-- | src/linux/ppoll.c | 26 | ||||
| -rw-r--r-- | src/linux/preadv2.c | 17 | ||||
| -rw-r--r-- | src/linux/prlimit.c | 3 | ||||
| -rw-r--r-- | src/linux/pwritev2.c | 17 | ||||
| -rw-r--r-- | src/linux/renameat2.c | 11 | ||||
| -rw-r--r-- | src/linux/sendfile.c | 2 | ||||
| -rw-r--r-- | src/linux/statx.c | 44 | ||||
| -rw-r--r-- | src/linux/wait4.c | 4 | 
14 files changed, 145 insertions, 46 deletions
diff --git a/src/linux/cache.c b/src/linux/cache.c index 0eb051c2..e76f7812 100644 --- a/src/linux/cache.c +++ b/src/linux/cache.c @@ -21,7 +21,7 @@ weak_alias(__cachectl, cachectl);  #ifdef SYS_riscv_flush_icache  #define VDSO_FLUSH_ICACHE_SYM "__vdso_flush_icache" -#define VDSO_FLUSH_ICACHE_VER "LINUX_4.5" +#define VDSO_FLUSH_ICACHE_VER "LINUX_4.15"  static void *volatile vdso_func; @@ -45,6 +45,7 @@ int __riscv_flush_icache(void *start, void *end, unsigned long int flags)  		if (!r) return r;  		if (r != -ENOSYS) return __syscall_ret(r);  	} +	return syscall(SYS_riscv_flush_icache, start, end, flags);  }  weak_alias(__riscv_flush_icache, riscv_flush_icache);  #endif diff --git a/src/linux/clone.c b/src/linux/clone.c index 8c1af7d3..257c1cec 100644 --- a/src/linux/clone.c +++ b/src/linux/clone.c @@ -4,18 +4,62 @@  #include <sched.h>  #include "pthread_impl.h"  #include "syscall.h" +#include "lock.h" +#include "fork_impl.h" + +struct clone_start_args { +	int (*func)(void *); +	void *arg; +	sigset_t sigmask; +}; + +static int clone_start(void *arg) +{ +	struct clone_start_args *csa = arg; +	__post_Fork(0); +	__restore_sigs(&csa->sigmask); +	return csa->func(csa->arg); +}  int clone(int (*func)(void *), void *stack, int flags, void *arg, ...)  { +	struct clone_start_args csa;  	va_list ap; -	pid_t *ptid, *ctid; -	void  *tls; +	pid_t *ptid = 0, *ctid = 0; +	void  *tls = 0; + +	/* Flags that produce an invalid thread/TLS state are disallowed. */ +	int badflags = CLONE_THREAD | CLONE_SETTLS | CLONE_CHILD_CLEARTID; + +	if ((flags & badflags) || !stack) +		return __syscall_ret(-EINVAL);  	va_start(ap, arg); -	ptid = va_arg(ap, pid_t *); -	tls  = va_arg(ap, void *); -	ctid = va_arg(ap, pid_t *); +	if (flags & (CLONE_PIDFD | CLONE_PARENT_SETTID | CLONE_CHILD_SETTID)) +	 	ptid = va_arg(ap, pid_t *); +	if (flags & CLONE_CHILD_SETTID) { +		tls = va_arg(ap, void *); +		ctid = va_arg(ap, pid_t *); +	}  	va_end(ap); -	return __syscall_ret(__clone(func, stack, flags, arg, ptid, tls, ctid)); +	/* If CLONE_VM is used, it's impossible to give the child a consistent +	 * thread structure. In this case, the best we can do is assume the +	 * caller is content with an extremely restrictive execution context +	 * like the one vfork() would provide. */ +	if (flags & CLONE_VM) return __syscall_ret( +		__clone(func, stack, flags, arg, ptid, tls, ctid)); + +	__block_all_sigs(&csa.sigmask); +	LOCK(__abort_lock); + +	/* Setup the a wrapper start function for the child process to do +	 * mimic _Fork in producing a consistent execution state. */ +	csa.func = func; +	csa.arg = arg; +	int ret = __clone(clone_start, stack, flags, &csa, ptid, tls, ctid); + +	__post_Fork(ret); +	__restore_sigs(&csa.sigmask); +	return __syscall_ret(ret);  } diff --git a/src/linux/epoll.c b/src/linux/epoll.c index 93baa814..e56e8f4c 100644 --- a/src/linux/epoll.c +++ b/src/linux/epoll.c @@ -5,6 +5,7 @@  int epoll_create(int size)  { +	if (size<=0) return __syscall_ret(-EINVAL);  	return epoll_create1(0);  } diff --git a/src/linux/fallocate.c b/src/linux/fallocate.c index 7d68bc8f..9146350e 100644 --- a/src/linux/fallocate.c +++ b/src/linux/fallocate.c @@ -7,6 +7,3 @@ int fallocate(int fd, int mode, off_t base, off_t len)  	return syscall(SYS_fallocate, fd, mode, __SYSCALL_LL_E(base),  		__SYSCALL_LL_E(len));  } - -#undef fallocate64 -weak_alias(fallocate, fallocate64); diff --git a/src/linux/getdents.c b/src/linux/getdents.c index 796c1e5c..97f76e14 100644 --- a/src/linux/getdents.c +++ b/src/linux/getdents.c @@ -8,5 +8,3 @@ int getdents(int fd, struct dirent *buf, size_t len)  	if (len>INT_MAX) len = INT_MAX;  	return syscall(SYS_getdents, fd, buf, len);  } - -weak_alias(getdents, getdents64); diff --git a/src/linux/membarrier.c b/src/linux/membarrier.c index 343f7360..f64fe7e1 100644 --- a/src/linux/membarrier.c +++ b/src/linux/membarrier.c @@ -35,7 +35,7 @@ int __membarrier(int cmd, int flags)  		__tl_lock();  		sem_init(&barrier_sem, 0, 0);  		struct sigaction sa = { -			.sa_flags = SA_RESTART, +			.sa_flags = SA_RESTART | SA_ONSTACK,  			.sa_handler = bcast_barrier  		};  		memset(&sa.sa_mask, -1, sizeof sa.sa_mask); diff --git a/src/linux/ppoll.c b/src/linux/ppoll.c deleted file mode 100644 index e614600a..00000000 --- a/src/linux/ppoll.c +++ /dev/null @@ -1,26 +0,0 @@ -#define _GNU_SOURCE -#include <poll.h> -#include <signal.h> -#include <errno.h> -#include "syscall.h" - -#define IS32BIT(x) !((x)+0x80000000ULL>>32) -#define CLAMP(x) (int)(IS32BIT(x) ? (x) : 0x7fffffffU+((0ULL+(x))>>63)) - -int ppoll(struct pollfd *fds, nfds_t n, const struct timespec *to, const sigset_t *mask) -{ -	time_t s = to ? to->tv_sec : 0; -	long ns = to ? to->tv_nsec : 0; -#ifdef SYS_ppoll_time64 -	int r = -ENOSYS; -	if (SYS_ppoll == SYS_ppoll_time64 || !IS32BIT(s)) -		r = __syscall_cp(SYS_ppoll_time64, fds, n, -			to ? ((long long[]){s, ns}) : 0, -			mask, _NSIG/8); -	if (SYS_ppoll == SYS_ppoll_time64 || r != -ENOSYS) -		return __syscall_ret(r); -	s = CLAMP(s); -#endif -	return syscall_cp(SYS_ppoll, fds, n, -		to ? ((long[]){s, ns}) : 0, mask, _NSIG/8); -} diff --git a/src/linux/preadv2.c b/src/linux/preadv2.c new file mode 100644 index 00000000..5e7ab70f --- /dev/null +++ b/src/linux/preadv2.c @@ -0,0 +1,17 @@ +#define _GNU_SOURCE +#include <sys/uio.h> +#include <unistd.h> +#include "syscall.h" + +ssize_t preadv2(int fd, const struct iovec *iov, int count, off_t ofs, int flags) +{ +#ifdef SYS_preadv +	if (!flags) { +		if (ofs==-1) return readv(fd, iov, count); +		return syscall_cp(SYS_preadv, fd, iov, count, +			(long)(ofs), (long)(ofs>>32)); +	} +#endif +	return syscall_cp(SYS_preadv2, fd, iov, count, +		(long)(ofs), (long)(ofs>>32), flags); +} diff --git a/src/linux/prlimit.c b/src/linux/prlimit.c index 3df9ffba..fcf45aab 100644 --- a/src/linux/prlimit.c +++ b/src/linux/prlimit.c @@ -21,6 +21,3 @@ int prlimit(pid_t pid, int resource, const struct rlimit *new_limit, struct rlim  	}  	return r;  } - -#undef prlimit64 -weak_alias(prlimit, prlimit64); diff --git a/src/linux/pwritev2.c b/src/linux/pwritev2.c new file mode 100644 index 00000000..ece90d7c --- /dev/null +++ b/src/linux/pwritev2.c @@ -0,0 +1,17 @@ +#define _GNU_SOURCE +#include <sys/uio.h> +#include <unistd.h> +#include "syscall.h" + +ssize_t pwritev2(int fd, const struct iovec *iov, int count, off_t ofs, int flags) +{ +#ifdef SYS_pwritev +	if (!flags) { +		if (ofs==-1) return writev(fd, iov, count); +		return syscall_cp(SYS_pwritev, fd, iov, count, +			(long)(ofs), (long)(ofs>>32)); +	} +#endif +	return syscall_cp(SYS_pwritev2, fd, iov, count, +		(long)(ofs), (long)(ofs>>32), flags); +} diff --git a/src/linux/renameat2.c b/src/linux/renameat2.c new file mode 100644 index 00000000..b8060388 --- /dev/null +++ b/src/linux/renameat2.c @@ -0,0 +1,11 @@ +#define _GNU_SOURCE +#include <stdio.h> +#include "syscall.h" + +int renameat2(int oldfd, const char *old, int newfd, const char *new, unsigned flags) +{ +#ifdef SYS_renameat +	if (!flags) return syscall(SYS_renameat, oldfd, old, newfd, new); +#endif +	return syscall(SYS_renameat2, oldfd, old, newfd, new, flags); +} diff --git a/src/linux/sendfile.c b/src/linux/sendfile.c index 9afe6dd6..fc1577d3 100644 --- a/src/linux/sendfile.c +++ b/src/linux/sendfile.c @@ -5,5 +5,3 @@ ssize_t sendfile(int out_fd, int in_fd, off_t *ofs, size_t count)  {  	return syscall(SYS_sendfile, out_fd, in_fd, ofs, count);  } - -weak_alias(sendfile, sendfile64); diff --git a/src/linux/statx.c b/src/linux/statx.c new file mode 100644 index 00000000..4fb96e4b --- /dev/null +++ b/src/linux/statx.c @@ -0,0 +1,44 @@ +#define _GNU_SOURCE +#include <sys/stat.h> +#include <string.h> +#include <syscall.h> +#include <sys/sysmacros.h> +#include <errno.h> + +int statx(int dirfd, const char *restrict path, int flags, unsigned mask, struct statx *restrict stx) +{ +	int ret = __syscall(SYS_statx, dirfd, path, flags, mask, stx); + +#ifndef SYS_fstatat +	return __syscall_ret(ret); +#endif + +	if (ret != -ENOSYS) return __syscall_ret(ret); + +	struct stat st; +	ret = fstatat(dirfd, path, &st, flags); +	if (ret) return ret; + +	*stx = (struct statx){0}; +	stx->stx_dev_major = major(st.st_dev); +	stx->stx_dev_minor = minor(st.st_dev); +	stx->stx_rdev_major = major(st.st_rdev); +	stx->stx_rdev_minor = minor(st.st_rdev); +	stx->stx_ino = st.st_ino; +	stx->stx_mode = st.st_mode; +	stx->stx_nlink = st.st_nlink; +	stx->stx_uid = st.st_uid; +	stx->stx_gid = st.st_gid; +	stx->stx_size = st.st_size; +	stx->stx_blksize = st.st_blksize; +	stx->stx_blocks = st.st_blocks; +	stx->stx_atime.tv_sec = st.st_atim.tv_sec; +	stx->stx_atime.tv_nsec = st.st_atim.tv_nsec; +	stx->stx_mtime.tv_sec = st.st_mtim.tv_sec; +	stx->stx_mtime.tv_nsec = st.st_mtim.tv_nsec; +	stx->stx_ctime.tv_sec = st.st_ctim.tv_sec; +	stx->stx_ctime.tv_nsec = st.st_ctim.tv_nsec; +	stx->stx_mask = STATX_BASIC_STATS; + +	return 0; +} diff --git a/src/linux/wait4.c b/src/linux/wait4.c index 83650e34..fb08c0d0 100644 --- a/src/linux/wait4.c +++ b/src/linux/wait4.c @@ -12,7 +12,7 @@ pid_t wait4(pid_t pid, int *status, int options, struct rusage *ru)  	if (ru) {  		long long kru64[18];  		r = __syscall(SYS_wait4_time64, pid, status, options, kru64); -		if (!r) { +		if (r > 0) {  			ru->ru_utime = (struct timeval)  				{ .tv_sec = kru64[0], .tv_usec = kru64[1] };  			ru->ru_stime = (struct timeval) @@ -26,7 +26,7 @@ pid_t wait4(pid_t pid, int *status, int options, struct rusage *ru)  	}  #endif  	char *dest = ru ? (char *)&ru->ru_maxrss - 4*sizeof(long) : 0; -	r = __syscall(SYS_wait4, pid, status, options, dest); +	r = __sys_wait4(pid, status, options, dest);  	if (r>0 && ru && sizeof(time_t) > sizeof(long)) {  		long kru[4];  		memcpy(kru, dest, 4*sizeof(long));  | 
