diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/linux/wait4.c | 34 | ||||
| -rw-r--r-- | src/misc/getrusage.c | 30 | 
2 files changed, 61 insertions, 3 deletions
| diff --git a/src/linux/wait4.c b/src/linux/wait4.c index 97f12cc5..83650e34 100644 --- a/src/linux/wait4.c +++ b/src/linux/wait4.c @@ -1,9 +1,39 @@  #define _GNU_SOURCE  #include <sys/wait.h>  #include <sys/resource.h> +#include <string.h> +#include <errno.h>  #include "syscall.h" -pid_t wait4(pid_t pid, int *status, int options, struct rusage *usage) +pid_t wait4(pid_t pid, int *status, int options, struct rusage *ru)  { -	return syscall(SYS_wait4, pid, status, options, usage); +	int r; +#ifdef SYS_wait4_time64 +	if (ru) { +		long long kru64[18]; +		r = __syscall(SYS_wait4_time64, pid, status, options, kru64); +		if (!r) { +			ru->ru_utime = (struct timeval) +				{ .tv_sec = kru64[0], .tv_usec = kru64[1] }; +			ru->ru_stime = (struct timeval) +				{ .tv_sec = kru64[2], .tv_usec = kru64[3] }; +			char *slots = (char *)&ru->ru_maxrss; +			for (int i=0; i<14; i++) +				*(long *)(slots + i*sizeof(long)) = kru64[4+i]; +		} +		if (SYS_wait4_time64 == SYS_wait4 || r != -ENOSYS) +			return __syscall_ret(r); +	} +#endif +	char *dest = ru ? (char *)&ru->ru_maxrss - 4*sizeof(long) : 0; +	r = __syscall(SYS_wait4, pid, status, options, dest); +	if (r>0 && ru && sizeof(time_t) > sizeof(long)) { +		long kru[4]; +		memcpy(kru, dest, 4*sizeof(long)); +		ru->ru_utime = (struct timeval) +			{ .tv_sec = kru[0], .tv_usec = kru[1] }; +		ru->ru_stime = (struct timeval) +			{ .tv_sec = kru[2], .tv_usec = kru[3] }; +	} +	return __syscall_ret(r);  } diff --git a/src/misc/getrusage.c b/src/misc/getrusage.c index 0aaf0ac7..8e03e2e3 100644 --- a/src/misc/getrusage.c +++ b/src/misc/getrusage.c @@ -1,7 +1,35 @@  #include <sys/resource.h> +#include <string.h> +#include <errno.h>  #include "syscall.h"  int getrusage(int who, struct rusage *ru)  { -	return syscall(SYS_getrusage, who, ru); +	int r; +#ifdef SYS_getrusage_time64 +	long long kru64[18]; +	r = __syscall(SYS_getrusage_time64, who, kru64); +	if (!r) { +		ru->ru_utime = (struct timeval) +			{ .tv_sec = kru64[0], .tv_usec = kru64[1] }; +		ru->ru_stime = (struct timeval) +			{ .tv_sec = kru64[2], .tv_usec = kru64[3] }; +		char *slots = (char *)&ru->ru_maxrss; +		for (int i=0; i<14; i++) +			*(long *)(slots + i*sizeof(long)) = kru64[4+i]; +	} +	if (SYS_getrusage_time64 == SYS_getrusage || r != -ENOSYS) +		return __syscall_ret(r); +#endif +	char *dest = (char *)&ru->ru_maxrss - 4*sizeof(long); +	r = __syscall(SYS_getrusage, who, dest); +	if (!r && sizeof(time_t) > sizeof(long)) { +		long kru[4]; +		memcpy(kru, dest, 4*sizeof(long)); +		ru->ru_utime = (struct timeval) +			{ .tv_sec = kru[0], .tv_usec = kru[1] }; +		ru->ru_stime = (struct timeval) +			{ .tv_sec = kru[2], .tv_usec = kru[3] }; +	} +	return __syscall_ret(r);  } | 
