cloudabi_clock.c revision 316327
1/*- 2 * Copyright (c) 2015 Nuxi, https://nuxi.nl/ 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26#include <sys/cdefs.h> 27__FBSDID("$FreeBSD: stable/11/sys/compat/cloudabi/cloudabi_clock.c 316327 2017-03-31 08:43:07Z ed $"); 28 29#include <sys/param.h> 30#include <sys/proc.h> 31#include <sys/stdint.h> 32#include <sys/systm.h> 33#include <sys/syscallsubr.h> 34 35#include <contrib/cloudabi/cloudabi_types_common.h> 36 37#include <compat/cloudabi/cloudabi_proto.h> 38#include <compat/cloudabi/cloudabi_util.h> 39 40/* Converts a CloudABI clock ID to a FreeBSD clock ID. */ 41static int 42cloudabi_convert_clockid(cloudabi_clockid_t in, clockid_t *out) 43{ 44 switch (in) { 45 case CLOUDABI_CLOCK_MONOTONIC: 46 *out = CLOCK_MONOTONIC; 47 return (0); 48 case CLOUDABI_CLOCK_PROCESS_CPUTIME_ID: 49 *out = CLOCK_PROCESS_CPUTIME_ID; 50 return (0); 51 case CLOUDABI_CLOCK_REALTIME: 52 *out = CLOCK_REALTIME; 53 return (0); 54 case CLOUDABI_CLOCK_THREAD_CPUTIME_ID: 55 *out = CLOCK_THREAD_CPUTIME_ID; 56 return (0); 57 default: 58 return (EINVAL); 59 } 60} 61 62/* Converts a struct timespec to a CloudABI timestamp. */ 63int 64cloudabi_convert_timespec(const struct timespec *in, cloudabi_timestamp_t *out) 65{ 66 cloudabi_timestamp_t s, ns; 67 68 if (in->tv_sec < 0) { 69 /* Timestamps from before the Epoch cannot be expressed. */ 70 *out = 0; 71 return (EOVERFLOW); 72 } 73 s = in->tv_sec; 74 ns = in->tv_nsec; 75 if (s > UINT64_MAX / 1000000000 || 76 (s == UINT64_MAX / 1000000000 && ns > UINT64_MAX % 1000000000)) { 77 /* Addition of seconds and nanoseconds would overflow. */ 78 *out = UINT64_MAX; 79 return (EOVERFLOW); 80 } 81 *out = s * 1000000000 + ns; 82 return (0); 83} 84 85/* Fetches the time value of a clock. */ 86int 87cloudabi_clock_time_get(struct thread *td, cloudabi_clockid_t clock_id, 88 cloudabi_timestamp_t *ret) 89{ 90 struct timespec ts; 91 int error; 92 clockid_t clockid; 93 94 error = cloudabi_convert_clockid(clock_id, &clockid); 95 if (error != 0) 96 return (error); 97 error = kern_clock_gettime(td, clockid, &ts); 98 if (error != 0) 99 return (error); 100 return (cloudabi_convert_timespec(&ts, ret)); 101} 102 103int 104cloudabi_sys_clock_res_get(struct thread *td, 105 struct cloudabi_sys_clock_res_get_args *uap) 106{ 107 struct timespec ts; 108 cloudabi_timestamp_t cts; 109 int error; 110 clockid_t clockid; 111 112 error = cloudabi_convert_clockid(uap->clock_id, &clockid); 113 if (error != 0) 114 return (error); 115 error = kern_clock_getres(td, clockid, &ts); 116 if (error != 0) 117 return (error); 118 error = cloudabi_convert_timespec(&ts, &cts); 119 if (error != 0) 120 return (error); 121 memcpy(td->td_retval, &cts, sizeof(cts)); 122 return (0); 123} 124 125int 126cloudabi_sys_clock_time_get(struct thread *td, 127 struct cloudabi_sys_clock_time_get_args *uap) 128{ 129 cloudabi_timestamp_t ts; 130 int error; 131 132 error = cloudabi_clock_time_get(td, uap->clock_id, &ts); 133 memcpy(td->td_retval, &ts, sizeof(ts)); 134 return (error); 135} 136