mirror of
https://github.com/opnsense/src.git
synced 2026-06-03 22:02:58 -04:00
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
This commit is contained in:
parent
cbc1089190
commit
7bc05ae6bb
1 changed files with 62 additions and 35 deletions
|
|
@ -65,6 +65,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp
|
|||
#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_clock_gettime_args *args)
|
|||
|
||||
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_clock_gettime_args *args)
|
|||
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_clock_gettime_args *args)
|
|||
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_clock_gettime_args *args)
|
|||
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_clock_getres_args *args)
|
|||
* 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_clock_getres_args *args)
|
|||
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_clock_getres_args *args)
|
|||
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_clock_getres_args *args)
|
|||
LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
|
||||
return (error);
|
||||
}
|
||||
|
||||
out:
|
||||
error = native_to_linux_timespec(<s, &ts);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
|
|
|||
Loading…
Reference in a new issue