1*6a72db4aSBryan Cantrill /* 2*6a72db4aSBryan Cantrill * This file and its contents are supplied under the terms of the 3*6a72db4aSBryan Cantrill * Common Development and Distribution License ("CDDL"), version 1.0. 4*6a72db4aSBryan Cantrill * You may only use this file in accordance with the terms of version 5*6a72db4aSBryan Cantrill * 1.0 of the CDDL. 6*6a72db4aSBryan Cantrill * 7*6a72db4aSBryan Cantrill * A full copy of the text of the CDDL should have accompanied this 8*6a72db4aSBryan Cantrill * source. A copy of the CDDL is also available via the Internet at 9*6a72db4aSBryan Cantrill * http://www.illumos.org/license/CDDL. 10*6a72db4aSBryan Cantrill */ 11*6a72db4aSBryan Cantrill 12*6a72db4aSBryan Cantrill /* 13*6a72db4aSBryan Cantrill * Copyright (c) 2015, Joyent, Inc. All rights reserved. 14*6a72db4aSBryan Cantrill */ 15*6a72db4aSBryan Cantrill 16*6a72db4aSBryan Cantrill #include <sys/timerfd.h> 17*6a72db4aSBryan Cantrill #include <sys/stat.h> 18*6a72db4aSBryan Cantrill #include <unistd.h> 19*6a72db4aSBryan Cantrill #include <errno.h> 20*6a72db4aSBryan Cantrill #include <fcntl.h> 21*6a72db4aSBryan Cantrill 22*6a72db4aSBryan Cantrill int 23*6a72db4aSBryan Cantrill timerfd_create(int clockid, int flags) 24*6a72db4aSBryan Cantrill { 25*6a72db4aSBryan Cantrill int oflags = O_RDWR; 26*6a72db4aSBryan Cantrill int fd; 27*6a72db4aSBryan Cantrill 28*6a72db4aSBryan Cantrill if (flags & ~(TFD_NONBLOCK | TFD_CLOEXEC)) { 29*6a72db4aSBryan Cantrill errno = EINVAL; 30*6a72db4aSBryan Cantrill return (-1); 31*6a72db4aSBryan Cantrill } 32*6a72db4aSBryan Cantrill 33*6a72db4aSBryan Cantrill if (flags & TFD_NONBLOCK) 34*6a72db4aSBryan Cantrill oflags |= O_NONBLOCK; 35*6a72db4aSBryan Cantrill 36*6a72db4aSBryan Cantrill if (flags & TFD_CLOEXEC) 37*6a72db4aSBryan Cantrill oflags |= O_CLOEXEC; 38*6a72db4aSBryan Cantrill 39*6a72db4aSBryan Cantrill if ((fd = open("/dev/timerfd", oflags)) < 0) 40*6a72db4aSBryan Cantrill return (-1); 41*6a72db4aSBryan Cantrill 42*6a72db4aSBryan Cantrill if (ioctl(fd, TIMERFDIOC_CREATE, clockid) != 0) { 43*6a72db4aSBryan Cantrill (void) close(fd); 44*6a72db4aSBryan Cantrill return (-1); 45*6a72db4aSBryan Cantrill } 46*6a72db4aSBryan Cantrill 47*6a72db4aSBryan Cantrill return (fd); 48*6a72db4aSBryan Cantrill } 49*6a72db4aSBryan Cantrill 50*6a72db4aSBryan Cantrill int 51*6a72db4aSBryan Cantrill timerfd_settime(int fd, int flags, const struct itimerspec *new_value, 52*6a72db4aSBryan Cantrill struct itimerspec *old_value) 53*6a72db4aSBryan Cantrill { 54*6a72db4aSBryan Cantrill timerfd_settime_t st; 55*6a72db4aSBryan Cantrill int rval; 56*6a72db4aSBryan Cantrill 57*6a72db4aSBryan Cantrill if (flags & ~(TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET)) { 58*6a72db4aSBryan Cantrill errno = EINVAL; 59*6a72db4aSBryan Cantrill return (-1); 60*6a72db4aSBryan Cantrill } 61*6a72db4aSBryan Cantrill 62*6a72db4aSBryan Cantrill st.tfd_settime_flags = flags; 63*6a72db4aSBryan Cantrill st.tfd_settime_value = (uint64_t)(uintptr_t)new_value; 64*6a72db4aSBryan Cantrill st.tfd_settime_ovalue = (uint64_t)(uintptr_t)old_value; 65*6a72db4aSBryan Cantrill 66*6a72db4aSBryan Cantrill rval = ioctl(fd, TIMERFDIOC_SETTIME, &st); 67*6a72db4aSBryan Cantrill 68*6a72db4aSBryan Cantrill if (rval == -1 && errno == ENOTTY) { 69*6a72db4aSBryan Cantrill /* 70*6a72db4aSBryan Cantrill * Linux has us return EINVAL when the file descriptor is valid 71*6a72db4aSBryan Cantrill * but is not a timerfd file descriptor -- and LTP explicitly 72*6a72db4aSBryan Cantrill * checks this case. 73*6a72db4aSBryan Cantrill */ 74*6a72db4aSBryan Cantrill errno = EINVAL; 75*6a72db4aSBryan Cantrill } 76*6a72db4aSBryan Cantrill 77*6a72db4aSBryan Cantrill return (rval); 78*6a72db4aSBryan Cantrill } 79*6a72db4aSBryan Cantrill 80*6a72db4aSBryan Cantrill int 81*6a72db4aSBryan Cantrill timerfd_gettime(int fd, struct itimerspec *curr_value) 82*6a72db4aSBryan Cantrill { 83*6a72db4aSBryan Cantrill int rval = ioctl(fd, TIMERFDIOC_GETTIME, curr_value); 84*6a72db4aSBryan Cantrill 85*6a72db4aSBryan Cantrill if (rval == -1 && errno == ENOTTY) { 86*6a72db4aSBryan Cantrill /* 87*6a72db4aSBryan Cantrill * See comment in timerfd_settime(), above. 88*6a72db4aSBryan Cantrill */ 89*6a72db4aSBryan Cantrill errno = EINVAL; 90*6a72db4aSBryan Cantrill } 91*6a72db4aSBryan Cantrill 92*6a72db4aSBryan Cantrill return (rval); 93*6a72db4aSBryan Cantrill } 94