On Fri, Jun 05, 2020 at 08:34:12PM +0300, Paul Irofti wrote: > On 05.06.2020 20:25, Mark Kettenis wrote: > > > Date: Fri, 5 Jun 2020 01:33:16 +0300 > > > From: Paul Irofti <p...@irofti.net> > > > > > > On Wed, Jun 03, 2020 at 05:13:42PM +0300, Paul Irofti wrote: > > > > On 2020-05-31 20:46, Mark Kettenis wrote: > > > > > Forget about all that for a moment. Here is an alternative > > > > > suggestion: > > > > > > > > > > On sparc64 we need to support both tick_timecounter and > > > > > sys_tick_timecounter. So we need some sort of clockid value to > > > > > distnguish between those two. I already suggested to use the tc_user > > > > > field of the timecounter for that. 0 means that a timecounter is not > > > > > usable in userland, a (small) positive integer means a specific > > > > > timecounter type. The code in libc will need to know whether a > > > > > particular timecounter type can be supported. My proposal would be to > > > > > implement a function*on all architecture* that takes the clockid as > > > > > an argument and returns a pointer to the function that implements > > > > > support for that timecounter. On architectures without support, ir > > > > > when called with a clockid that isn't supported, that function would > > > > > simply return NULL. > > > > > > > > I am sorry, but the more I try to implement this in a sane way, the more > > > > obvious it is that it is not possible. I would rather have a define > > > > sausage > > > > than something like this. > > > > > > > > I will try to think of something else that avoids the defines, but I do > > > > not > > > > think that your proposal is a valid solution. > > > > > > OK. I think I found an elegant way around this using the Makefile > > > system: if usertc.c is not present in the arch/${MACHINE}/gen, then a > > > stub gen/usertc.c file is built that just sets the function pointer to > > > NULL. This avoids the need for the define checks in dlfcn/init.c and I > > > think fixes the rest of the issues discussed around this bit. > > > > > > Also included in the diff are a few other fixes and regression tests. > > > I left the rdtsc and acpihpet example (with no functional acpihpet > > > support) just to show-case how we can handle multiple clocks on > > > architectures that have them. > > > > You're still using tk_user unconditionally. If the kernel returns a > > tk_user value that is larger than what's supported by libc you have an > > out-of-bounds array access. > > > > Also if the machine switches to a timecounter that has tk_user == 0 > > you have an out-of-bounds array access. If that happens you need to > > detect this and fall back on the system call. > > Right. Even though we test in the beginning for tk_user=0 it might change > until the access to tc_get_timecount(). I will fix this in my next diff. > Thanks!
Hi, This iteration of the diff adds bounds checking for tk_user and moves the usertc.c stub to every arch in libc as recommanded by deraadt@. It also fixes a gettimeofday issue reported by cheloha@ and tb@. The acpihpet stub is still there, but it will be removed in the final diff. Paul diff --git lib/libc/arch/aarch64/gen/Makefile.inc lib/libc/arch/aarch64/gen/Makefile.inc index a7b1b73f3ef..ee198f5d611 100644 --- lib/libc/arch/aarch64/gen/Makefile.inc +++ lib/libc/arch/aarch64/gen/Makefile.inc @@ -9,4 +9,4 @@ SRCS+= fpgetmask.c fpgetround.c fpgetsticky.c SRCS+= fpsetmask.c fpsetround.c fpsetsticky.c SRCS+= fpclassifyl.c SRCS+= isfinitel.c isinfl.c isnanl.c isnormall.c -SRCS+= signbitl.c +SRCS+= signbitl.c usertc.c diff --git lib/libc/arch/aarch64/gen/usertc.c lib/libc/arch/aarch64/gen/usertc.c new file mode 100644 index 00000000000..84a112c2ea3 --- /dev/null +++ lib/libc/arch/aarch64/gen/usertc.c @@ -0,0 +1,21 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/timetc.h> + +int (*const _tc_get_timecount)(struct timekeep *, uint64_t *) = NULL; diff --git lib/libc/arch/alpha/gen/Makefile.inc lib/libc/arch/alpha/gen/Makefile.inc index a44599d2cab..2a8abd32b61 100644 --- lib/libc/arch/alpha/gen/Makefile.inc +++ lib/libc/arch/alpha/gen/Makefile.inc @@ -3,5 +3,5 @@ SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c setjmp.S SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \ - fpsetround.c fpsetsticky.c + fpsetround.c fpsetsticky.c usertc.c SRCS+= sigsetjmp.S diff --git lib/libc/arch/alpha/gen/usertc.c lib/libc/arch/alpha/gen/usertc.c new file mode 100644 index 00000000000..84a112c2ea3 --- /dev/null +++ lib/libc/arch/alpha/gen/usertc.c @@ -0,0 +1,21 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/timetc.h> + +int (*const _tc_get_timecount)(struct timekeep *, uint64_t *) = NULL; diff --git lib/libc/arch/amd64/gen/Makefile.inc lib/libc/arch/amd64/gen/Makefile.inc index e995309ed71..f6349e2b974 100644 --- lib/libc/arch/amd64/gen/Makefile.inc +++ lib/libc/arch/amd64/gen/Makefile.inc @@ -2,6 +2,7 @@ SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.S nan.c setjmp.S \ sigsetjmp.S -SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c +SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c \ + usertc.c SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S fpsetmask.S \ fpsetround.S fpsetsticky.S diff --git lib/libc/arch/amd64/gen/usertc.c lib/libc/arch/amd64/gen/usertc.c new file mode 100644 index 00000000000..3f3052445cf --- /dev/null +++ lib/libc/arch/amd64/gen/usertc.c @@ -0,0 +1,53 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/timetc.h> + +static uint64_t +rdtsc() +{ + uint32_t hi, lo; + asm volatile("rdtsc" : "=a"(lo), "=d"(hi)); + return ((uint64_t)lo)|(((uint64_t)hi)<<32); +} + +static uint64_t +acpihpet() +{ + return rdtsc(); /* JUST TO COMPILE */ +} + +static uint64_t (*get_tc[])(void) = +{ + rdtsc, + acpihpet, +}; + +int +tc_get_timecount(struct timekeep *tk, uint64_t *tc) +{ + int tk_user = tk->tk_user; + + if (tc == NULL || tk_user < 1 || tk_user > tk->tk_nclocks) + return -1; + + *tc = (*get_tc[tk_user - 1])(); + return 0; +} +int (*const _tc_get_timecount)(struct timekeep *tk, uint64_t *tc) + = tc_get_timecount; diff --git lib/libc/arch/arm/gen/Makefile.inc lib/libc/arch/arm/gen/Makefile.inc index 1b4ab2f3ae7..27090a0d9dc 100644 --- lib/libc/arch/arm/gen/Makefile.inc +++ lib/libc/arch/arm/gen/Makefile.inc @@ -2,5 +2,5 @@ # $NetBSD: Makefile.inc,v 1.6 2003/08/01 17:03:47 lukem Exp $ SRCS+= byte_swap_2.S byte_swap_4.S divsi3.S fabs.c flt_rounds.c infinity.c -SRCS+= ldexp.c modf.c nan.c +SRCS+= ldexp.c modf.c nan.c usertc.c SRCS+= setjmp.S _setjmp.S sigsetjmp.S diff --git lib/libc/arch/arm/gen/usertc.c lib/libc/arch/arm/gen/usertc.c new file mode 100644 index 00000000000..84a112c2ea3 --- /dev/null +++ lib/libc/arch/arm/gen/usertc.c @@ -0,0 +1,21 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/timetc.h> + +int (*const _tc_get_timecount)(struct timekeep *, uint64_t *) = NULL; diff --git lib/libc/arch/hppa/gen/Makefile.inc lib/libc/arch/hppa/gen/Makefile.inc index e0c864242fe..1fde24670f1 100644 --- lib/libc/arch/hppa/gen/Makefile.inc +++ lib/libc/arch/hppa/gen/Makefile.inc @@ -2,6 +2,6 @@ SRCS+= setjmp.S SRCS+= fabs.c -SRCS+= infinity.c ldexp.c modf.c nan.c +SRCS+= infinity.c ldexp.c modf.c nan.c usertc.c SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \ fpsetround.c fpsetsticky.c diff --git lib/libc/arch/hppa/gen/usertc.c lib/libc/arch/hppa/gen/usertc.c new file mode 100644 index 00000000000..84a112c2ea3 --- /dev/null +++ lib/libc/arch/hppa/gen/usertc.c @@ -0,0 +1,21 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/timetc.h> + +int (*const _tc_get_timecount)(struct timekeep *, uint64_t *) = NULL; diff --git lib/libc/arch/i386/gen/Makefile.inc lib/libc/arch/i386/gen/Makefile.inc index 4c18e059581..b7dd30adccd 100644 --- lib/libc/arch/i386/gen/Makefile.inc +++ lib/libc/arch/i386/gen/Makefile.inc @@ -1,6 +1,6 @@ # $OpenBSD: Makefile.inc,v 1.14 2012/04/19 19:14:56 deraadt Exp $ -SRCS+= _setjmp.S fabs.S infinity.c ldexp.c \ +SRCS+= _setjmp.S fabs.S infinity.c ldexp.c usertc.c \ modf.S nan.c setjmp.S sigsetjmp.S SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c SRCS+= flt_rounds.S fpgetmask.S fpgetround.S fpgetsticky.S fpsetmask.S \ diff --git lib/libc/arch/i386/gen/usertc.c lib/libc/arch/i386/gen/usertc.c new file mode 100644 index 00000000000..84a112c2ea3 --- /dev/null +++ lib/libc/arch/i386/gen/usertc.c @@ -0,0 +1,21 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/timetc.h> + +int (*const _tc_get_timecount)(struct timekeep *, uint64_t *) = NULL; diff --git lib/libc/arch/m88k/gen/Makefile.inc lib/libc/arch/m88k/gen/Makefile.inc index cff75b8d425..d66f66af4af 100644 --- lib/libc/arch/m88k/gen/Makefile.inc +++ lib/libc/arch/m88k/gen/Makefile.inc @@ -1,7 +1,7 @@ # $OpenBSD: Makefile.inc,v 1.16 2013/06/05 22:06:30 miod Exp $ # $NetBSD: Makefile.inc,v 1.3 1995/04/10 21:09:06 jtc Exp $ -SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c +SRCS+= _setjmp.S fabs.S infinity.c ldexp.c modf.c nan.c usertc.c SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \ fpsetround.c fpsetsticky.c SRCS+= setjmp.S sigsetjmp.S diff --git lib/libc/arch/m88k/gen/usertc.c lib/libc/arch/m88k/gen/usertc.c new file mode 100644 index 00000000000..84a112c2ea3 --- /dev/null +++ lib/libc/arch/m88k/gen/usertc.c @@ -0,0 +1,21 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/timetc.h> + +int (*const _tc_get_timecount)(struct timekeep *, uint64_t *) = NULL; diff --git lib/libc/arch/mips64/gen/Makefile.inc lib/libc/arch/mips64/gen/Makefile.inc index 8cf1fc2d28a..839241a2069 100644 --- lib/libc/arch/mips64/gen/Makefile.inc +++ lib/libc/arch/mips64/gen/Makefile.inc @@ -1,6 +1,6 @@ # $OpenBSD: Makefile.inc,v 1.12 2012/04/12 16:14:09 deraadt Exp $ -SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c +SRCS+= _setjmp.S fabs.S infinity.c ldexp.S modf.S nan.c usertc.c SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \ fpsetround.c fpsetsticky.c SRCS+= fpclassifyl.c isfinitel.c isinfl.c isnanl.c isnormall.c signbitl.c diff --git lib/libc/arch/mips64/gen/usertc.c lib/libc/arch/mips64/gen/usertc.c new file mode 100644 index 00000000000..84a112c2ea3 --- /dev/null +++ lib/libc/arch/mips64/gen/usertc.c @@ -0,0 +1,21 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/timetc.h> + +int (*const _tc_get_timecount)(struct timekeep *, uint64_t *) = NULL; diff --git lib/libc/arch/powerpc/gen/Makefile.inc lib/libc/arch/powerpc/gen/Makefile.inc index 6b2e4613ee8..d4d7b00bff7 100644 --- lib/libc/arch/powerpc/gen/Makefile.inc +++ lib/libc/arch/powerpc/gen/Makefile.inc @@ -1,5 +1,5 @@ SRCS+= infinity.c setjmp.S sigsetjmp.S flt_rounds.c ldexp.c modf.c nan.c -SRCS+= fabs.c +SRCS+= fabs.c usertc.c SRCS+= fpgetmask.c fpsetmask.c SRCS+= fpgetround.c fpsetround.c SRCS+= fpgetsticky.c fpsetsticky.c diff --git lib/libc/arch/powerpc/gen/usertc.c lib/libc/arch/powerpc/gen/usertc.c new file mode 100644 index 00000000000..84a112c2ea3 --- /dev/null +++ lib/libc/arch/powerpc/gen/usertc.c @@ -0,0 +1,21 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/timetc.h> + +int (*const _tc_get_timecount)(struct timekeep *, uint64_t *) = NULL; diff --git lib/libc/arch/sh/gen/Makefile.inc lib/libc/arch/sh/gen/Makefile.inc index 55de1973b30..4724fb3a6a8 100644 --- lib/libc/arch/sh/gen/Makefile.inc +++ lib/libc/arch/sh/gen/Makefile.inc @@ -3,4 +3,4 @@ SRCS+= flt_rounds.c infinity.c ldexp.c modf.c nan.c setjmp.S _setjmp.S SRCS+= sigsetjmp.S SRCS+= fabs.c fpgetmask.c fpgetround.c fpgetsticky.c \ - fpsetmask.c fpsetround.c fpsetsticky.c + fpsetmask.c fpsetround.c fpsetsticky.c usertc.c diff --git lib/libc/arch/sh/gen/usertc.c lib/libc/arch/sh/gen/usertc.c new file mode 100644 index 00000000000..84a112c2ea3 --- /dev/null +++ lib/libc/arch/sh/gen/usertc.c @@ -0,0 +1,21 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/timetc.h> + +int (*const _tc_get_timecount)(struct timekeep *, uint64_t *) = NULL; diff --git lib/libc/arch/sparc64/gen/Makefile.inc lib/libc/arch/sparc64/gen/Makefile.inc index 58259cedef6..a908e022954 100644 --- lib/libc/arch/sparc64/gen/Makefile.inc +++ lib/libc/arch/sparc64/gen/Makefile.inc @@ -3,5 +3,5 @@ SRCS+= _setjmp.S fabs.S fixunsdfsi.S flt_rounds.c fpclassifyl.c \ fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \ fpsetround.c fpsetsticky.c infinity.c isfinitel.c \ - isinfl.c isnanl.c isnormall.c ldexp.c modf.S \ + isinfl.c isnanl.c isnormall.c ldexp.c usertc.c modf.S \ mul.S nan.c setjmp.S signbitl.c sigsetjmp.S umul.S diff --git lib/libc/arch/sparc64/gen/usertc.c lib/libc/arch/sparc64/gen/usertc.c new file mode 100644 index 00000000000..84a112c2ea3 --- /dev/null +++ lib/libc/arch/sparc64/gen/usertc.c @@ -0,0 +1,21 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/timetc.h> + +int (*const _tc_get_timecount)(struct timekeep *, uint64_t *) = NULL; diff --git lib/libc/asr/asr.c lib/libc/asr/asr.c index cd056c85719..2b25d49f32a 100644 --- lib/libc/asr/asr.c +++ lib/libc/asr/asr.c @@ -196,11 +196,11 @@ poll_intrsafe(struct pollfd *fds, nfds_t nfds, int timeout) struct timespec pollstart, pollend, elapsed; int r; - if (clock_gettime(CLOCK_MONOTONIC, &pollstart)) + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollstart)) return -1; while ((r = poll(fds, 1, timeout)) == -1 && errno == EINTR) { - if (clock_gettime(CLOCK_MONOTONIC, &pollend)) + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &pollend)) return -1; timespecsub(&pollend, &pollstart, &elapsed); timeout -= elapsed.tv_sec * 1000 + elapsed.tv_nsec / 1000000; @@ -418,7 +418,7 @@ asr_check_reload(struct asr *asr) asr->a_rtime = 0; } - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1) return; if ((ts.tv_sec - asr->a_rtime) < RELOAD_DELAY && asr->a_rtime != 0) diff --git lib/libc/crypt/bcrypt.c lib/libc/crypt/bcrypt.c index 82de8fa33b7..02fd3013cc1 100644 --- lib/libc/crypt/bcrypt.c +++ lib/libc/crypt/bcrypt.c @@ -248,9 +248,9 @@ _bcrypt_autorounds(void) char buf[_PASSWORD_LEN]; int duration; - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &before); + WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &before); bcrypt_newhash("testpassword", r, buf, sizeof(buf)); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &after); + WRAP(clock_gettime)(CLOCK_THREAD_CPUTIME_ID, &after); duration = after.tv_sec - before.tv_sec; duration *= 1000000; diff --git lib/libc/dlfcn/init.c lib/libc/dlfcn/init.c index 270f54aada5..19d0a2c3ad6 100644 --- lib/libc/dlfcn/init.c +++ lib/libc/dlfcn/init.c @@ -20,6 +20,7 @@ #include <sys/types.h> #include <sys/syscall.h> +#include <sys/timetc.h> /* timekeep */ #ifndef PIC #include <sys/mman.h> @@ -45,8 +46,9 @@ /* XXX should be in an include file shared with csu */ char ***_csu_finish(char **_argv, char **_envp, void (*_cleanup)(void)); -/* provide definition for this */ +/* provide definitions for these */ int _pagesize = 0; +void *_timekeep = NULL; /* * In dynamicly linked binaries environ and __progname are overriden by @@ -105,6 +107,10 @@ _libc_preinit(int argc, char **argv, char **envp, dl_cb_cb *cb) phnum = aux->au_v; break; #endif /* !PIC */ + case AUX_openbsd_timekeep: + if (_tc_get_timecount) + _timekeep = (void *)aux->au_v; + break; } } diff --git lib/libc/gen/auth_subr.c lib/libc/gen/auth_subr.c index 1286a96fe40..32f86eda50f 100644 --- lib/libc/gen/auth_subr.c +++ lib/libc/gen/auth_subr.c @@ -752,7 +752,7 @@ auth_check_expire(auth_session_t *as) if (as->pwd && (quad_t)as->pwd->pw_expire != 0) { if (as->now.tv_sec == 0) - gettimeofday(&as->now, NULL); + WRAP(gettimeofday)(&as->now, NULL); if ((quad_t)as->now.tv_sec >= (quad_t)as->pwd->pw_expire) { as->state &= ~AUTH_ALLOW; as->state |= AUTH_EXPIRED; @@ -779,7 +779,7 @@ auth_check_change(auth_session_t *as) if (as->pwd && (quad_t)as->pwd->pw_change) { if (as->now.tv_sec == 0) - gettimeofday(&as->now, NULL); + WRAP(gettimeofday)(&as->now, NULL); if (as->now.tv_sec >= (quad_t)as->pwd->pw_change) { as->state &= ~AUTH_ALLOW; as->state |= AUTH_PWEXPIRED; diff --git lib/libc/gen/time.c lib/libc/gen/time.c index 3bbd0d733d1..b3ce9a800f1 100644 --- lib/libc/gen/time.c +++ lib/libc/gen/time.c @@ -36,7 +36,7 @@ time(time_t *t) { struct timeval tt; - if (gettimeofday(&tt, NULL) == -1) + if (WRAP(gettimeofday)(&tt, NULL) == -1) return (-1); if (t) *t = (time_t)tt.tv_sec; diff --git lib/libc/gen/times.c lib/libc/gen/times.c index 02e4dd44b5c..36841810d1b 100644 --- lib/libc/gen/times.c +++ lib/libc/gen/times.c @@ -52,7 +52,7 @@ times(struct tms *tp) return ((clock_t)-1); tp->tms_cutime = CONVTCK(ru.ru_utime); tp->tms_cstime = CONVTCK(ru.ru_stime); - if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1) + if (WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts) == -1) return ((clock_t)-1); return (ts.tv_sec * CLK_TCK + ts.tv_nsec / (1000000000 / CLK_TCK)); } diff --git lib/libc/gen/timespec_get.c lib/libc/gen/timespec_get.c index 520a5954025..845cbe80356 100644 --- lib/libc/gen/timespec_get.c +++ lib/libc/gen/timespec_get.c @@ -37,7 +37,7 @@ timespec_get(struct timespec *ts, int base) { switch (base) { case TIME_UTC: - if (clock_gettime(CLOCK_REALTIME, ts) == -1) + if (WRAP(clock_gettime)(CLOCK_REALTIME, ts) == -1) return 0; break; default: diff --git lib/libc/hidden/sys/time.h lib/libc/hidden/sys/time.h index ed112320fa2..df717021cab 100644 --- lib/libc/hidden/sys/time.h +++ lib/libc/hidden/sys/time.h @@ -24,7 +24,7 @@ PROTO_NORMAL(adjfreq); PROTO_NORMAL(adjtime); PROTO_NORMAL(futimes); PROTO_NORMAL(getitimer); -PROTO_NORMAL(gettimeofday); +PROTO_WRAP(gettimeofday); PROTO_NORMAL(setitimer); PROTO_NORMAL(settimeofday); PROTO_NORMAL(utimes); diff --git lib/libc/hidden/sys/timetc.h lib/libc/hidden/sys/timetc.h new file mode 100644 index 00000000000..d86b31e0d86 --- /dev/null +++ lib/libc/hidden/sys/timetc.h @@ -0,0 +1,38 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _LIBC_SYS_TIMETC_H_ +#define _LIBC_SYS_TIMETC_H_ + +#define _LIBC +#include <sys/types.h> +#include <sys/time.h> + +#include_next <sys/timetc.h> + +__BEGIN_HIDDEN_DECLS +extern void *_timekeep; + +extern int (*const _tc_get_timecount)(struct timekeep *, uint64_t *); + +int _microtime(struct timeval *, struct timekeep *); +int _nanotime(struct timespec *, struct timekeep *); +int _nanoruntime(struct timespec *, struct timekeep *); +int _nanouptime(struct timespec *, struct timekeep *); +__END_HIDDEN_DECLS + +#endif /* !_LIBC_SYS_TIMETC_H_ */ diff --git lib/libc/hidden/time.h lib/libc/hidden/time.h index 18c49f8fcb9..d8e1e0caf64 100644 --- lib/libc/hidden/time.h +++ lib/libc/hidden/time.h @@ -29,7 +29,7 @@ PROTO_NORMAL(asctime_r); PROTO_STD_DEPRECATED(clock); PROTO_DEPRECATED(clock_getcpuclockid); PROTO_NORMAL(clock_getres); -PROTO_NORMAL(clock_gettime); +PROTO_WRAP(clock_gettime); PROTO_NORMAL(clock_settime); PROTO_STD_DEPRECATED(ctime); PROTO_DEPRECATED(ctime_r); diff --git lib/libc/net/res_random.c lib/libc/net/res_random.c index 763e420bb88..9babb28470a 100644 --- lib/libc/net/res_random.c +++ lib/libc/net/res_random.c @@ -219,7 +219,7 @@ res_initid(void) if (ru_prf != NULL) arc4random_buf(ru_prf, sizeof(*ru_prf)); - clock_gettime(CLOCK_MONOTONIC, &ts); + WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts); ru_reseed = ts.tv_sec + RU_OUT; ru_msb = ru_msb == 0x8000 ? 0 : 0x8000; } @@ -232,7 +232,7 @@ __res_randomid(void) u_int r; static void *randomid_mutex; - clock_gettime(CLOCK_MONOTONIC, &ts); + WRAP(clock_gettime)(CLOCK_MONOTONIC, &ts); pid = getpid(); _MUTEX_LOCK(&randomid_mutex); diff --git lib/libc/rpc/auth_unix.c lib/libc/rpc/auth_unix.c index 402d98cede4..917a6d42b8a 100644 --- lib/libc/rpc/auth_unix.c +++ lib/libc/rpc/auth_unix.c @@ -121,7 +121,7 @@ authunix_create(char *machname, int uid, int gid, int len, int *aup_gids) /* * fill in param struct from the given params */ - (void)gettimeofday(&now, NULL); + (void)WRAP(gettimeofday)(&now, NULL); aup.aup_time = now.tv_sec; aup.aup_machname = machname; aup.aup_uid = uid; @@ -274,7 +274,7 @@ authunix_refresh(AUTH *auth) goto done; /* update the time and serialize in place */ - (void)gettimeofday(&now, NULL); + (void)WRAP(gettimeofday)(&now, NULL); aup.aup_time = now.tv_sec; xdrs.x_op = XDR_ENCODE; XDR_SETPOS(&xdrs, 0); diff --git lib/libc/rpc/clnt_tcp.c lib/libc/rpc/clnt_tcp.c index 8e6ef515b0e..927b4bf2028 100644 --- lib/libc/rpc/clnt_tcp.c +++ lib/libc/rpc/clnt_tcp.c @@ -393,12 +393,12 @@ readtcp(struct ct_data *ct, caddr_t buf, int len) pfd[0].events = POLLIN; TIMEVAL_TO_TIMESPEC(&ct->ct_wait, &wait); delta = wait; - clock_gettime(CLOCK_MONOTONIC, &start); + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start); for (;;) { r = ppoll(pfd, 1, &delta, NULL); save_errno = errno; - clock_gettime(CLOCK_MONOTONIC, &after); + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after); timespecsub(&start, &after, &duration); timespecsub(&wait, &duration, &delta); if (delta.tv_sec < 0 || !timespecisset(&delta)) diff --git lib/libc/rpc/clnt_udp.c lib/libc/rpc/clnt_udp.c index 68d01674410..92e1d5c350d 100644 --- lib/libc/rpc/clnt_udp.c +++ lib/libc/rpc/clnt_udp.c @@ -265,7 +265,7 @@ send_again: reply_msg.acpted_rply.ar_results.where = resultsp; reply_msg.acpted_rply.ar_results.proc = xresults; - clock_gettime(CLOCK_MONOTONIC, &start); + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start); for (;;) { switch (ppoll(pfd, 1, &wait, NULL)) { case 0: @@ -283,7 +283,7 @@ send_again: /* FALLTHROUGH */ case -1: if (errno == EINTR) { - clock_gettime(CLOCK_MONOTONIC, &after); + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after); timespecsub(&after, &start, &duration); timespecadd(&time_waited, &duration, &time_waited); if (timespeccmp(&time_waited, &timeout, <)) diff --git lib/libc/rpc/svc_tcp.c lib/libc/rpc/svc_tcp.c index f9d7a70938f..6c99db84359 100644 --- lib/libc/rpc/svc_tcp.c +++ lib/libc/rpc/svc_tcp.c @@ -342,7 +342,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len) * A timeout is fatal for the connection. */ delta = wait_per_try; - clock_gettime(CLOCK_MONOTONIC, &start); + WRAP(clock_gettime)(CLOCK_MONOTONIC, &start); pfd[0].fd = sock; pfd[0].events = POLLIN; do { @@ -351,7 +351,7 @@ readtcp(SVCXPRT *xprt, caddr_t buf, int len) case -1: if (errno != EINTR) goto fatal_err; - clock_gettime(CLOCK_MONOTONIC, &after); + WRAP(clock_gettime)(CLOCK_MONOTONIC, &after); timespecsub(&after, &start, &duration); timespecsub(&wait_per_try, &duration, &delta); if (delta.tv_sec < 0 || !timespecisset(&delta)) diff --git lib/libc/sys/Makefile.inc lib/libc/sys/Makefile.inc index 34769576ced..d57418d81bf 100644 --- lib/libc/sys/Makefile.inc +++ lib/libc/sys/Makefile.inc @@ -12,7 +12,8 @@ SRCS+= Ovfork.S brk.S ${CERROR} \ # glue to offer userland wrappers for some syscalls SRCS+= posix_madvise.c pthread_sigmask.c \ - w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c + w_fork.c w_sigaction.c w_sigprocmask.c w_sigsuspend.c w_vfork.c \ + w_clock_gettime.c w_gettimeofday.c microtime.c # glue for compat with old syscall interfaces. SRCS+= ftruncate.c lseek.c mquery.c mmap.c ptrace.c semctl.c truncate.c \ @@ -43,7 +44,7 @@ SRCS+= ${CANCEL:%=w_%.c} w_pread.c w_preadv.c w_pwrite.c w_pwritev.c ASM= __semctl.o __syscall.o __thrsigdivert.o \ access.o acct.o adjfreq.o adjtime.o \ bind.o chdir.o chflags.o chflagsat.o chmod.o chown.o chroot.o \ - clock_getres.o clock_gettime.o clock_settime.o \ + clock_getres.o clock_settime.o \ dup.o dup2.o dup3.o \ execve.o \ faccessat.o fchdir.o fchflags.o fchmod.o fchmodat.o fchown.o \ @@ -54,7 +55,7 @@ ASM= __semctl.o __syscall.o __thrsigdivert.o \ getgroups.o getitimer.o getpeername.o getpgid.o \ getpriority.o getresgid.o getresuid.o \ getrlimit.o getrusage.o getsid.o getsockname.o \ - getsockopt.o gettimeofday.o ioctl.o \ + getsockopt.o ioctl.o \ kevent.o kill.o kqueue.o ktrace.o lchown.o \ link.o linkat.o listen.o lstat.o madvise.o \ minherit.o mkdir.o mkdirat.o mkfifo.o mkfifoat.o \ @@ -109,7 +110,8 @@ PPSEUDO_NOERR=${PSEUDO_NOERR:.o=.po} SPSEUDO_NOERR=${PSEUDO_NOERR:.o=.so} DPSEUDO_NOERR=${PSEUDO_NOERR:.o=.do} -HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o ${CANCEL:=.o} +HIDDEN= ___realpath.o ___getcwd.o fork.o sigaction.o _ptrace.o ${CANCEL:=.o} \ + clock_gettime.o gettimeofday.o PHIDDEN=${HIDDEN:.o=.po} SHIDDEN=${HIDDEN:.o=.so} DHIDDEN=${HIDDEN:.o=.do} diff --git lib/libc/sys/microtime.c lib/libc/sys/microtime.c new file mode 100644 index 00000000000..fc023e8452f --- /dev/null +++ lib/libc/sys/microtime.c @@ -0,0 +1,180 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2000 Poul-Henning Kamp <p...@freebsd.org> + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> +#include <sys/atomic.h> +#include <sys/timetc.h> + +#include <time.h> + +/* + * Return the difference between the timehands' counter value now and what + * was when we copied it to the timehands' offset_count. + */ +static inline int +tc_delta(struct timekeep *tk, u_int *delta) +{ + uint64_t tc; + if (delta == NULL || _tc_get_timecount(tk, &tc)) + return -1; + *delta = (tc - tk->tk_offset_count) & tk->tk_counter_mask; + return 0; +} + +static inline void +bintimeaddfrac(const struct bintime *bt, uint64_t x, struct bintime *ct) +{ + ct->sec = bt->sec; + if (bt->frac > bt->frac + x) + ct->sec++; + ct->frac = bt->frac + x; +} + +static inline void +BINTIME_TO_TIMESPEC(const struct bintime *bt, struct timespec *ts) +{ + ts->tv_sec = bt->sec; + ts->tv_nsec = (long)(((uint64_t)1000000000 * (uint32_t)(bt->frac >> 32)) >> 32); +} + +static inline void +BINTIME_TO_TIMEVAL(const struct bintime *bt, struct timeval *tv) +{ + tv->tv_sec = bt->sec; + tv->tv_usec = (long)(((uint64_t)1000000 * (uint32_t)(bt->frac >> 32)) >> 32); +} + +static int +binuptime(struct bintime *bt, struct timekeep *tk) +{ + u_int gen, delta; + + do { + gen = tk->tk_generation; + membar_consumer(); + *bt = tk->tk_offset; + if (tc_delta(tk, &delta)) + return -1; + bintimeaddfrac(bt, tk->tk_scale * delta, bt); + membar_consumer(); + } while (gen == 0 || gen != tk->tk_generation); + + return 0; +} + +static inline void +bintimeadd(const struct bintime *bt, const struct bintime *ct, + struct bintime *dt) +{ + dt->sec = bt->sec + ct->sec; + if (bt->frac > bt->frac + ct->frac) + dt->sec++; + dt->frac = bt->frac + ct->frac; +} + +static inline void +bintimesub(const struct bintime *bt, const struct bintime *ct, + struct bintime *dt) +{ + dt->sec = bt->sec - ct->sec; + if (bt->frac < bt->frac - ct->frac) + dt->sec--; + dt->frac = bt->frac - ct->frac; +} + +static int +binruntime(struct bintime *bt, struct timekeep *tk) +{ + u_int gen, delta; + + do { + gen = tk->tk_generation; + membar_consumer(); + if (tc_delta(tk, &delta)) + return -1; + bintimeaddfrac(&tk->tk_offset, tk->tk_scale * delta, bt); + bintimesub(bt, &tk->tk_naptime, bt); + membar_consumer(); + } while (gen == 0 || gen != tk->tk_generation); + + return 0; +} + +static int +bintime(struct bintime *bt, struct timekeep *tk) +{ + u_int gen, delta; + + do { + gen = tk->tk_generation; + membar_consumer(); + *bt = tk->tk_offset; + if (tc_delta(tk, &delta)) + return -1; + bintimeaddfrac(bt, tk->tk_scale * delta, bt); + bintimeadd(bt, &tk->tk_boottime, bt); + membar_consumer(); + } while (gen == 0 || gen != tk->tk_generation); + + return 0; +} + +int +_microtime(struct timeval *tvp, struct timekeep *tk) +{ + struct bintime bt; + + if (bintime(&bt, tk)) + return -1; + BINTIME_TO_TIMEVAL(&bt, tvp); + return 0; +} + +int +_nanotime(struct timespec *tsp, struct timekeep *tk) +{ + struct bintime bt; + + if (bintime(&bt, tk)) + return -1; + BINTIME_TO_TIMESPEC(&bt, tsp); + return 0; +} + +int +_nanoruntime(struct timespec *ts, struct timekeep *tk) +{ + struct bintime bt; + + if (binruntime(&bt, tk)) + return -1; + BINTIME_TO_TIMESPEC(&bt, ts); + return 0; +} + + +int +_nanouptime(struct timespec *tsp, struct timekeep *tk) +{ + struct bintime bt; + + if (binuptime(&bt, tk)) + return -1; + BINTIME_TO_TIMESPEC(&bt, tsp); + return 0; +} diff --git lib/libc/sys/w_clock_gettime.c lib/libc/sys/w_clock_gettime.c new file mode 100644 index 00000000000..6e6478bd131 --- /dev/null +++ lib/libc/sys/w_clock_gettime.c @@ -0,0 +1,51 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/timetc.h> + +#include <time.h> + +int +WRAP(clock_gettime)(clockid_t clock_id, struct timespec *tp) +{ + int rc = 0; + struct timekeep *timekeep = _timekeep; + + if (timekeep == NULL || timekeep->tk_user == 0) + return clock_gettime(clock_id, tp); + + switch (clock_id) { + case CLOCK_REALTIME: + rc = _nanotime(tp, timekeep); + break; + case CLOCK_UPTIME: + rc = _nanoruntime(tp, timekeep); + break; + case CLOCK_MONOTONIC: + case CLOCK_BOOTTIME: + rc = _nanouptime(tp, timekeep); + break; + default: + return clock_gettime(clock_id, tp); + } + + if (rc) + return clock_gettime(clock_id, tp); + + return 0; +} +DEF_WRAP(clock_gettime); diff --git lib/libc/sys/w_gettimeofday.c lib/libc/sys/w_gettimeofday.c new file mode 100644 index 00000000000..f44edfbb1ad --- /dev/null +++ lib/libc/sys/w_gettimeofday.c @@ -0,0 +1,40 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Robert Nagy <rob...@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/timetc.h> + +int +WRAP(gettimeofday)(struct timeval *tp, struct timezone *tzp) +{ + int rc = 0; + struct timekeep *timekeep = _timekeep; + static struct timezone zerotz = { 0, 0 }; + + if (timekeep == NULL || timekeep->tk_user == 0) + return gettimeofday(tp, tzp); + + if (tp) + rc = _microtime(tp, timekeep); + if (rc) + return gettimeofday(tp, tzp); + + if (tzp) + *tzp = zerotz; + + return 0; +} +DEF_WRAP(gettimeofday); diff --git lib/libc/thread/synch.h lib/libc/thread/synch.h index 788890add89..df2239438d2 100644 --- lib/libc/thread/synch.h +++ lib/libc/thread/synch.h @@ -33,7 +33,7 @@ _twait(volatile uint32_t *p, int val, clockid_t clockid, const struct timespec * if (abs == NULL) return futex(p, FUTEX_WAIT_PRIVATE, val, NULL, NULL); - if (abs->tv_nsec >= 1000000000 || clock_gettime(clockid, &rel)) + if (abs->tv_nsec >= 1000000000 || WRAP(clock_gettime)(clockid, &rel)) return (EINVAL); rel.tv_sec = abs->tv_sec - rel.tv_sec; diff --git regress/lib/libc/timekeep/Makefile regress/lib/libc/timekeep/Makefile new file mode 100644 index 00000000000..a7f3080290d --- /dev/null +++ regress/lib/libc/timekeep/Makefile @@ -0,0 +1,5 @@ +# $OpenBSD$ + +PROGS= test_clock_gettime test_time_skew test_gettimeofday + +.include <bsd.regress.mk> diff --git regress/lib/libc/timekeep/test_clock_gettime.c regress/lib/libc/timekeep/test_clock_gettime.c new file mode 100644 index 00000000000..859ec368215 --- /dev/null +++ regress/lib/libc/timekeep/test_clock_gettime.c @@ -0,0 +1,43 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <assert.h> +#include <time.h> + +#define ASSERT_EQ(a, b) assert((a) == (b)) + +void +check() +{ + struct timespec tp = {0}; + + ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &tp)); + ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp)); + ASSERT_EQ(0, clock_gettime(CLOCK_BOOTTIME, &tp)); + ASSERT_EQ(0, clock_gettime(CLOCK_UPTIME, &tp)); + + + ASSERT_EQ(0, clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp)); + ASSERT_EQ(0, clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)); + +} + +int main() +{ + check(); + return 0; +} diff --git regress/lib/libc/timekeep/test_gettimeofday.c regress/lib/libc/timekeep/test_gettimeofday.c new file mode 100644 index 00000000000..ea90a1be7e0 --- /dev/null +++ regress/lib/libc/timekeep/test_gettimeofday.c @@ -0,0 +1,37 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <assert.h> +#include <sys/time.h> + +#define ASSERT_EQ(a, b) assert((a) == (b)) + +void +check() +{ + struct timeval tv = {0}; + struct timezone tzp; + + ASSERT_EQ(0, gettimeofday(&tv, NULL)); + ASSERT_EQ(0, gettimeofday(&tv, &tzp)); +} + +int main() +{ + check(); + return 0; +} diff --git regress/lib/libc/timekeep/test_time_skew.c regress/lib/libc/timekeep/test_time_skew.c new file mode 100644 index 00000000000..dfa9481c091 --- /dev/null +++ regress/lib/libc/timekeep/test_time_skew.c @@ -0,0 +1,55 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2020 Paul Irofti <p...@irofti.net> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/time.h> + +#include <assert.h> +#include <time.h> +#include <stdlib.h> +#include <stdio.h> + +#define ASSERT_EQ(a, b) assert((a) == (b)) +#define ASSERT_NE(a, b) assert((a) != (b)) + +void +check() +{ + struct timespec tp1, tp2, tout; + + tout.tv_sec = 0; + tout.tv_nsec = 100000; + + ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp1)); + + nanosleep(&tout, NULL); + + ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &tp2)); + + /* tp1 should never be larger than tp2 */ + ASSERT_NE(1, timespeccmp(&tp1, &tp2, >)); +} + +int +main(void) +{ + int i; + + for (i = 0; i < 1000; i++) + check(); + + return 0; +} diff --git sys/arch/alpha/alpha/clock.c sys/arch/alpha/alpha/clock.c index 3f5f2c5b42b..6eaf8b107c6 100644 --- sys/arch/alpha/alpha/clock.c +++ sys/arch/alpha/alpha/clock.c @@ -64,7 +64,7 @@ int clk_irq = 0; u_int rpcc_get_timecount(struct timecounter *); struct timecounter rpcc_timecounter = { - rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL + rpcc_get_timecount, NULL, ~0u, 0, "rpcc", 0, NULL, 0 }; extern todr_chip_handle_t todr_handle; diff --git sys/arch/alpha/alpha/machdep.c sys/arch/alpha/alpha/machdep.c index 09dc7e9cba5..9e43723959f 100644 --- sys/arch/alpha/alpha/machdep.c +++ sys/arch/alpha/alpha/machdep.c @@ -139,6 +139,9 @@ struct uvm_constraint_range *uvm_md_constraints[] = { struct vm_map *exec_map = NULL; struct vm_map *phys_map = NULL; +/* timekeep number of user accesible clocks */ +int tk_nclocks = 0; + /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. diff --git sys/arch/amd64/amd64/machdep.c sys/arch/amd64/amd64/machdep.c index 9dab8947af0..f58ab1a345c 100644 --- sys/arch/amd64/amd64/machdep.c +++ sys/arch/amd64/amd64/machdep.c @@ -193,6 +193,9 @@ int lid_action = 1; int pwr_action = 1; int forceukbd; +/* timekeep number of user accesible clocks */ +int tk_nclocks = 1; + /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. diff --git sys/arch/amd64/amd64/tsc.c sys/arch/amd64/amd64/tsc.c index 7a1dcb4ad75..3db93d88dec 100644 --- sys/arch/amd64/amd64/tsc.c +++ sys/arch/amd64/amd64/tsc.c @@ -50,7 +50,7 @@ extern u_int32_t lapic_per_second; #endif struct timecounter tsc_timecounter = { - tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL + tsc_get_timecount, NULL, ~0u, 0, "tsc", -1000, NULL, 1 }; uint64_t diff --git sys/arch/amd64/isa/clock.c sys/arch/amd64/isa/clock.c index 613f7ee0e0f..00da0c6a8d0 100644 --- sys/arch/amd64/isa/clock.c +++ sys/arch/amd64/isa/clock.c @@ -116,7 +116,7 @@ u_int i8254_get_timecount(struct timecounter *tc); u_int i8254_simple_get_timecount(struct timecounter *tc); static struct timecounter i8254_timecounter = { - i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL + i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0 }; int clockintr(void *); diff --git sys/arch/arm64/arm64/machdep.c sys/arch/arm64/arm64/machdep.c index 4e292479233..2b6165800ca 100644 --- sys/arch/arm64/arm64/machdep.c +++ sys/arch/arm64/arm64/machdep.c @@ -90,6 +90,9 @@ struct uvm_constraint_range *uvm_md_constraints[] = { /* the following is used externally (sysctl_hw) */ char machine[] = MACHINE; /* from <machine/param.h> */ +/* timekeep number of user accesible clocks */ +int tk_nclocks = 0; + int safepri = 0; struct cpu_info cpu_info_primary; diff --git sys/arch/arm64/dev/agtimer.c sys/arch/arm64/dev/agtimer.c index 29394141ad5..6b7c6db862f 100644 --- sys/arch/arm64/dev/agtimer.c +++ sys/arch/arm64/dev/agtimer.c @@ -43,7 +43,7 @@ int32_t agtimer_frequency = TIMER_FREQUENCY; u_int agtimer_get_timecount(struct timecounter *); static struct timecounter agtimer_timecounter = { - agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL + agtimer_get_timecount, NULL, 0x7fffffff, 0, "agtimer", 0, NULL, 0 }; struct agtimer_pcpu_softc { diff --git sys/arch/armv7/omap/gptimer.c sys/arch/armv7/omap/gptimer.c index 7605845d5e2..061542d532f 100644 --- sys/arch/armv7/omap/gptimer.c +++ sys/arch/armv7/omap/gptimer.c @@ -117,7 +117,7 @@ int gptimer_irq = 0; u_int gptimer_get_timecount(struct timecounter *); static struct timecounter gptimer_timecounter = { - gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL + gptimer_get_timecount, NULL, 0x7fffffff, 0, "gptimer", 0, NULL, 0 }; volatile u_int32_t nexttickevent; diff --git sys/arch/armv7/sunxi/sxitimer.c sys/arch/armv7/sunxi/sxitimer.c index 14a243c78d0..41028f9a602 100644 --- sys/arch/armv7/sunxi/sxitimer.c +++ sys/arch/armv7/sunxi/sxitimer.c @@ -89,7 +89,7 @@ void sxitimer_delay(u_int); u_int sxitimer_get_timecount(struct timecounter *); static struct timecounter sxitimer_timecounter = { - sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL + sxitimer_get_timecount, NULL, 0xffffffff, 0, "sxitimer", 0, NULL, 0 }; bus_space_tag_t sxitimer_iot; diff --git sys/arch/hppa/dev/clock.c sys/arch/hppa/dev/clock.c index 4c594ab5ec7..8cce6c3a893 100644 --- sys/arch/hppa/dev/clock.c +++ sys/arch/hppa/dev/clock.c @@ -47,7 +47,7 @@ int cpu_hardclock(void *); u_int itmr_get_timecount(struct timecounter *); struct timecounter itmr_timecounter = { - itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL + itmr_get_timecount, NULL, 0xffffffff, 0, "itmr", 0, NULL, 0 }; extern todr_chip_handle_t todr_handle; diff --git sys/arch/hppa/hppa/machdep.c sys/arch/hppa/hppa/machdep.c index f7bb998d53e..df356e5202f 100644 --- sys/arch/hppa/hppa/machdep.c +++ sys/arch/hppa/hppa/machdep.c @@ -152,6 +152,9 @@ void hpmc_dump(void); void cpuid(void); void blink_led_timeout(void *); +/* timekeep number of user accesible clocks */ +int tk_nclocks = 0; + /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. diff --git sys/arch/i386/i386/machdep.c sys/arch/i386/i386/machdep.c index 0d392c75802..c22eb22bafe 100644 --- sys/arch/i386/i386/machdep.c +++ sys/arch/i386/i386/machdep.c @@ -235,6 +235,9 @@ int lid_action = 1; int pwr_action = 1; int forceukbd; +/* timekeep number of user accesible clocks */ +int tk_nclocks = 0; + /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. diff --git sys/arch/i386/isa/clock.c sys/arch/i386/isa/clock.c index 09a6db983f2..dd74bd425ad 100644 --- sys/arch/i386/isa/clock.c +++ sys/arch/i386/isa/clock.c @@ -129,7 +129,7 @@ u_int i8254_get_timecount(struct timecounter *tc); u_int i8254_simple_get_timecount(struct timecounter *tc); static struct timecounter i8254_timecounter = { - i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL + i8254_get_timecount, NULL, ~0u, TIMER_FREQ, "i8254", 0, NULL, 0 }; struct mutex timer_mutex = MUTEX_INITIALIZER(IPL_HIGH); u_long rtclock_tval; diff --git sys/arch/i386/pci/geodesc.c sys/arch/i386/pci/geodesc.c index 9d9f061eef9..bb8e4c7f9ae 100644 --- sys/arch/i386/pci/geodesc.c +++ sys/arch/i386/pci/geodesc.c @@ -65,7 +65,9 @@ struct timecounter geodesc_timecounter = { 0xffffffff, /* counter_mask */ 27000000, /* frequency */ "GEOTSC", /* name */ - 2000 /* quality */ + 2000, /* quality */ + NULL, /* private bits */ + 0 /* expose to user */ }; int diff --git sys/arch/i386/pci/gscpm.c sys/arch/i386/pci/gscpm.c index 8b8aa4ac430..a6f324e66f3 100644 --- sys/arch/i386/pci/gscpm.c +++ sys/arch/i386/pci/gscpm.c @@ -55,7 +55,9 @@ struct timecounter gscpm_timecounter = { 0xffffff, /* counter_mask */ 3579545, /* frequency */ "GSCPM", /* name */ - 1000 /* quality */ + 1000, /* quality */ + NULL, /* private bits */ + 0 /* expose to user */ }; struct cfattach gscpm_ca = { diff --git sys/arch/i386/pci/ichpcib.c sys/arch/i386/pci/ichpcib.c index 6abf1627de2..629a86a14ff 100644 --- sys/arch/i386/pci/ichpcib.c +++ sys/arch/i386/pci/ichpcib.c @@ -63,7 +63,9 @@ struct timecounter ichpcib_timecounter = { 0xffffff, /* counter_mask */ 3579545, /* frequency */ "ICHPM", /* name */ - 1000 /* quality */ + 1000, /* quality */ + NULL, /* private bits */ + 0 /* expose to user */ }; struct cfattach ichpcib_ca = { diff --git sys/arch/landisk/landisk/machdep.c sys/arch/landisk/landisk/machdep.c index d5ea8df1740..3b515d191c9 100644 --- sys/arch/landisk/landisk/machdep.c +++ sys/arch/landisk/landisk/machdep.c @@ -119,6 +119,9 @@ extern u_int32_t getramsize(void); struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; +/* timekeep number of user accesible clocks */ +int tk_nclocks = 0; + /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. diff --git sys/arch/loongson/loongson/generic3a_machdep.c sys/arch/loongson/loongson/generic3a_machdep.c index ac3f1db6ccd..53489b07549 100644 --- sys/arch/loongson/loongson/generic3a_machdep.c +++ sys/arch/loongson/loongson/generic3a_machdep.c @@ -98,7 +98,9 @@ struct timecounter rs780e_timecounter = { .tc_counter_mask = 0xffffffffu, /* truncated to 32 bits */ .tc_frequency = HPET_FREQ, .tc_name = "hpet", - .tc_quality = 100 + .tc_quality = 100, + .tc_priv = NULL, + .tc_user = 0, }; /* Firmware entry points */ diff --git sys/arch/loongson/loongson/machdep.c sys/arch/loongson/loongson/machdep.c index aaceb54bea8..9c66faa4b50 100644 --- sys/arch/loongson/loongson/machdep.c +++ sys/arch/loongson/loongson/machdep.c @@ -103,6 +103,9 @@ struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; vm_map_t exec_map; vm_map_t phys_map; +/* timekeep number of user accesible clocks */ +int tk_nclocks = 0; + /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. diff --git sys/arch/luna88k/luna88k/clock.c sys/arch/luna88k/luna88k/clock.c index a04120987e0..6580a4a46bf 100644 --- sys/arch/luna88k/luna88k/clock.c +++ sys/arch/luna88k/luna88k/clock.c @@ -112,7 +112,9 @@ struct timecounter clock_tc = { .tc_counter_mask = 0xffffffff, .tc_frequency = 0, /* will be filled in */ .tc_name = "clock", - .tc_quality = 0 + .tc_quality = 0, + .tc_priv = NULL, + .tc_user = 0, }; /* diff --git sys/arch/luna88k/luna88k/machdep.c sys/arch/luna88k/luna88k/machdep.c index 9501ad85210..41bbe6793d4 100644 --- sys/arch/luna88k/luna88k/machdep.c +++ sys/arch/luna88k/luna88k/machdep.c @@ -193,6 +193,9 @@ int sysconsole = 1; /* 0 = ttya, 1 = keyboard/mouse, used in dev/sio.c */ u_int16_t dipswitch = 0; /* set in locore.S */ int hwplanebits; /* set in locore.S */ +/* timekeep number of user accesible clocks */ +int tk_nclocks = 0; + extern struct consdev syscons; /* in dev/siotty.c */ extern void syscnattach(int); /* in dev/siotty.c */ diff --git sys/arch/macppc/macppc/clock.c sys/arch/macppc/macppc/clock.c index 4a44a92cfc0..8c3ad620be8 100644 --- sys/arch/macppc/macppc/clock.c +++ sys/arch/macppc/macppc/clock.c @@ -57,7 +57,7 @@ u_int32_t ns_per_tick = 320; static int32_t ticks_per_intr; static struct timecounter tb_timecounter = { - tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL + tb_get_timecount, NULL, 0x7fffffff, 0, "tb", 0, NULL, 0 }; /* calibrate the timecounter frequency for the listed models */ diff --git sys/arch/macppc/macppc/machdep.c sys/arch/macppc/macppc/machdep.c index 178fe0995da..af4f68ed1d6 100644 --- sys/arch/macppc/macppc/machdep.c +++ sys/arch/macppc/macppc/machdep.c @@ -350,6 +350,9 @@ install_extint(void (*handler)(void)) ppc_mtmsr(omsr); } +/* timekeep number of user accesible clocks */ +int tk_nclocks = 0; + /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. diff --git sys/arch/mips64/mips64/mips64_machdep.c sys/arch/mips64/mips64/mips64_machdep.c index d4a42ed5acc..5c4dbadb5bb 100644 --- sys/arch/mips64/mips64/mips64_machdep.c +++ sys/arch/mips64/mips64/mips64_machdep.c @@ -327,7 +327,9 @@ struct timecounter cp0_timecounter = { 0xffffffff, /* counter_mask */ 0, /* frequency */ "CP0", /* name */ - 0 /* quality */ + 0, /* quality */ + NULL, /* private bits */ + 0, /* expose to user */ }; u_int diff --git sys/arch/octeon/octeon/machdep.c sys/arch/octeon/octeon/machdep.c index 1387af284ca..0cfabfc642a 100644 --- sys/arch/octeon/octeon/machdep.c +++ sys/arch/octeon/octeon/machdep.c @@ -107,6 +107,9 @@ struct boot_info *octeon_boot_info; void *octeon_fdt; unsigned int octeon_ver; +/* timekeep number of user accesible clocks */ +int tk_nclocks = 0; + /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. @@ -151,8 +154,9 @@ struct timecounter ioclock_timecounter = { .tc_name = "ioclock", .tc_quality = 0, /* ioclock can be overridden * by cp0 counter */ - .tc_priv = 0 /* clock register, + .tc_priv = 0, /* clock register, * determined at runtime */ + .tc_user = 0, /* expose to user */ }; static int diff --git sys/arch/powerpc64/powerpc64/machdep.c sys/arch/powerpc64/powerpc64/machdep.c index bae64a1f297..b00bf682b76 100644 --- sys/arch/powerpc64/powerpc64/machdep.c +++ sys/arch/powerpc64/powerpc64/machdep.c @@ -43,6 +43,9 @@ int cacheline_size = 128; struct uvm_constraint_range dma_constraint = { 0x0, (paddr_t)-1 }; struct uvm_constraint_range *uvm_md_constraints[] = { NULL }; +/* timekeep number of user accesible clocks */ +int tk_nclocks = 0; + int cold = 1; int safepri = 0; int physmem; diff --git sys/arch/sgi/sgi/ip27_machdep.c sys/arch/sgi/sgi/ip27_machdep.c index ba7fa558b96..2a2cc144242 100644 --- sys/arch/sgi/sgi/ip27_machdep.c +++ sys/arch/sgi/sgi/ip27_machdep.c @@ -111,7 +111,9 @@ struct timecounter ip27_hub_timecounter = { .tc_counter_mask = 0xffffffff, /* truncated to 32 bits. */ .tc_frequency = 1250000, .tc_name = "hubrt", - .tc_quality = 100 + .tc_quality = 100, + .tc_priv = 0, + .tc_user = 0, }; volatile uint64_t ip27_spinup_a0; diff --git sys/arch/sgi/sgi/machdep.c sys/arch/sgi/sgi/machdep.c index d251c15fc01..9b73112addf 100644 --- sys/arch/sgi/sgi/machdep.c +++ sys/arch/sgi/sgi/machdep.c @@ -93,6 +93,9 @@ struct uvm_constraint_range *uvm_md_constraints[] = { vm_map_t exec_map; vm_map_t phys_map; +/* timekeep number of user accesible clocks */ +int tk_nclocks = 0; + /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. diff --git sys/arch/sgi/xbow/xheart.c sys/arch/sgi/xbow/xheart.c index 56b29915c70..827775512ac 100644 --- sys/arch/sgi/xbow/xheart.c +++ sys/arch/sgi/xbow/xheart.c @@ -83,7 +83,9 @@ struct timecounter xheart_timecounter = { .tc_counter_mask = 0xffffffff, /* truncate 52-bit counter to 32-bit */ .tc_frequency = 12500000, .tc_name = "heart", - .tc_quality = 100 + .tc_quality = 100, + .tc_priv = NULL, + .tc_user = 0, }; extern uint32_t ip30_lights_frob(uint32_t, struct trapframe *); diff --git sys/arch/sparc64/dev/psycho.c sys/arch/sparc64/dev/psycho.c index e24f804dff6..1a7a1afa8c2 100644 --- sys/arch/sparc64/dev/psycho.c +++ sys/arch/sparc64/dev/psycho.c @@ -127,7 +127,7 @@ extern struct sparc_pci_chipset _sparc_pci_chipset; u_int stick_get_timecount(struct timecounter *); struct timecounter stick_timecounter = { - stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL + stick_get_timecount, NULL, ~0u, 0, "stick", 1000, NULL, 0 }; /* diff --git sys/arch/sparc64/sparc64/clock.c sys/arch/sparc64/sparc64/clock.c index fd5e8a9c15b..5c2e47d386b 100644 --- sys/arch/sparc64/sparc64/clock.c +++ sys/arch/sparc64/sparc64/clock.c @@ -109,13 +109,13 @@ struct cfdriver clock_cd = { u_int tick_get_timecount(struct timecounter *); struct timecounter tick_timecounter = { - tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL + tick_get_timecount, NULL, ~0u, 0, "tick", 0, NULL, 0 }; u_int sys_tick_get_timecount(struct timecounter *); struct timecounter sys_tick_timecounter = { - sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL + sys_tick_get_timecount, NULL, ~0u, 0, "sys_tick", 1000, NULL, 0 }; /* diff --git sys/arch/sparc64/sparc64/machdep.c sys/arch/sparc64/sparc64/machdep.c index 05aa4342943..0ee7ff3b802 100644 --- sys/arch/sparc64/sparc64/machdep.c +++ sys/arch/sparc64/sparc64/machdep.c @@ -183,6 +183,9 @@ extern int64_t cecclast; #define MAX_DMA_SEGS 20 #endif +/* timekeep number of user accesible clocks */ +int tk_nclocks = 0; + /* * safepri is a safe priority for sleep to set for a spin-wait * during autoconfiguration or after a panic. diff --git sys/dev/acpi/acpihpet.c sys/dev/acpi/acpihpet.c index d0ee72cec9b..13177a909da 100644 --- sys/dev/acpi/acpihpet.c +++ sys/dev/acpi/acpihpet.c @@ -45,7 +45,9 @@ static struct timecounter hpet_timecounter = { 0xffffffff, /* counter_mask (32 bits) */ 0, /* frequency */ 0, /* name */ - 1000 /* quality */ + 1000, /* quality */ + NULL, /* private bits */ + 0, /* expose to user */ }; #define HPET_TIMERS 3 diff --git sys/dev/acpi/acpitimer.c sys/dev/acpi/acpitimer.c index cdc8c99a17a..89b5a397e47 100644 --- sys/dev/acpi/acpitimer.c +++ sys/dev/acpi/acpitimer.c @@ -36,7 +36,9 @@ static struct timecounter acpi_timecounter = { 0x00ffffff, /* counter_mask (24 bits) */ ACPI_FREQUENCY, /* frequency */ 0, /* name */ - 1000 /* quality */ + 1000, /* quality */ + NULL, /* private bits */ + 0, /* expose to user */ }; struct acpitimer_softc { diff --git sys/dev/pci/amdpm.c sys/dev/pci/amdpm.c index 6df82858016..9610d5bc1f0 100644 --- sys/dev/pci/amdpm.c +++ sys/dev/pci/amdpm.c @@ -82,7 +82,9 @@ static struct timecounter amdpm_timecounter = { 0xffffff, /* counter_mask */ AMDPM_FREQUENCY, /* frequency */ "AMDPM", /* name */ - 1000 /* quality */ + 1000, /* quality */ + NULL, /* private bits */ + 0, /* expose to user */ }; #define AMDPM_CONFREG 0x40 diff --git sys/dev/pci/viapm.c sys/dev/pci/viapm.c index db806eedf80..ce33cd175e6 100644 --- sys/dev/pci/viapm.c +++ sys/dev/pci/viapm.c @@ -177,7 +177,9 @@ static struct timecounter viapm_timecounter = { 0xffffff, /* counter_mask */ VIAPM_FREQUENCY, /* frequency */ "VIAPM", /* name */ - 1000 /* quality */ + 1000, /* quality */ + NULL, /* private bits */ + 0, /* expose to user */ }; struct timeout viapm_timeout; diff --git sys/dev/pv/hyperv.c sys/dev/pv/hyperv.c index b32facdacb1..b9ee2feec4c 100644 --- sys/dev/pv/hyperv.c +++ sys/dev/pv/hyperv.c @@ -141,7 +141,7 @@ struct { }; struct timecounter hv_timecounter = { - hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001 + hv_gettime, 0, 0xffffffff, 10000000, "hyperv", 9001, NULL, 0 }; struct cfdriver hyperv_cd = { diff --git sys/dev/pv/pvclock.c sys/dev/pv/pvclock.c index 6b242f7448d..b80e4d2a484 100644 --- sys/dev/pv/pvclock.c +++ sys/dev/pv/pvclock.c @@ -74,7 +74,7 @@ struct cfdriver pvclock_cd = { }; struct timecounter pvclock_timecounter = { - pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL + pvclock_get_timecount, NULL, ~0u, 0, NULL, -2000, NULL, 0 }; int diff --git sys/kern/exec_elf.c sys/kern/exec_elf.c index 9b5b8eb3acf..59bc923a6fb 100644 --- sys/kern/exec_elf.c +++ sys/kern/exec_elf.c @@ -124,7 +124,7 @@ extern char *syscallnames[]; /* * How many entries are in the AuxInfo array we pass to the process? */ -#define ELF_AUX_ENTRIES 8 +#define ELF_AUX_ENTRIES 9 /* * This is the OpenBSD ELF emul @@ -860,6 +860,10 @@ exec_elf_fixup(struct proc *p, struct exec_package *epp) a->au_v = ap->arg_entry; a++; + a->au_id = AUX_openbsd_timekeep; + a->au_v = p->p_p->ps_timekeep; + a++; + a->au_id = AUX_null; a->au_v = 0; a++; diff --git sys/kern/kern_exec.c sys/kern/kern_exec.c index 20480c2fc28..9d6a3d9c910 100644 --- sys/kern/kern_exec.c +++ sys/kern/kern_exec.c @@ -64,6 +64,11 @@ #include <uvm/uvm_extern.h> #include <machine/tcb.h> +#include <sys/timetc.h> + +struct uvm_object *timekeep_object; +struct timekeep* timekeep; + void unveil_destroy(struct process *ps); const struct kmem_va_mode kv_exec = { @@ -76,6 +81,11 @@ const struct kmem_va_mode kv_exec = { */ int exec_sigcode_map(struct process *, struct emul *); +/* + * Map the shared timekeep page. + */ +int exec_timekeep_map(struct process *); + /* * If non-zero, stackgap_random specifies the upper limit of the random gap size * added to the fixed stack position. Must be n^2. @@ -684,6 +694,9 @@ sys_execve(struct proc *p, void *v, register_t *retval) /* map the process's signal trampoline code */ if (exec_sigcode_map(pr, pack.ep_emul)) goto free_pack_abort; + /* map the process's timekeep page */ + if (exec_timekeep_map(pr)) + goto free_pack_abort; #ifdef __HAVE_EXEC_MD_MAP /* perform md specific mappings that process might need */ @@ -863,3 +876,42 @@ exec_sigcode_map(struct process *pr, struct emul *e) return (0); } + +int +exec_timekeep_map(struct process *pr) +{ + size_t timekeep_sz = sizeof(struct timekeep); + + /* + * Similar to the sigcode object, except that there is a single timekeep + * object, and not one per emulation. + */ + if (timekeep_object == NULL) { + vaddr_t va; + + timekeep_object = uao_create(timekeep_sz, 0); + uao_reference(timekeep_object); + + if (uvm_map(kernel_map, &va, round_page(timekeep_sz), timekeep_object, + 0, 0, UVM_MAPFLAG(PROT_READ | PROT_WRITE, PROT_READ | PROT_WRITE, + MAP_INHERIT_SHARE, MADV_RANDOM, 0))) { + uao_detach(timekeep_object); + return (ENOMEM); + } + + timekeep = (struct timekeep *)va; + timekeep->tk_major = 0; + timekeep->tk_minor = 0; + timekeep->tk_nclocks = tk_nclocks; + } + + uao_reference(timekeep_object); + if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_timekeep, round_page(timekeep_sz), + timekeep_object, 0, 0, UVM_MAPFLAG(PROT_READ, PROT_READ, + MAP_INHERIT_COPY, MADV_RANDOM, 0))) { + uao_detach(timekeep_object); + return (ENOMEM); + } + + return (0); +} diff --git sys/kern/kern_tc.c sys/kern/kern_tc.c index 88d4a3379f9..47efbdd0b78 100644 --- sys/kern/kern_tc.c +++ sys/kern/kern_tc.c @@ -63,7 +63,7 @@ dummy_get_timecount(struct timecounter *tc) } static struct timecounter dummy_timecounter = { - dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000 + dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000, NULL, 0 }; /* @@ -479,6 +479,34 @@ tc_setclock(const struct timespec *ts) #endif } +void +tc_update_timekeep(void) +{ + static struct timecounter *last_tc = NULL; + struct timehands *th; + + if (timekeep == NULL) + return; + + th = timehands; + timekeep->tk_generation = 0; + membar_producer(); + timekeep->tk_scale = th->th_scale; + timekeep->tk_offset_count = th->th_offset_count; + timekeep->tk_offset = th->th_offset; + timekeep->tk_naptime = th->th_naptime; + timekeep->tk_boottime = th->th_boottime; + if (last_tc != th->th_counter) { + timekeep->tk_counter_mask = th->th_counter->tc_counter_mask; + timekeep->tk_user = th->th_counter->tc_user; + last_tc = th->th_counter; + } + membar_producer(); + timekeep->tk_generation = th->th_generation; + + return; +} + /* * Initialize the next struct timehands in the ring and make * it the active timehands. Along the way we might switch to a different @@ -631,6 +659,8 @@ tc_windup(struct bintime *new_boottime, struct bintime *new_offset, time_uptime = th->th_offset.sec; membar_producer(); timehands = th; + + tc_update_timekeep(); } /* Report or change the active timecounter hardware. */ diff --git sys/sys/exec_elf.h sys/sys/exec_elf.h index a40e0510273..3084ed595a6 100644 --- sys/sys/exec_elf.h +++ sys/sys/exec_elf.h @@ -691,7 +691,8 @@ enum AuxID { AUX_sun_uid = 2000, /* euid */ AUX_sun_ruid = 2001, /* ruid */ AUX_sun_gid = 2002, /* egid */ - AUX_sun_rgid = 2003 /* rgid */ + AUX_sun_rgid = 2003, /* rgid */ + AUX_openbsd_timekeep = 4000, /* userland clock_gettime */ }; struct elf_args { diff --git sys/sys/proc.h sys/sys/proc.h index 357c0c0d52c..c6d54572bdd 100644 --- sys/sys/proc.h +++ sys/sys/proc.h @@ -242,6 +242,7 @@ struct process { char ps_comm[MAXCOMLEN+1]; vaddr_t ps_strings; /* User pointers to argv/env */ + vaddr_t ps_timekeep; /* User pointer to timekeep */ vaddr_t ps_sigcode; /* User pointer to the signal code */ vaddr_t ps_sigcoderet; /* User pointer to sigreturn retPC */ u_long ps_sigcookie; diff --git sys/sys/time.h sys/sys/time.h index e758a64ce07..bcd3acd034d 100644 --- sys/sys/time.h +++ sys/sys/time.h @@ -163,7 +163,7 @@ struct clockinfo { }; #endif /* __BSD_VISIBLE */ -#if defined(_KERNEL) || defined(_STANDALONE) +#if defined(_KERNEL) || defined(_STANDALONE) || defined (_LIBC) #include <sys/_time.h> /* Time expressed as seconds and fractions of a second + operations on it. */ @@ -171,6 +171,9 @@ struct bintime { time_t sec; uint64_t frac; }; +#endif + +#if defined(_KERNEL) || defined(_STANDALONE) #define bintimecmp(btp, ctp, cmp) \ ((btp)->sec == (ctp)->sec ? \ diff --git sys/sys/timetc.h sys/sys/timetc.h index ce81c3475a0..a4a80eecff1 100644 --- sys/sys/timetc.h +++ sys/sys/timetc.h @@ -24,7 +24,7 @@ #ifndef _SYS_TIMETC_H_ #define _SYS_TIMETC_H_ -#ifndef _KERNEL +#if !defined(_KERNEL) && !defined(_LIBC) #error "no user-serviceable parts inside" #endif @@ -80,6 +80,8 @@ struct timecounter { */ void *tc_priv; /* [I] */ /* Pointer to the timecounter's private parts. */ + int tc_user; /* [I] */ + /* Expose this timecounter to userland. */ SLIST_ENTRY(timecounter) tc_next; /* [I] */ /* Pointer to the next timecounter. */ int64_t tc_freq_adj; /* [tw] */ @@ -88,11 +90,34 @@ struct timecounter { /* Precision of the counter. Computed in tc_init(). */ }; +struct timekeep { + /* set at initialization */ + uint32_t tk_major; /* version major number */ + uint32_t tk_minor; /* version minor number */ + int tk_nclocks; /* number of arch user clocks */ + + /* timehands members */ + uint64_t tk_scale; + u_int tk_offset_count; + struct bintime tk_offset; + struct bintime tk_naptime; + struct bintime tk_boottime; + volatile u_int tk_generation; + + /* timecounter members */ + int tk_user; + u_int tk_counter_mask; +}; +extern int tk_nclocks; + struct rwlock; extern struct rwlock tc_lock; extern struct timecounter *timecounter; +extern struct uvm_object *timekeep_object; +extern struct timekeep *timekeep; + u_int64_t tc_getfrequency(void); u_int64_t tc_getprecision(void); void tc_init(struct timecounter *tc);