Date: Mon, 24 Aug 2020 14:48:54 +0000 (UTC) From: Edward Tomasz Napierala <trasz@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r364689 - stable/12/sys/compat/linux Message-ID: <202008241448.07OEmsYl011360@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: trasz Date: Mon Aug 24 14:48:54 2020 New Revision: 364689 URL: https://svnweb.freebsd.org/changeset/base/364689 Log: MFC r357493 by dchagin: Fix clock_gettime() and clock_getres() for cpu clocks: - handle the CLOCK_{PROCESS,THREAD}_CPUTIME_ID specified directly; - fix thread id calculation as in the Linuxulator we should convert the user supplied thread id to struct thread * by linux_tdfind(); - fix CPUCLOCK_SCHED case by using kern_{process,thread}_cputime() directly as native get_cputime() used by kern_clock_gettime() uses native tdfind()/pfind() to find proccess/thread. PR: 240990 Modified: stable/12/sys/compat/linux/linux_time.c Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/compat/linux/linux_time.c ============================================================================== --- stable/12/sys/compat/linux/linux_time.c Mon Aug 24 14:26:48 2020 (r364688) +++ stable/12/sys/compat/linux/linux_time.c Mon Aug 24 14:48:54 2020 (r364689) @@ -65,6 +65,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/0 #endif #include <compat/linux/linux_dtrace.h> +#include <compat/linux/linux_misc.h> #include <compat/linux/linux_timer.h> /* DTrace init */ @@ -203,6 +204,12 @@ linux_to_native_clockid(clockid_t *n, clockid_t l) case LINUX_CLOCK_MONOTONIC: *n = CLOCK_MONOTONIC; break; + case LINUX_CLOCK_PROCESS_CPUTIME_ID: + *n = CLOCK_PROCESS_CPUTIME_ID; + break; + case LINUX_CLOCK_THREAD_CPUTIME_ID: + *n = CLOCK_THREAD_CPUTIME_ID; + break; case LINUX_CLOCK_REALTIME_COARSE: *n = CLOCK_REALTIME_FAST; break; @@ -269,8 +276,13 @@ linux_clock_gettime(struct thread *td, struct linux_cl switch (nwhich) { case CLOCK_PROCESS_CPUTIME_ID: - clockwhich = LINUX_CPUCLOCK_WHICH(args->which); - pid = LINUX_CPUCLOCK_ID(args->which); + if (args->which < 0) { + clockwhich = LINUX_CPUCLOCK_WHICH(args->which); + pid = LINUX_CPUCLOCK_ID(args->which); + } else { + clockwhich = LINUX_CPUCLOCK_SCHED; + pid = 0; + } if (pid == 0) { p = td->td_proc; PROC_LOCK(p); @@ -296,12 +308,8 @@ linux_clock_gettime(struct thread *td, struct linux_cl TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); break; case LINUX_CPUCLOCK_SCHED: + kern_process_cputime(p, &tp); 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); @@ -311,14 +319,19 @@ linux_clock_gettime(struct thread *td, struct linux_cl break; case CLOCK_THREAD_CPUTIME_ID: - clockwhich = LINUX_CPUCLOCK_WHICH(args->which); + if (args->which < 0) { + clockwhich = LINUX_CPUCLOCK_WHICH(args->which); + tid = LINUX_CPUCLOCK_ID(args->which); + } else { + clockwhich = LINUX_CPUCLOCK_SCHED; + tid = 0; + } 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); + targettd = linux_tdfind(td, tid, p->p_pid); if (targettd == NULL) return (EINVAL); } @@ -343,12 +356,10 @@ linux_clock_gettime(struct thread *td, struct linux_cl TIMEVAL_TO_TIMESPEC(&ru.ru_utime, &tp); break; case LINUX_CPUCLOCK_SCHED: - error = kern_clock_getcpuclockid2(td, tid, - CPUCLOCK_WHICH_TID, &nwhich); + if (td == targettd) + targettd = NULL; + kern_thread_cputime(targettd, &tp); PROC_UNLOCK(p); - if (error != 0) - return (EINVAL); - error = kern_clock_gettime(td, nwhich, &tp); break; default: PROC_UNLOCK(p); @@ -440,25 +451,27 @@ linux_clock_getres(struct thread *td, struct linux_clo * 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); + if (args->which < 0) { + switch (nwhich) { + case CLOCK_THREAD_CPUTIME_ID: + tid = LINUX_CPUCLOCK_ID(args->which); + if (tid != 0) { + p = td->td_proc; + if (linux_tdfind(td, tid, p->p_pid) == NULL) + return (EINVAL); + 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; } - 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) { @@ -471,6 +484,20 @@ linux_clock_getres(struct thread *td, struct linux_clo case CLOCK_THREAD_CPUTIME_ID: case CLOCK_PROCESS_CPUTIME_ID: clockwhich = LINUX_CPUCLOCK_WHICH(args->which); + /* + * In both cases (when the clock id obtained by a call to + * clock_getcpuclockid() or using the clock + * ID CLOCK_PROCESS_CPUTIME_ID Linux hardcodes precision + * of clock. The same for the CLOCK_THREAD_CPUTIME_ID clock. + * + * See Linux posix_cpu_clock_getres() implementation. + */ + if (args->which > 0 || clockwhich == LINUX_CPUCLOCK_SCHED) { + ts.tv_sec = 0; + ts.tv_nsec = 1; + goto out; + } + switch (clockwhich) { case LINUX_CPUCLOCK_PROF: nwhich = CLOCK_PROF; @@ -478,8 +505,6 @@ linux_clock_getres(struct thread *td, struct linux_clo case LINUX_CPUCLOCK_VIRT: nwhich = CLOCK_VIRTUAL; break; - case LINUX_CPUCLOCK_SCHED: - break; default: return (EINVAL); } @@ -494,6 +519,8 @@ linux_clock_getres(struct thread *td, struct linux_clo LIN_SDT_PROBE1(time, linux_clock_getres, return, error); return (error); } + +out: error = native_to_linux_timespec(<s, &ts); if (error != 0) return (error);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202008241448.07OEmsYl011360>