Date: Sun, 24 May 2015 17:23:08 +0000 (UTC) From: Dmitry Chagin <dchagin@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r283459 - head/sys/compat/linux Message-ID: <201505241723.t4OHN8BB018745@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: dchagin Date: Sun May 24 17:23:08 2015 New Revision: 283459 URL: https://svnweb.freebsd.org/changeset/base/283459 Log: Add some clock mappings used in glibc 2.20. Differential Revision: https://reviews.freebsd.org/D1465 Reviewd by: trasz Modified: head/sys/compat/linux/linux_time.c head/sys/compat/linux/linux_timer.h Modified: head/sys/compat/linux/linux_time.c ============================================================================== --- head/sys/compat/linux/linux_time.c Sun May 24 17:16:55 2015 (r283458) +++ head/sys/compat/linux/linux_time.c Sun May 24 17:23:08 2015 (r283459) @@ -39,8 +39,11 @@ __KERNEL_RCSID(0, "$NetBSD: linux_time.c #include <sys/param.h> #include <sys/kernel.h> +#include <sys/lock.h> #include <sys/ucred.h> #include <sys/mount.h> +#include <sys/mutex.h> +#include <sys/resourcevar.h> #include <sys/sdt.h> #include <sys/signal.h> #include <sys/stdint.h> @@ -59,7 +62,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_time.c #endif #include <compat/linux/linux_dtrace.h> -#include <compat/linux/linux_misc.h> +#include <compat/linux/linux_timer.h> /* DTrace init */ LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); @@ -157,6 +160,20 @@ linux_to_native_clockid(clockid_t *n, cl LIN_SDT_PROBE2(time, linux_to_native_clockid, entry, n, l); + if (l < 0) { + /* cpu-clock */ + if ((l & LINUX_CLOCKFD_MASK) == LINUX_CLOCKFD) + return (EINVAL); + if (LINUX_CPUCLOCK_WHICH(l) >= LINUX_CPUCLOCK_MAX) + return (EINVAL); + + if (LINUX_CPUCLOCK_PERTHREAD(l)) + *n = CLOCK_THREAD_CPUTIME_ID; + else + *n = CLOCK_PROCESS_CPUTIME_ID; + return (0); + } + switch (l) { case LINUX_CLOCK_REALTIME: *n = CLOCK_REALTIME; @@ -164,21 +181,27 @@ linux_to_native_clockid(clockid_t *n, cl case LINUX_CLOCK_MONOTONIC: *n = CLOCK_MONOTONIC; break; - case LINUX_CLOCK_PROCESS_CPUTIME_ID: - case LINUX_CLOCK_THREAD_CPUTIME_ID: - case LINUX_CLOCK_REALTIME_HR: - case LINUX_CLOCK_MONOTONIC_HR: + case LINUX_CLOCK_REALTIME_COARSE: + *n = CLOCK_REALTIME_FAST; + break; + case LINUX_CLOCK_MONOTONIC_COARSE: + *n = CLOCK_MONOTONIC_FAST; + break; + case LINUX_CLOCK_MONOTONIC_RAW: + case LINUX_CLOCK_BOOTTIME: + case LINUX_CLOCK_REALTIME_ALARM: + case LINUX_CLOCK_BOOTTIME_ALARM: + case LINUX_CLOCK_SGI_CYCLE: + case LINUX_CLOCK_TAI: LIN_SDT_PROBE1(time, linux_to_native_clockid, unsupported_clockid, l); LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL); return (EINVAL); - break; default: LIN_SDT_PROBE1(time, linux_to_native_clockid, unknown_clockid, l); LIN_SDT_PROBE1(time, linux_to_native_clockid, return, EINVAL); return (EINVAL); - break; } LIN_SDT_PROBE1(time, linux_to_native_clockid, return, 0); @@ -189,9 +212,14 @@ int linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args) { struct l_timespec lts; - int error; - clockid_t nwhich = 0; /* XXX: GCC */ struct timespec tp; + struct rusage ru; + struct thread *targettd; + struct proc *p; + int error, clockwhich; + clockid_t nwhich = 0; /* XXX: GCC */ + pid_t pid; + lwpid_t tid; LIN_SDT_PROBE2(time, linux_clock_gettime, entry, args->which, args->tp); @@ -202,7 +230,100 @@ linux_clock_gettime(struct thread *td, s LIN_SDT_PROBE1(time, linux_clock_gettime, return, error); return (error); } - error = kern_clock_gettime(td, nwhich, &tp); + + switch (nwhich) { + case CLOCK_PROCESS_CPUTIME_ID: + clockwhich = LINUX_CPUCLOCK_WHICH(args->which); + pid = LINUX_CPUCLOCK_ID(args->which); + if (pid == 0) { + p = td->td_proc; + PROC_LOCK(p); + } else { + error = pget(pid, PGET_CANSEE, &p); + if (error != 0) + return (EINVAL); + } + switch (clockwhich) { + case LINUX_CPUCLOCK_PROF: + PROC_STATLOCK(p); + calcru(p, &ru.ru_utime, &ru.ru_stime); + PROC_STATUNLOCK(p); + PROC_UNLOCK(p); + timevaladd(&ru.ru_utime, &ru.ru_stime); + TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); + break; + case LINUX_CPUCLOCK_VIRT: + PROC_STATLOCK(p); + calcru(p, &ru.ru_utime, &ru.ru_stime); + PROC_STATUNLOCK(p); + PROC_UNLOCK(p); + TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); + break; + case LINUX_CPUCLOCK_SCHED: + PROC_UNLOCK(p); + error = kern_clock_getcpuclockid2(td, pid, + CPUCLOCK_WHICH_PID, &nwhich); + if (error != 0) + return (EINVAL); + error = kern_clock_gettime(td, nwhich, &tp); + break; + default: + PROC_UNLOCK(p); + return (EINVAL); + } + + break; + + case CLOCK_THREAD_CPUTIME_ID: + clockwhich = LINUX_CPUCLOCK_WHICH(args->which); + p = td->td_proc; + tid = LINUX_CPUCLOCK_ID(args->which); + if (tid == 0) { + targettd = td; + PROC_LOCK(p); + } else { + targettd = tdfind(tid, p->p_pid); + if (targettd == NULL) + return (EINVAL); + } + switch (clockwhich) { + case LINUX_CPUCLOCK_PROF: + PROC_STATLOCK(p); + thread_lock(targettd); + rufetchtd(targettd, &ru); + thread_unlock(targettd); + PROC_STATUNLOCK(p); + PROC_UNLOCK(p); + timevaladd(&ru.ru_utime, &ru.ru_stime); + TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); + break; + case LINUX_CPUCLOCK_VIRT: + PROC_STATLOCK(p); + thread_lock(targettd); + rufetchtd(targettd, &ru); + thread_unlock(targettd); + PROC_STATUNLOCK(p); + PROC_UNLOCK(p); + TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); + break; + case LINUX_CPUCLOCK_SCHED: + error = kern_clock_getcpuclockid2(td, tid, + CPUCLOCK_WHICH_TID, &nwhich); + PROC_UNLOCK(p); + if (error != 0) + return (EINVAL); + error = kern_clock_gettime(td, nwhich, &tp); + break; + default: + PROC_UNLOCK(p); + return (EINVAL); + } + break; + + default: + error = kern_clock_gettime(td, nwhich, &tp); + break; + } if (error != 0) { LIN_SDT_PROBE1(time, linux_clock_gettime, gettime_error, error); LIN_SDT_PROBE1(time, linux_clock_gettime, return, error); @@ -260,19 +381,16 @@ linux_clock_settime(struct thread *td, s int linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args) { + struct proc *p; struct timespec ts; struct l_timespec lts; - int error; + int error, clockwhich; clockid_t nwhich = 0; /* XXX: GCC */ + pid_t pid; + lwpid_t tid; LIN_SDT_PROBE2(time, linux_clock_getres, entry, args->which, args->tp); - if (args->tp == NULL) { - LIN_SDT_PROBE0(time, linux_clock_getres, nullcall); - LIN_SDT_PROBE1(time, linux_clock_getres, return, 0); - return (0); - } - error = linux_to_native_clockid(&nwhich, args->which); if (error != 0) { LIN_SDT_PROBE1(time, linux_clock_getres, conversion_error, @@ -280,6 +398,59 @@ linux_clock_getres(struct thread *td, st LIN_SDT_PROBE1(time, linux_clock_getres, return, error); return (error); } + + /* + * Check user supplied clock id in case of per-process + * or thread-specific cpu-time clock. + */ + switch (nwhich) { + case CLOCK_THREAD_CPUTIME_ID: + tid = LINUX_CPUCLOCK_ID(args->which); + if (tid != 0) { + p = td->td_proc; + if (tdfind(tid, p->p_pid) == NULL) + return (ESRCH); + PROC_UNLOCK(p); + } + break; + case CLOCK_PROCESS_CPUTIME_ID: + pid = LINUX_CPUCLOCK_ID(args->which); + if (pid != 0) { + error = pget(pid, PGET_CANSEE, &p); + if (error != 0) + return (EINVAL); + PROC_UNLOCK(p); + } + break; + } + + if (args->tp == NULL) { + LIN_SDT_PROBE0(time, linux_clock_getres, nullcall); + LIN_SDT_PROBE1(time, linux_clock_getres, return, 0); + return (0); + } + + switch (nwhich) { + case CLOCK_THREAD_CPUTIME_ID: + case CLOCK_PROCESS_CPUTIME_ID: + clockwhich = LINUX_CPUCLOCK_WHICH(args->which); + switch (clockwhich) { + case LINUX_CPUCLOCK_PROF: + nwhich = CLOCK_PROF; + break; + case LINUX_CPUCLOCK_VIRT: + nwhich = CLOCK_VIRTUAL; + break; + case LINUX_CPUCLOCK_SCHED: + break; + default: + return (EINVAL); + } + break; + + default: + break; + } error = kern_clock_getres(td, nwhich, &ts); if (error != 0) { LIN_SDT_PROBE1(time, linux_clock_getres, getres_error, error); Modified: head/sys/compat/linux/linux_timer.h ============================================================================== --- head/sys/compat/linux/linux_timer.h Sun May 24 17:16:55 2015 (r283458) +++ head/sys/compat/linux/linux_timer.h Sun May 24 17:23:08 2015 (r283459) @@ -56,6 +56,23 @@ #define LINUX_CLOCK_SGI_CYCLE 10 #define LINUX_CLOCK_TAI 11 +#define LINUX_CPUCLOCK_PERTHREAD_MASK 4 +#define LINUX_CPUCLOCK_MASK 3 +#define LINUX_CPUCLOCK_WHICH(clock) \ + ((clock) & (clockid_t) LINUX_CPUCLOCK_MASK) +#define LINUX_CPUCLOCK_PROF 0 +#define LINUX_CPUCLOCK_VIRT 1 +#define LINUX_CPUCLOCK_SCHED 2 +#define LINUX_CPUCLOCK_MAX 3 +#define LINUX_CLOCKFD LINUX_CPUCLOCK_MAX +#define LINUX_CLOCKFD_MASK \ + (LINUX_CPUCLOCK_PERTHREAD_MASK|LINUX_CPUCLOCK_MASK) + +#define LINUX_CPUCLOCK_ID(clock) ((pid_t) ~((clock) >> 3)) +#define LINUX_CPUCLOCK_PERTHREAD(clock) \ + (((clock) & (clockid_t) LINUX_CPUCLOCK_PERTHREAD_MASK) != 0) + + #define L_SIGEV_SIGNAL 0 #define L_SIGEV_NONE 1 #define L_SIGEV_THREAD 2
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505241723.t4OHN8BB018745>