From 725edadf86d63f56a584adf23265845c8590d734 Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Wed, 26 Jul 2017 19:57:32 +0200 Subject: [PATCH] libc/libpthread: Add clock_getcpuclockid() and pthread_getcpuclockid(). * Adjust clock_gettime() and clock_getres() to accept values obtained this way. * Also set _POSIX_CPUTIME and _POSIX_THREAD_CPUTIME, although we should really support values obtained by these functions in clock_settime() too. Based on and taken from FreeBSD's code. Reviewed-by: sephe --- include/pthread.h | 1 + include/time.h | 10 ++- include/unistd.h | 1 - lib/libc/gen/Makefile.inc | 4 +- lib/libc/gen/Symbol.map | 3 + lib/libc/gen/_pthread_stubs.c | 1 + lib/libc/gen/clock_getcpuclockid.3 | 98 +++++++++++++++++++++ lib/libc/gen/clock_getcpuclockid.c | 41 +++++++++ lib/libc/include/namespace.h | 1 + lib/libc/include/un-namespace.h | 1 + lib/libc/sys/Symbol.map | 6 ++ lib/libc/sys/clock_gettime.2 | 68 +++++++------- lib/libpthread/Makefile | 1 + lib/libpthread/pthread_getcpuclockid.3 | 89 +++++++++++++++++++ lib/libthread_xu/pthread.map | 2 + lib/libthread_xu/thread/Makefile.inc | 1 + lib/libthread_xu/thread/thr_getcpuclockid.c | 48 ++++++++++ lib/libthread_xu/thread/thr_init.c | 2 + sys/kern/init_sysent.c | 1 + sys/kern/kern_time.c | 80 ++++++++++++++++- sys/kern/syscalls.c | 1 + sys/kern/syscalls.master | 1 + sys/sys/param.h | 3 +- sys/sys/syscall.h | 3 +- sys/sys/syscall.mk | 3 +- sys/sys/sysproto.h | 9 ++ sys/sys/sysunion.h | 1 + sys/sys/unistd.h | 3 +- 28 files changed, 441 insertions(+), 42 deletions(-) create mode 100644 lib/libc/gen/clock_getcpuclockid.3 create mode 100644 lib/libc/gen/clock_getcpuclockid.c create mode 100644 lib/libpthread/pthread_getcpuclockid.3 create mode 100644 lib/libthread_xu/thread/thr_getcpuclockid.c diff --git a/include/pthread.h b/include/pthread.h index 666202fb71..12fb145979 100644 --- a/include/pthread.h +++ b/include/pthread.h @@ -198,6 +198,7 @@ int pthread_detach(pthread_t); int pthread_equal(pthread_t, pthread_t); void pthread_exit(void *) __dead2; void *pthread_getspecific(pthread_key_t); +int pthread_getcpuclockid(pthread_t, clockid_t *) __nonnull(2); int pthread_join(pthread_t, void **); int pthread_key_create(pthread_key_t *, void (*) (void *)) __nonnull(1); int pthread_key_delete(pthread_key_t); diff --git a/include/time.h b/include/time.h index 665ed72093..94c2fd7863 100644 --- a/include/time.h +++ b/include/time.h @@ -96,6 +96,13 @@ typedef __pid_t pid_t; #endif #endif +#if __BSD_VISIBLE +#ifndef _LWPID_T_DECLARED +#define _LWPID_T_DECLARED +typedef __pid_t lwpid_t; /* light weight process id */ +#endif +#endif + /* These macros are also in sys/time.h. */ #if !defined(CLOCK_REALTIME) && __POSIX_VISIBLE >= 199309 #define CLOCK_REALTIME 0 @@ -180,9 +187,9 @@ struct tm *localtime_r(const time_t *, struct tm *); #endif #if __POSIX_VISIBLE >= 200112 +int clock_getcpuclockid(pid_t, clockid_t *); #if 0 /* XXX missing */ struct sigevent; -int clock_getcpuclockid(pid_t, clockid_t *); int clock_nanosleep(clockid_t, int, const struct timespec *, struct timespec *); int timer_create(clockid_t, struct sigevent *__restrict, timer_t *__restrict); int timer_delete(timer_t); @@ -201,6 +208,7 @@ char *strptime(const char * __restrict, const char * __restrict, #endif #if __BSD_VISIBLE +int getcpuclockid(pid_t, lwpid_t, clockid_t *); void tzsetwall(void); time_t timelocal(struct tm * const); time_t timegm(struct tm * const); diff --git a/include/unistd.h b/include/unistd.h index 638cc91d99..906ef75b1d 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -99,7 +99,6 @@ typedef __uint32_t uid_t; /* XXX __uid_t */ #define _POSIX_SPAWN 200112L /* [SPN] */ #define _POSIX_THREAD_ATTR_STACKADDR 200112L /* [TSA] */ #define _POSIX_THREAD_ATTR_STACKSIZE 200112L /* [TSS] */ -#define _POSIX_THREAD_CPUTIME -1 /* [TCT] */ #define _POSIX_THREAD_PRIO_INHERIT 200112L /* [TPI] */ #define _POSIX_THREAD_PRIO_PROTECT 200112L /* [TPP] */ #define _POSIX_THREAD_PRIORITY_SCHEDULING 200112L /* [TPS] */ diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc index 7aa4851cb5..5ea09775a5 100644 --- a/lib/libc/gen/Makefile.inc +++ b/lib/libc/gen/Makefile.inc @@ -10,7 +10,7 @@ CMAPS+= ${.CURDIR}/gen/Symbol.map SRCS+= _once_stub.c _pthread_stubs.c _rand48.c _spinlock_stub.c \ _thread_init.c alarm.c arc4random.c assert.c basename.c \ - clock.c closedir.c confstr.c creat.c \ + clock.c clock_getcpuclockid.c closedir.c confstr.c creat.c \ ctermid.c daemon.c devname.c dirfd.c dirname.c disklabel.c disktab.c \ dlfcn.c drand48.c elf_utils.c erand48.c err.c errlst.c exec.c \ fdevname.c fmtcheck.c fmtmsg.c fnmatch.c fpclassify.c \ @@ -53,7 +53,7 @@ SRCS+= tls.c .if ${LIB} == "c" MAN+= alarm.3 arc4random.3 clock.3 \ basename.3 \ - confstr.3 creat.3 ctermid.3 daemon.3 \ + clock_getcpuclockid.3 confstr.3 creat.3 ctermid.3 daemon.3 \ devname.3 directory.3 dirname.3 \ dladdr.3 dlinfo.3 dlopen.3 \ dlclose.3 dlerror.3 dlfcn.3 dlsym.3 dlvsym.3 dl_iterate_phdr.3 \ diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index bdfce2b635..5b23ed786c 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -460,7 +460,9 @@ DF404.0 { }; DF410.0 { + clock_getcpuclockid; /* pthread stubs */ + pthread_getcpuclockid; pthread_getthreadid_np; }; @@ -518,6 +520,7 @@ DFprivate_1.0 { _pthread_exit; _pthread_getaffinity_np; _pthread_getconcurrency; + _pthread_getcpuclockid; _pthread_getprio; _pthread_getschedparam; _pthread_getspecific; diff --git a/lib/libc/gen/_pthread_stubs.c b/lib/libc/gen/_pthread_stubs.c index 13c0bd0ad2..a44debe56d 100644 --- a/lib/libc/gen/_pthread_stubs.c +++ b/lib/libc/gen/_pthread_stubs.c @@ -99,6 +99,7 @@ WR(stub_true, pthread_equal); WR(stub_exit, pthread_exit); WR(stub_zero, pthread_getaffinity_np); WR(stub_zero, pthread_getconcurrency); +WR(stub_zero, pthread_getcpuclockid); WR(stub_zero, pthread_getprio); WR(stub_zero, pthread_getschedparam); WR(stub_null, pthread_getspecific); diff --git a/lib/libc/gen/clock_getcpuclockid.3 b/lib/libc/gen/clock_getcpuclockid.3 new file mode 100644 index 0000000000..08d980219f --- /dev/null +++ b/lib/libc/gen/clock_getcpuclockid.3 @@ -0,0 +1,98 @@ +.\" Copyright (c) 2012 David Xu +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" Portions of this text are reprinted and reproduced in electronic form +.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- +.\" Portable Operating System Interface (POSIX), The Open Group Base +.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of +.\" Electrical and Electronics Engineers, Inc and The Open Group. In the +.\" event of any discrepancy between this version and the original IEEE and +.\" The Open Group Standard, the original IEEE and The Open Group Standard is +.\" the referee document. The original Standard can be obtained online at +.\" http://www.opengroup.org/unix/online.html. +.\" +.\" $FreeBSD: head/lib/libc/gen/clock_getcpuclockid.3 303742 2016-08-04 11:38:53Z pluknet $ +.\" +.Dd July 26, 2017 +.Dt CLOCK_GETCPUCLOCKID 3 +.Os +.Sh NAME +.Nm clock_getcpuclockid +.Nd access a process CPU-time clock +.Sh LIBRARY +.Lb libc +.Sh SYNOPSIS +.In time.h +.Ft int +.Fn clock_getcpuclockid "pid_t pid" "clockid_t *clock_id" +.Sh DESCRIPTION +The +.Fn clock_getcpuclockid +function returns the clock ID of the CPU-time clock of the process specified by +.Fa pid . +If the process described by +.Fa pid +exists and the calling process has permission, the clock ID of this +clock will be returned in +.Fa clock_id . +.Pp +If +.Fa pid +is zero, +.Fn clock_getcpuclockid +returns the clock ID of the CPU-time clock of the process +making the call. +.Sh RETURN VALUES +Upon successful completion, +.Fn clock_getcpuclockid +returns zero; otherwise, an error number is returned to indicate the +error. +.Sh ERRORS +The +.Fn clock_getcpuclockid +function will fail if: +.Bl -tag -width Er +.It Bq Er EPERM +The requesting process does not have permission to access the CPU-time +clock for the process. +.It Bq Er ESRCH +No process can be found corresponding to the process specified by +.Fa pid . +.El +.Sh SEE ALSO +.Xr clock_gettime 2 +.Sh STANDARDS +The +.Fn clock_getcpuclockid +function conforms to +.St -p1003.1-2001 . +.Sh HISTORY +The +.Fn clock_getcpuclockid +function first appeared in +.Fx 10.0 +and was ported to +.Dx 4.9 . +.Sh AUTHORS +.An David Xu Aq Mt davidxu@FreeBSD.org diff --git a/lib/libc/gen/clock_getcpuclockid.c b/lib/libc/gen/clock_getcpuclockid.c new file mode 100644 index 0000000000..62696bd46b --- /dev/null +++ b/lib/libc/gen/clock_getcpuclockid.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2017 The DragonFly Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific, prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +int +clock_getcpuclockid(pid_t pid, clockid_t *clock_id) +{ + if (getcpuclockid(pid, 0, clock_id)) + return (errno); + return (0); +} diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h index e2ad237aa7..d40d59a59d 100644 --- a/lib/libc/include/namespace.h +++ b/lib/libc/include/namespace.h @@ -128,6 +128,7 @@ #define pthread_exit _pthread_exit #define pthread_getaffinity_np _pthread_getaffinity_np #define pthread_getconcurrency _pthread_getconcurrency +#define pthread_getcpuclockid _pthread_getcpuclockid #define pthread_getprio _pthread_getprio #define pthread_getschedparam _pthread_getschedparam #define pthread_getspecific _pthread_getspecific diff --git a/lib/libc/include/un-namespace.h b/lib/libc/include/un-namespace.h index cecfc3697f..7ad87d75da 100644 --- a/lib/libc/include/un-namespace.h +++ b/lib/libc/include/un-namespace.h @@ -109,6 +109,7 @@ #undef pthread_exit #undef pthread_getaffinity_np #undef pthread_getconcurrency +#undef pthread_getcpuclockid #undef pthread_getprio #undef pthread_getschedparam #undef pthread_getspecific diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map index ece6736584..7cc20d13fc 100644 --- a/lib/libc/sys/Symbol.map +++ b/lib/libc/sys/Symbol.map @@ -320,6 +320,10 @@ DF408.0 { lwp_setaffinity; }; +DF410.0 { + getcpuclockid; +}; + DFprivate_1.0 { __fork; @@ -402,6 +406,7 @@ DFprivate_1.0 { __sys_futimens; __sys_futimes; __sys_get_tls_area; + __sys_getcpuclockid; __sys_getdents; __sys_getdirentries; __sys_getdtablesize; @@ -700,6 +705,7 @@ DFprivate_1.0 { _futimens; _futimes; _get_tls_area; + _getcpuclockid; _getdents; _getdirentries; _getdtablesize; diff --git a/lib/libc/sys/clock_gettime.2 b/lib/libc/sys/clock_gettime.2 index dcab0f09e4..5ac754c438 100644 --- a/lib/libc/sys/clock_gettime.2 +++ b/lib/libc/sys/clock_gettime.2 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD: head/lib/libc/sys/clock_gettime.2 292777 2015-12-27 15:37:07Z dchagin $ .\" -.Dd September 26, 2016 +.Dd July 26, 2017 .Dt CLOCK_GETTIME 2 .Os .Sh NAME @@ -58,37 +58,39 @@ used by a clock which is specified by .Pp The .Fa clock_id -argument -can be one of the following values: -.Dv CLOCK_REALTIME , -.Dv CLOCK_REALTIME_PRECISE , -and -.Dv CLOCK_REALTIME_FAST -for time that increments as a wall clock should; -.Dv CLOCK_MONOTONIC , -.Dv CLOCK_MONOTONIC_PRECISE , -and -.Dv CLOCK_MONOTONIC_FAST -which increments in SI seconds; -.Dv CLOCK_UPTIME , -.Dv CLOCK_UPTIME_PRECISE , -and -.Dv CLOCK_UPTIME_FAST -which starts at zero when the kernel boots and increments -monotonically in SI seconds while the machine is running; -.Dv CLOCK_VIRTUAL -for time that increments only when -the CPU is running in user mode on behalf of the calling process; -.Dv CLOCK_PROF -for time that increments when the CPU is running in user or -kernel mode; -.Dv CLOCK_SECOND -which returns the current second without performing a full time counter -query, using in-kernel cached value of current second; -.Dv CLOCK_PROCESS_CPUTIME_ID -which returns the CPU-time clock of the calling process; or -.Dv CLOCK_THREAD_CPUTIME_ID -which returns the CPU-time clock of the calling thread. +argument can be a value obtained from +.Xr clock_getcpuclockid 3 +or +.Xr pthread_getcpuclockid 3 +as well as the following values: +.Pp +.Bl -tag -width indent -compact +.It Dv CLOCK_REALTIME +.It Dv CLOCK_REALTIME_PRECISE +.It Dv CLOCK_REALTIME_FAST +Increments as a wall clock should. +.It Dv CLOCK_MONOTONIC +.It Dv CLOCK_MONOTONIC_PRECISE +.It Dv CLOCK_MONOTONIC_FAST +Increments in SI seconds. +.It Dv CLOCK_UPTIME +.It Dv CLOCK_UPTIME_PRECISE +.It Dv CLOCK_UPTIME_FAST +Starts at zero when the kernel boots and increments +monotonically in SI seconds while the machine is running. +.It Dv CLOCK_VIRTUAL +Increments only when +the CPU is running in user mode on behalf of the calling process. +.It Dv CLOCK_PROF +Increments when the CPU is running in user or kernel mode. +.It Dv CLOCK_SECOND +Returns the current second without performing a full time counter +query, using an in-kernel cached value of the current second. +.It Dv CLOCK_PROCESS_CPUTIME_ID +Returns the execution time of the calling process. +.It Dv CLOCK_THREAD_CPUTIME_ID +Returns the execution time of the calling thread. +.El .Pp The clock IDs .Dv CLOCK_REALTIME_FAST , @@ -161,7 +163,9 @@ A user other than the super-user attempted to set the time. .Sh SEE ALSO .Xr date 1 , .Xr adjtime 2 , +.Xr clock_getcpuclockid 3 , .Xr ctime 3 , +.Xr pthread_getcpuclockid 3 , .Xr timed 8 .Sh STANDARDS The diff --git a/lib/libpthread/Makefile b/lib/libpthread/Makefile index f915fdf99a..eccab0b3a4 100644 --- a/lib/libpthread/Makefile +++ b/lib/libpthread/Makefile @@ -18,6 +18,7 @@ MAN+= \ pthread_cleanup_pop.3 \ pthread_cleanup_push.3 \ pthread_getconcurrency.3 \ + pthread_getcpuclockid.3 \ pthread_condattr.3 \ pthread_cond_broadcast.3 \ pthread_cond_destroy.3 \ diff --git a/lib/libpthread/pthread_getcpuclockid.3 b/lib/libpthread/pthread_getcpuclockid.3 new file mode 100644 index 0000000000..ff4cb56754 --- /dev/null +++ b/lib/libpthread/pthread_getcpuclockid.3 @@ -0,0 +1,89 @@ +.\" Copyright (c) 2012 David Xu +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" Portions of this text are reprinted and reproduced in electronic form +.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology -- +.\" Portable Operating System Interface (POSIX), The Open Group Base +.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of +.\" Electrical and Electronics Engineers, Inc and The Open Group. In the +.\" event of any discrepancy between this version and the original IEEE and +.\" The Open Group Standard, the original IEEE and The Open Group Standard is +.\" the referee document. The original Standard can be obtained online at +.\" http://www.opengroup.org/unix/online.html. +.\" +.\" $FreeBSD: head/share/man/man3/pthread_getcpuclockid.3 303742 2016-08-04 11:38:53Z pluknet $ +.\" +.Dd July 26, 2017 +.Dt PTHREAD_GETCPUCLOCKID 3 +.Os +.Sh NAME +.Nm pthread_getcpuclockid +.Nd access a thread CPU-time clock +.Sh LIBRARY +.Lb libpthread +.Sh SYNOPSIS +.In pthread.h +.In time.h +.Ft int +.Fn pthread_getcpuclockid "pthread_t thread" "clockid_t *clock_id" +.Sh DESCRIPTION +The +.Fn pthread_getcpuclockid +returns the clock ID of the CPU-time clock of the thread specified by +.Fa thread , +if the thread described by +.Fa thread +exists. +.Sh RETURN VALUES +Upon successful completion, +.Fn pthread_getcpuclockid +returns zero; otherwise, an error number is returned to indicate the +error. +.Sh ERRORS +The +.Fn pthread_getcpuclockid +function will fail if: +.Bl -tag -width Er +.It Bq Er ESRCH +The value specified by +.Fa thread +does not refer to an existing thread. +.El +.Sh SEE ALSO +.Xr clock_gettime 2 , +.Xr clock_getcpuclockid 3 +.Sh STANDARDS +The +.Fn pthread_getcpuclockid +function conforms to +.St -p1003.1-2004 . +.Sh HISTORY +The +.Fn pthread_getcpuclockid +function first appeared in +.Fx 10.0 +and was ported to +.Dx 4.9 . +.Sh AUTHORS +.An David Xu Aq Mt davidxu@FreeBSD.org diff --git a/lib/libthread_xu/pthread.map b/lib/libthread_xu/pthread.map index e15440ee81..f1628a54f6 100644 --- a/lib/libthread_xu/pthread.map +++ b/lib/libthread_xu/pthread.map @@ -393,6 +393,8 @@ global: LIBTHREAD_1_2 { global: + _pthread_getcpuclockid; _pthread_getthreadid_np; + pthread_getcpuclockid; pthread_getthreadid_np; }; diff --git a/lib/libthread_xu/thread/Makefile.inc b/lib/libthread_xu/thread/Makefile.inc index af110a15f3..2bf5b7030d 100644 --- a/lib/libthread_xu/thread/Makefile.inc +++ b/lib/libthread_xu/thread/Makefile.inc @@ -19,6 +19,7 @@ SRCS+= \ thr_event.c \ thr_exit.c \ thr_fork.c \ + thr_getcpuclockid.c \ thr_getprio.c \ thr_getschedparam.c \ thr_getthreadid_np.c \ diff --git a/lib/libthread_xu/thread/thr_getcpuclockid.c b/lib/libthread_xu/thread/thr_getcpuclockid.c new file mode 100644 index 0000000000..36d451a962 --- /dev/null +++ b/lib/libthread_xu/thread/thr_getcpuclockid.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008 David Xu + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/lib/libthr/thread/thr_getcpuclockid.c 297706 2016-04-08 11:15:26Z kib $ + */ + +#include "namespace.h" +#include +#include +#include +#include "un-namespace.h" + +#include "thr_private.h" + +int +_pthread_getcpuclockid(pthread_t pthread, clockid_t *clock_id) +{ + if (pthread == NULL) + return (EINVAL); + + if (getcpuclockid(getpid(), pthread->tid, clock_id)) + return (errno); + return (0); +} + +__strong_reference(_pthread_getcpuclockid, pthread_getcpuclockid); diff --git a/lib/libthread_xu/thread/thr_init.c b/lib/libthread_xu/thread/thr_init.c index d14c621d73..c39919dcb2 100644 --- a/lib/libthread_xu/thread/thr_init.c +++ b/lib/libthread_xu/thread/thr_init.c @@ -107,6 +107,8 @@ STATIC_LIB_REQUIRE(_pthread_atfork); STATIC_LIB_REQUIRE(_fork); /* thr_affinity.c */ STATIC_LIB_REQUIRE(_pthread_getaffinity_np); +/* thr_getcpuclockid.c */ +STATIC_LIB_REQUIRE(_pthread_getcpuclockid); /* thr_getprio.c */ STATIC_LIB_REQUIRE(_pthread_getprio); /* thr_getschedparam.c */ diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 90d3de7816..2e777611a4 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -563,4 +563,5 @@ struct sysent sysent[] = { { AS(lwp_setaffinity_args), (sy_call_t *)sys_lwp_setaffinity }, /* 544 = lwp_setaffinity */ { AS(lwp_getaffinity_args), (sy_call_t *)sys_lwp_getaffinity }, /* 545 = lwp_getaffinity */ { AS(lwp_create2_args), (sy_call_t *)sys_lwp_create2 }, /* 546 = lwp_create2 */ + { AS(getcpuclockid_args), (sy_call_t *)sys_getcpuclockid }, /* 547 = getcpuclockid */ }; diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 02b7810230..887d41bf10 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -54,6 +54,12 @@ extern struct spinlock ntp_spin; +#define CPUCLOCK_BIT 0x80000000 +#define CPUCLOCK_ID_MASK ~CPUCLOCK_BIT +#define CPUCLOCK2LWPID(clock_id) (((clockid_t)(clock_id) >> 32) & CPUCLOCK_ID_MASK) +#define CPUCLOCK2PID(clock_id) ((clock_id) & CPUCLOCK_ID_MASK) +#define MAKE_CPUCLOCK(pid, lwp_id) ((clockid_t)(lwp_id) << 32 | (pid) | CPUCLOCK_BIT) + struct timezone tz; /* @@ -196,6 +202,8 @@ int kern_clock_gettime(clockid_t clock_id, struct timespec *ats) { struct proc *p; + struct lwp *lp; + lwpid_t lwp_id; p = curproc; switch(clock_id) { @@ -231,7 +239,25 @@ kern_clock_gettime(clockid_t clock_id, struct timespec *ats) get_thread_cputime(curthread, ats); break; default: - return (EINVAL); + if ((clock_id & CPUCLOCK_BIT) == 0) + return (EINVAL); + if ((p = pfind(CPUCLOCK2PID(clock_id))) == NULL) + return (EINVAL); + lwp_id = CPUCLOCK2LWPID(clock_id); + if (lwp_id == 0) { + get_process_cputime(p, ats); + } else { + lwkt_gettoken(&p->p_token); + lp = lwp_rb_tree_RB_LOOKUP(&p->p_lwp_tree, lwp_id); + if (lp == NULL) { + lwkt_reltoken(&p->p_token); + PRELE(p); + return (EINVAL); + } + get_thread_cputime(lp->lwp_thread, ats); + lwkt_reltoken(&p->p_token); + } + PRELE(p); } return (0); } @@ -330,7 +356,10 @@ kern_clock_getres(clockid_t clock_id, struct timespec *ts) ts->tv_nsec = 1000; break; default: - return (EINVAL); + if ((clock_id & CPUCLOCK_BIT) != 0) + ts->tv_nsec = 1000; + else + return (EINVAL); } return (0); @@ -352,6 +381,53 @@ sys_clock_getres(struct clock_getres_args *uap) return (error); } +static int +kern_getcpuclockid(pid_t pid, lwpid_t lwp_id, clockid_t *clock_id) +{ + struct proc *p; + int error = 0; + + if (pid == 0) { + p = curproc; + pid = p->p_pid; + PHOLD(p); + } else { + p = pfind(pid); + if (p == NULL) + return (ESRCH); + } + /* lwp_id can be 0 when called by clock_getcpuclockid() */ + if (lwp_id < 0) { + error = EINVAL; + goto out; + } + lwkt_gettoken(&p->p_token); + if (lwp_id > 0 && + lwp_rb_tree_RB_LOOKUP(&p->p_lwp_tree, lwp_id) == NULL) { + lwkt_reltoken(&p->p_token); + error = ESRCH; + goto out; + } + *clock_id = MAKE_CPUCLOCK(pid, lwp_id); + lwkt_reltoken(&p->p_token); +out: + PRELE(p); + return (error); +} + +int +sys_getcpuclockid(struct getcpuclockid_args *uap) +{ + clockid_t clk_id; + int error; + + error = kern_getcpuclockid(uap->pid, uap->lwp_id, &clk_id); + if (error == 0) + error = copyout(&clk_id, uap->clock_id, sizeof(clockid_t)); + + return (error); +} + /* * nanosleep1() * diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index 2f47e388cd..df9e415cc2 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -553,4 +553,5 @@ const char *syscallnames[] = { "lwp_setaffinity", /* 544 = lwp_setaffinity */ "lwp_getaffinity", /* 545 = lwp_getaffinity */ "lwp_create2", /* 546 = lwp_create2 */ + "getcpuclockid", /* 547 = getcpuclockid */ }; diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 01bf54da32..21351da410 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -747,3 +747,4 @@ 544 STD { int lwp_setaffinity(pid_t pid, lwpid_t tid, const cpumask_t *mask); } 545 STD { int lwp_getaffinity(pid_t pid, lwpid_t tid, cpumask_t *mask); } 546 STD { int lwp_create2(struct lwp_params *params, const cpumask_t *mask); } +547 STD { int getcpuclockid(pid_t pid, lwpid_t lwp_id, clockid_t *clock_id); } diff --git a/sys/sys/param.h b/sys/sys/param.h index 4971dbbefc..653d149d36 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -157,9 +157,10 @@ * 400905 - PTHREAD_STACK_MIN increase: 1024 => 16384 * 400906 - lwpid_t >=1, instead of >=0 * 400907 - pthread_getthreadid_np() + * 400908 - {clock,pthread}_getcpuclockid() */ #undef __DragonFly_version -#define __DragonFly_version 400907 /* propagated to newvers */ +#define __DragonFly_version 400908 /* propagated to newvers */ #include diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index 2094c4a37f..11b23e44f7 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -381,4 +381,5 @@ #define SYS_lwp_setaffinity 544 #define SYS_lwp_getaffinity 545 #define SYS_lwp_create2 546 -#define SYS_MAXSYSCALL 547 +#define SYS_getcpuclockid 547 +#define SYS_MAXSYSCALL 548 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index 635a7e20a1..bf13b67710 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -310,4 +310,5 @@ MIASM = \ ppoll.o \ lwp_setaffinity.o \ lwp_getaffinity.o \ - lwp_create2.o + lwp_create2.o \ + getcpuclockid.o diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index 5e47f0063a..73f9541bed 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -2348,6 +2348,14 @@ struct lwp_create2_args { struct lwp_params * params; char params_[PAD_(struct lwp_params *)]; const cpumask_t * mask; char mask_[PAD_(const cpumask_t *)]; }; +struct getcpuclockid_args { +#ifdef _KERNEL + struct sysmsg sysmsg; +#endif + pid_t pid; char pid_[PAD_(pid_t)]; + lwpid_t lwp_id; char lwp_id_[PAD_(lwpid_t)]; + clockid_t * clock_id; char clock_id_[PAD_(clockid_t *)]; +}; struct olseek_args { #ifdef _KERNEL struct sysmsg sysmsg; @@ -2844,6 +2852,7 @@ int sys_ppoll (struct ppoll_args *); int sys_lwp_setaffinity (struct lwp_setaffinity_args *); int sys_lwp_getaffinity (struct lwp_getaffinity_args *); int sys_lwp_create2 (struct lwp_create2_args *); +int sys_getcpuclockid (struct getcpuclockid_args *); #endif /* !_SYS_SYSPROTO_H_ */ #undef PAD_ diff --git a/sys/sys/sysunion.h b/sys/sys/sysunion.h index fde0762f88..bfb4ebbf9a 100644 --- a/sys/sys/sysunion.h +++ b/sys/sys/sysunion.h @@ -319,4 +319,5 @@ union sysunion { struct lwp_setaffinity_args lwp_setaffinity; struct lwp_getaffinity_args lwp_getaffinity; struct lwp_create2_args lwp_create2; + struct getcpuclockid_args getcpuclockid; }; diff --git a/sys/sys/unistd.h b/sys/sys/unistd.h index 7a02556d78..d62fbe55fc 100644 --- a/sys/sys/unistd.h +++ b/sys/sys/unistd.h @@ -55,7 +55,7 @@ #define _POSIX_BARRIERS 200112L /* mandatory */ #define _POSIX_CHOWN_RESTRICTED 1 #define _POSIX_CLOCK_SELECTION -1 /* XXX mandatory */ -#define _POSIX_CPUTIME -1 /* [CPT] */ +#define _POSIX_CPUTIME 200112L /* [CPT] */ #define _POSIX_FSYNC 200112L /* [FSC] */ #define _POSIX_IPV6 0 #define _POSIX_JOB_CONTROL 1 /* mandatory */ @@ -75,6 +75,7 @@ #define _POSIX_SPIN_LOCKS 200112L /* mandatory */ #define _POSIX_SPORADIC_SERVER -1 /* [SS] */ #define _POSIX_SYNCHRONIZED_IO -1 /* [SIO] */ +#define _POSIX_THREAD_CPUTIME 200112L /* [TCT] */ #define _POSIX_TIMEOUTS 200112L /* mandatory */ #define _POSIX_TIMERS 200112L /* mandatory */ #define _POSIX_TYPED_MEMORY_OBJECTS -1 /* [TYM] */ -- 2.41.0