Add some clock mappings used in glibc 2.20.
Differential Revision: https://reviews.freebsd.org/D1465 Reviewd by: trasz
This commit is contained in:
parent
7d96520b25
commit
2711aba97e
@ -39,8 +39,11 @@ __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp
|
||||
|
||||
#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,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 */
|
||||
LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE);
|
||||
@ -157,6 +160,20 @@ linux_to_native_clockid(clockid_t *n, clockid_t l)
|
||||
|
||||
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, clockid_t l)
|
||||
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, struct linux_clock_gettime_args *args)
|
||||
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, struct linux_clock_settime_args *args)
|
||||
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, struct linux_clock_getres_args *args)
|
||||
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);
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user