svn commit: r357493 - head/sys/compat/linux

Dmitry Chagin dchagin at FreeBSD.org
Tue Feb 4 05:27:05 UTC 2020


Author: dchagin
Date: Tue Feb  4 05:27:05 2020
New Revision: 357493
URL: https://svnweb.freebsd.org/changeset/base/357493

Log:
  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
  Reviewed by:		kib
  Differential Revision:	https://reviews.freebsd.org/D23341
  MFC after:		2 weeks

Modified:
  head/sys/compat/linux/linux_time.c

Modified: head/sys/compat/linux/linux_time.c
==============================================================================
--- head/sys/compat/linux/linux_time.c	Tue Feb  4 05:25:51 2020	(r357492)
+++ head/sys/compat/linux/linux_time.c	Tue Feb  4 05:27:05 2020	(r357493)
@@ -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(&lts, &ts);
 	if (error != 0)
 		return (error);


More information about the svn-src-head mailing list