Home | History | Annotate | Line # | Download | only in kern
subr_time.c revision 1.40
      1 /*	$NetBSD: subr_time.c,v 1.40 2024/12/22 23:18:47 riastradh Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1982, 1986, 1989, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  *
     31  *	@(#)kern_clock.c	8.5 (Berkeley) 1/21/94
     32  *	@(#)kern_time.c 8.4 (Berkeley) 5/26/95
     33  */
     34 
     35 #include <sys/cdefs.h>
     36 __KERNEL_RCSID(0, "$NetBSD: subr_time.c,v 1.40 2024/12/22 23:18:47 riastradh Exp $");
     37 
     38 #include <sys/param.h>
     39 #include <sys/types.h>
     40 
     41 #include <sys/intr.h>
     42 #include <sys/kauth.h>
     43 #include <sys/kernel.h>
     44 #include <sys/lwp.h>
     45 #include <sys/proc.h>
     46 #include <sys/time.h>
     47 #include <sys/timetc.h>
     48 #include <sys/timex.h>
     49 
     50 /*
     51  * Compute number of hz until specified time.  Used to compute second
     52  * argument to callout_reset() from an absolute time.
     53  */
     54 int
     55 tvhzto(const struct timeval *tvp)
     56 {
     57 	struct timeval now, tv;
     58 
     59 	tv = *tvp;	/* Don't modify original tvp. */
     60 	getmicrotime(&now);
     61 	timersub(&tv, &now, &tv);
     62 	return tvtohz(&tv);
     63 }
     64 
     65 /*
     66  * Compute number of ticks in the specified amount of time.
     67  */
     68 int
     69 tvtohz(const struct timeval *tv)
     70 {
     71 	unsigned long ticks;
     72 	long sec, usec;
     73 
     74 	/*
     75 	 * If the number of usecs in the whole seconds part of the time
     76 	 * difference fits in a long, then the total number of usecs will
     77 	 * fit in an unsigned long.  Compute the total and convert it to
     78 	 * ticks, rounding up and adding 1 to allow for the current tick
     79 	 * to expire.  Rounding also depends on unsigned long arithmetic
     80 	 * to avoid overflow.
     81 	 *
     82 	 * Otherwise, if the number of ticks in the whole seconds part of
     83 	 * the time difference fits in a long, then convert the parts to
     84 	 * ticks separately and add, using similar rounding methods and
     85 	 * overflow avoidance.  This method would work in the previous
     86 	 * case, but it is slightly slower and assumes that hz is integral.
     87 	 *
     88 	 * Otherwise, round the time difference down to the maximum
     89 	 * representable value.
     90 	 *
     91 	 * If ints are 32-bit, then the maximum value for any timeout in
     92 	 * 10ms ticks is 248 days.
     93 	 */
     94 	sec = tv->tv_sec;
     95 	usec = tv->tv_usec;
     96 
     97 	KASSERT(usec >= 0);
     98 	KASSERT(usec < 1000000);
     99 
    100 	/* catch overflows in conversion time_t->int */
    101 	if (tv->tv_sec > INT_MAX)
    102 		return INT_MAX;
    103 	if (tv->tv_sec < 0)
    104 		return 0;
    105 
    106 	if (sec < 0 || (sec == 0 && usec == 0)) {
    107 		/*
    108 		 * Would expire now or in the past.  Return 0 ticks.
    109 		 * This is different from the legacy tvhzto() interface,
    110 		 * and callers need to check for it.
    111 		 */
    112 		ticks = 0;
    113 	} else if (sec <= (LONG_MAX / 1000000))
    114 		ticks = (((sec * 1000000) + (unsigned long)usec + (tick - 1))
    115 		    / tick) + 1;
    116 	else if (sec <= (LONG_MAX / hz))
    117 		ticks = (sec * hz) +
    118 		    (((unsigned long)usec + (tick - 1)) / tick) + 1;
    119 	else
    120 		ticks = LONG_MAX;
    121 
    122 	if (ticks > INT_MAX)
    123 		ticks = INT_MAX;
    124 
    125 	return ((int)ticks);
    126 }
    127 
    128 int
    129 tshzto(const struct timespec *tsp)
    130 {
    131 	struct timespec now, ts;
    132 
    133 	ts = *tsp;	/* Don't modify original tsp. */
    134 	getnanotime(&now);
    135 	timespecsub(&ts, &now, &ts);
    136 	return tstohz(&ts);
    137 }
    138 
    139 int
    140 tshztoup(const struct timespec *tsp)
    141 {
    142 	struct timespec now, ts;
    143 
    144 	ts = *tsp;	/* Don't modify original tsp. */
    145 	getnanouptime(&now);
    146 	timespecsub(&ts, &now, &ts);
    147 	return tstohz(&ts);
    148 }
    149 
    150 /*
    151  * Compute number of ticks in the specified amount of time.
    152  */
    153 int
    154 tstohz(const struct timespec *ts)
    155 {
    156 	struct timeval tv;
    157 
    158 	/*
    159 	 * usec has great enough resolution for hz, so convert to a
    160 	 * timeval and use tvtohz() above.
    161 	 */
    162 	TIMESPEC_TO_TIMEVAL(&tv, ts);
    163 	return tvtohz(&tv);
    164 }
    165 
    166 /*
    167  * Check that a proposed value to load into the .it_value or
    168  * .it_interval part of an interval timer is acceptable, and
    169  * fix it to have at least minimal value (i.e. if it is less
    170  * than the resolution of the clock, round it up.). We don't
    171  * timeout the 0,0 value because this means to disable the
    172  * timer or the interval.
    173  */
    174 int
    175 itimerfix(struct timeval *tv)
    176 {
    177 
    178 	if (tv->tv_usec < 0 || tv->tv_usec >= 1000000)
    179 		return EINVAL;
    180 	if (tv->tv_sec < 0)
    181 		return ETIMEDOUT;
    182 	if (tv->tv_sec == 0 && tv->tv_usec != 0 && tv->tv_usec < tick)
    183 		tv->tv_usec = tick;
    184 	return 0;
    185 }
    186 
    187 int
    188 itimespecfix(struct timespec *ts)
    189 {
    190 
    191 	if (ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000)
    192 		return EINVAL;
    193 	if (ts->tv_sec < 0)
    194 		return ETIMEDOUT;
    195 	if (ts->tv_sec == 0 && ts->tv_nsec != 0 && ts->tv_nsec < tick * 1000)
    196 		ts->tv_nsec = tick * 1000;
    197 	return 0;
    198 }
    199 
    200 int
    201 inittimeleft(struct timespec *ts, struct timespec *sleepts)
    202 {
    203 
    204 	if (itimespecfix(ts)) {
    205 		return -1;
    206 	}
    207 	KASSERT(ts->tv_sec >= 0);
    208 	getnanouptime(sleepts);
    209 	return 0;
    210 }
    211 
    212 int
    213 gettimeleft(struct timespec *ts, struct timespec *sleepts)
    214 {
    215 	struct timespec now, sleptts;
    216 
    217 	KASSERT(ts->tv_sec >= 0);
    218 
    219 	/*
    220 	 * Reduce ts by elapsed time based on monotonic time scale.
    221 	 */
    222 	getnanouptime(&now);
    223 	KASSERT(timespeccmp(sleepts, &now, <=));
    224 	timespecsub(&now, sleepts, &sleptts);
    225 	*sleepts = now;
    226 
    227 	if (timespeccmp(ts, &sleptts, <=)) { /* timed out */
    228 		timespecclear(ts);
    229 		return 0;
    230 	}
    231 	timespecsub(ts, &sleptts, ts);
    232 
    233 	return tstohz(ts);
    234 }
    235 
    236 void
    237 clock_timeleft(clockid_t clockid, struct timespec *ts, struct timespec *sleepts)
    238 {
    239 	struct timespec sleptts;
    240 
    241 	clock_gettime1(clockid, &sleptts);
    242 	timespecadd(ts, sleepts, ts);
    243 	timespecsub(ts, &sleptts, ts);
    244 	*sleepts = sleptts;
    245 }
    246 
    247 int
    248 clock_gettime1(clockid_t clock_id, struct timespec *ts)
    249 {
    250 	int error;
    251 	struct proc *p;
    252 
    253 #define CPUCLOCK_ID_MASK (~(CLOCK_THREAD_CPUTIME_ID|CLOCK_PROCESS_CPUTIME_ID))
    254 	if (clock_id & CLOCK_PROCESS_CPUTIME_ID) {
    255 		pid_t pid = clock_id & CPUCLOCK_ID_MASK;
    256 		struct timeval cputime;
    257 
    258 		mutex_enter(&proc_lock);
    259 		p = pid == 0 ? curproc : proc_find(pid);
    260 		if (p == NULL) {
    261 			mutex_exit(&proc_lock);
    262 			return ESRCH;
    263 		}
    264 		mutex_enter(p->p_lock);
    265 		calcru(p, /*usertime*/NULL, /*systime*/NULL, /*intrtime*/NULL,
    266 		    &cputime);
    267 		mutex_exit(p->p_lock);
    268 		mutex_exit(&proc_lock);
    269 
    270 		// XXX: Perhaps create a special kauth type
    271 		error = kauth_authorize_process(kauth_cred_get(),
    272 		    KAUTH_PROCESS_PTRACE, p,
    273 		    KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
    274 		if (error)
    275 			return error;
    276 
    277 		TIMEVAL_TO_TIMESPEC(&cputime, ts);
    278 		return 0;
    279 	} else if (clock_id & CLOCK_THREAD_CPUTIME_ID) {
    280 		struct lwp *l;
    281 		lwpid_t lid = clock_id & CPUCLOCK_ID_MASK;
    282 		struct bintime tm = {0, 0};
    283 
    284 		p = curproc;
    285 		mutex_enter(p->p_lock);
    286 		l = lid == 0 ? curlwp : lwp_find(p, lid);
    287 		if (l == NULL) {
    288 			mutex_exit(p->p_lock);
    289 			return ESRCH;
    290 		}
    291 		addrulwp(l, &tm);
    292 		mutex_exit(p->p_lock);
    293 
    294 		bintime2timespec(&tm, ts);
    295 		return 0;
    296 	}
    297 
    298 	switch (clock_id) {
    299 	case CLOCK_REALTIME:
    300 		nanotime(ts);
    301 		break;
    302 	case CLOCK_MONOTONIC:
    303 		nanouptime(ts);
    304 		break;
    305 	default:
    306 		return EINVAL;
    307 	}
    308 
    309 	return 0;
    310 }
    311 
    312 /*
    313  * Calculate delta and convert from struct timespec to the ticks.
    314  */
    315 int
    316 ts2timo(clockid_t clock_id, int flags, struct timespec *ts,
    317     int *timo, struct timespec *start)
    318 {
    319 	int error;
    320 	struct timespec tsd;
    321 
    322 	if (ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000L)
    323 		return EINVAL;
    324 
    325 	if ((flags & TIMER_ABSTIME) != 0 || start != NULL) {
    326 		error = clock_gettime1(clock_id, &tsd);
    327 		if (error != 0)
    328 			return error;
    329 		if (start != NULL)
    330 			*start = tsd;
    331 	}
    332 
    333 	if ((flags & TIMER_ABSTIME) != 0) {
    334 		if (!timespecsubok(ts, &tsd))
    335 			return EINVAL;
    336 		timespecsub(ts, &tsd, &tsd);
    337 		ts = &tsd;
    338 	}
    339 
    340 	error = itimespecfix(ts);
    341 	if (error != 0)
    342 		return error;
    343 
    344 	if (ts->tv_sec == 0 && ts->tv_nsec == 0)
    345 		return ETIMEDOUT;
    346 
    347 	*timo = tstohz(ts);
    348 	KASSERT(*timo > 0);
    349 
    350 	return 0;
    351 }
    352 
    353 bool
    354 timespecaddok(const struct timespec *tsp, const struct timespec *usp)
    355 {
    356 	enum { TIME_MIN = __type_min(time_t), TIME_MAX = __type_max(time_t) };
    357 	time_t a = tsp->tv_sec;
    358 	time_t b = usp->tv_sec;
    359 	bool carry;
    360 
    361 	/*
    362 	 * Caller is responsible for guaranteeing valid timespec
    363 	 * inputs.  Any user-controlled inputs must be validated or
    364 	 * adjusted.
    365 	 */
    366 	KASSERT(tsp->tv_nsec >= 0);
    367 	KASSERT(usp->tv_nsec >= 0);
    368 	KASSERT(tsp->tv_nsec < 1000000000L);
    369 	KASSERT(usp->tv_nsec < 1000000000L);
    370 	CTASSERT(1000000000L <= __type_max(long) - 1000000000L);
    371 
    372 	/*
    373 	 * Fail if a + b + carry overflows TIME_MAX, or if a + b
    374 	 * overflows TIME_MIN because timespecadd adds the carry after
    375 	 * computing a + b.
    376 	 *
    377 	 * Break it into two mutually exclusive and exhaustive cases:
    378 	 * I. a >= 0
    379 	 * II. a < 0
    380 	 */
    381 	carry = (tsp->tv_nsec + usp->tv_nsec >= 1000000000L);
    382 	if (a >= 0) {
    383 		/*
    384 		 * Case I: a >= 0.  If b < 0, then b + 1 <= 0, so
    385 		 *
    386 		 *	a + b + 1 <= a + 0 <= TIME_MAX,
    387 		 *
    388 		 * and
    389 		 *
    390 		 *	a + b >= 0 + b = b >= TIME_MIN,
    391 		 *
    392 		 * so this can't overflow.
    393 		 *
    394 		 * If b >= 0, then a + b + carry >= a + b >= 0, so
    395 		 * negative results and thus results below TIME_MIN are
    396 		 * impossible; we need only avoid
    397 		 *
    398 		 *	a + b + carry > TIME_MAX,
    399 		 *
    400 		 * which we will do by rejecting if
    401 		 *
    402 		 *	b > TIME_MAX - a - carry,
    403 		 *
    404 		 * which in turn is incidentally always false if b < 0
    405 		 * so we don't need extra logic to discriminate on the
    406 		 * b >= 0 and b < 0 cases.
    407 		 *
    408 		 * Since 0 <= a <= TIME_MAX, we know
    409 		 *
    410 		 *	0 <= TIME_MAX - a <= TIME_MAX,
    411 		 *
    412 		 * and hence
    413 		 *
    414 		 *	-1 <= TIME_MAX - a - 1 < TIME_MAX.
    415 		 *
    416 		 * So we can compute TIME_MAX - a - carry (i.e., either
    417 		 * TIME_MAX - a or TIME_MAX - a - 1) safely without
    418 		 * overflow.
    419 		 */
    420 		if (b > TIME_MAX - a - carry)
    421 			return false;
    422 	} else {
    423 		/*
    424 		 * Case II: a < 0.  If b >= 0, then since a + 1 <= 0,
    425 		 * we have
    426 		 *
    427 		 *	a + b + 1 <= b <= TIME_MAX,
    428 		 *
    429 		 * and
    430 		 *
    431 		 *	a + b >= a >= TIME_MIN,
    432 		 *
    433 		 * so this can't overflow.
    434 		 *
    435 		 * If b < 0, then the intermediate a + b is negative
    436 		 * and the outcome a + b + 1 is nonpositive, so we need
    437 		 * only avoid
    438 		 *
    439 		 *	a + b < TIME_MIN,
    440 		 *
    441 		 * which we will do by rejecting if
    442 		 *
    443 		 *	a < TIME_MIN - b.
    444 		 *
    445 		 * (Reminder: The carry is added afterward in
    446 		 * timespecadd, so to avoid overflow it is not enough
    447 		 * to merely reject a + b + carry < TIME_MIN.)
    448 		 *
    449 		 * It is safe to compute the difference TIME_MIN - b
    450 		 * because b is negative, so the result lies in
    451 		 * (TIME_MIN, 0].
    452 		 */
    453 		if (b < 0 && a < TIME_MIN - b)
    454 			return false;
    455 	}
    456 
    457 	return true;
    458 }
    459 
    460 bool
    461 timespecsubok(const struct timespec *tsp, const struct timespec *usp)
    462 {
    463 	enum { TIME_MIN = __type_min(time_t), TIME_MAX = __type_max(time_t) };
    464 	time_t a = tsp->tv_sec, b = usp->tv_sec;
    465 	bool borrow;
    466 
    467 	/*
    468 	 * Caller is responsible for guaranteeing valid timespec
    469 	 * inputs.  Any user-controlled inputs must be validated or
    470 	 * adjusted.
    471 	 */
    472 	KASSERT(tsp->tv_nsec >= 0);
    473 	KASSERT(usp->tv_nsec >= 0);
    474 	KASSERT(tsp->tv_nsec < 1000000000L);
    475 	KASSERT(usp->tv_nsec < 1000000000L);
    476 	CTASSERT(1000000000L <= __type_max(long) - 1000000000L);
    477 
    478 	/*
    479 	 * Fail if a - b - borrow overflows TIME_MIN, or if a - b
    480 	 * overflows TIME_MAX because timespecsub subtracts the borrow
    481 	 * after computing a - b.
    482 	 *
    483 	 * Break it into two mutually exclusive and exhaustive cases:
    484 	 * I. a < 0
    485 	 * II. a >= 0
    486 	 */
    487 	borrow = (tsp->tv_nsec - usp->tv_nsec < 0);
    488 	if (a < 0) {
    489 		/*
    490 		 * Case I: a < 0.  If b < 0, then -b - 1 >= 0, so
    491 		 *
    492 		 *	a - b - 1 >= a + 0 >= TIME_MIN,
    493 		 *
    494 		 * and, since a <= -1, provided that TIME_MIN <=
    495 		 * -TIME_MAX - 1 so that TIME_MAX <= -TIME_MIN - 1 (in
    496 		 * fact, equality holds, under the assumption of
    497 		 * two's-complement arithmetic),
    498 		 *
    499 		 *	a - b <= -1 - b = -b - 1 <= TIME_MAX,
    500 		 *
    501 		 * so this can't overflow.
    502 		 */
    503 		CTASSERT(TIME_MIN <= -TIME_MAX - 1);
    504 
    505 		/*
    506 		 * If b >= 0, then a - b - borrow <= a - b < 0, so
    507 		 * positive results and thus results above TIME_MAX are
    508 		 * impossible; we need only avoid
    509 		 *
    510 		 *	a - b - borrow < TIME_MIN,
    511 		 *
    512 		 * which we will do by rejecting if
    513 		 *
    514 		 *	a < TIME_MIN + b + borrow.
    515 		 *
    516 		 * The right-hand side is safe to evaluate for any
    517 		 * values of b and borrow as long as TIME_MIN +
    518 		 * TIME_MAX + 1 <= TIME_MAX, i.e., TIME_MIN <= -1.
    519 		 * (Note: If time_t were unsigned, this would fail!)
    520 		 *
    521 		 * Note: Unlike Case I in timespecaddok, this criterion
    522 		 * does not work for b < 0, nor can the roles of a and
    523 		 * b in the inequality be reversed (e.g., -b < TIME_MIN
    524 		 * - a + borrow) without extra cases like checking for
    525 		 * b = TEST_MIN.
    526 		 */
    527 		CTASSERT(TIME_MIN < -1);
    528 		if (b >= 0 && a < TIME_MIN + b + borrow)
    529 			return false;
    530 	} else {
    531 		/*
    532 		 * Case II: a >= 0.  If b >= 0, then
    533 		 *
    534 		 *	a - b <= a <= TIME_MAX,
    535 		 *
    536 		 * and, provided TIME_MIN <= -TIME_MAX - 1 (in fact,
    537 		 * equality holds, under the assumption of
    538 		 * two's-complement arithmetic)
    539 		 *
    540 		 *	a - b - 1 >= -b - 1 >= -TIME_MAX - 1 >= TIME_MIN,
    541 		 *
    542 		 * so this can't overflow.
    543 		 */
    544 		CTASSERT(TIME_MIN <= -TIME_MAX - 1);
    545 
    546 		/*
    547 		 * If b < 0, then a - b >= a >= 0, so negative results
    548 		 * and thus results below TIME_MIN are impossible; we
    549 		 * need only avoid
    550 		 *
    551 		 *	a - b > TIME_MAX,
    552 		 *
    553 		 * which we will do by rejecting if
    554 		 *
    555 		 *	a > TIME_MAX + b.
    556 		 *
    557 		 * (Reminder: The borrow is subtracted afterward in
    558 		 * timespecsub, so to avoid overflow it is not enough
    559 		 * to merely reject a - b - borrow > TIME_MAX.)
    560 		 *
    561 		 * It is safe to compute the sum TIME_MAX + b because b
    562 		 * is negative, so the result lies in [0, TIME_MAX).
    563 		 */
    564 		if (b < 0 && a > TIME_MAX + b)
    565 			return false;
    566 	}
    567 
    568 	return true;
    569 }
    570