Branch data Line data Source code
1 : : /* 2 : : * Copyright (c) 2018 Friedt Professional Engineering Services, Inc 3 : : * 4 : : * SPDX-License-Identifier: Apache-2.0 5 : : */ 6 : : 7 : : #include <stdint.h> 8 : : #include <kernel.h> 9 : : #include <limits.h> 10 : : #include <errno.h> 11 : : /* required for struct timespec */ 12 : : #include <posix/time.h> 13 : : #include <sys/util.h> 14 : : #include <sys_clock.h> 15 : : 16 : : /** 17 : : * @brief Suspend execution for nanosecond intervals. 18 : : * 19 : : * See IEEE 1003.1 20 : : */ 21 : 0 : int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) 22 : : { 23 : : uint64_t ns; 24 : : uint64_t us; 25 : 0 : const bool update_rmtp = rmtp != NULL; 26 : : 27 [ # # ]: 0 : if (rqtp == NULL) { 28 : 0 : errno = EFAULT; 29 : 0 : return -1; 30 : : } 31 : : 32 [ # # # # ]: 0 : if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 33 [ # # ]: 0 : || rqtp->tv_nsec >= NSEC_PER_SEC) { 34 : 0 : errno = EINVAL; 35 : 0 : return -1; 36 : : } 37 : : 38 [ # # # # ]: 0 : if (rqtp->tv_sec == 0 && rqtp->tv_nsec == 0) { 39 : 0 : goto do_rmtp_update; 40 : : } 41 : : 42 [ # # ]: 0 : if (unlikely(rqtp->tv_sec >= ULLONG_MAX / NSEC_PER_SEC)) { 43 : : /* If a user passes this in, we could be here a while, but 44 : : * at least it's technically correct-ish 45 : : */ 46 : 0 : ns = rqtp->tv_nsec + NSEC_PER_SEC 47 [ # # ]: 0 : + k_sleep(K_SECONDS(rqtp->tv_sec - 1)) * NSEC_PER_MSEC; 48 : : } else { 49 : 0 : ns = rqtp->tv_sec * NSEC_PER_SEC + rqtp->tv_nsec; 50 : : } 51 : : 52 : : /* TODO: improve upper bound when hr timers are available */ 53 : 0 : us = ceiling_fraction(ns, NSEC_PER_USEC); 54 : : do { 55 : 0 : us = k_usleep(us); 56 [ # # ]: 0 : } while (us != 0); 57 : : 58 : 0 : do_rmtp_update: 59 [ # # ]: 0 : if (update_rmtp) { 60 : 0 : rmtp->tv_sec = 0; 61 : 0 : rmtp->tv_nsec = 0; 62 : : } 63 : : 64 : 0 : return 0; 65 : : }