wait4, getrusage: add time64/x32 variant
[musl] / src / linux / wait4.c
index 97f12cc..83650e3 100644 (file)
@@ -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);
 }