19ea3e141SMark Johnston /*- 29ea3e141SMark Johnston * Copyright (c) 2017 Mark Johnston <[email protected]> 39ea3e141SMark Johnston * 49ea3e141SMark Johnston * Redistribution and use in source and binary forms, with or without 59ea3e141SMark Johnston * modification, are permitted provided that the following conditions 69ea3e141SMark Johnston * are met: 79ea3e141SMark Johnston * 1. Redistributions of source code must retain the above copyright 89ea3e141SMark Johnston * notice unmodified, this list of conditions, and the following 99ea3e141SMark Johnston * disclaimer. 109ea3e141SMark Johnston * 2. Redistributions in binary form must reproduce the above copyright 119ea3e141SMark Johnston * notice, this list of conditions and the following disclaimer in the 129ea3e141SMark Johnston * documentation and/or other materials provided with the distribution. 139ea3e141SMark Johnston * 149ea3e141SMark Johnston * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 159ea3e141SMark Johnston * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 169ea3e141SMark Johnston * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 179ea3e141SMark Johnston * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 189ea3e141SMark Johnston * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 199ea3e141SMark Johnston * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 209ea3e141SMark Johnston * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 219ea3e141SMark Johnston * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 229ea3e141SMark Johnston * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 239ea3e141SMark Johnston * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 249ea3e141SMark Johnston */ 259ea3e141SMark Johnston 269ea3e141SMark Johnston #include <sys/cdefs.h> 279ea3e141SMark Johnston __FBSDID("$FreeBSD$"); 289ea3e141SMark Johnston 299ea3e141SMark Johnston #include <sys/param.h> 309ea3e141SMark Johnston #include <sys/systm.h> 319ea3e141SMark Johnston #include <sys/lock.h> 329ea3e141SMark Johnston #include <sys/mutex.h> 339ea3e141SMark Johnston #include <sys/time.h> 349ea3e141SMark Johnston 359ea3e141SMark Johnston #include <machine/cpu.h> 369ea3e141SMark Johnston 379ea3e141SMark Johnston #include <linux/hrtimer.h> 389ea3e141SMark Johnston 399ea3e141SMark Johnston static void 409ea3e141SMark Johnston hrtimer_call_handler(void *arg) 419ea3e141SMark Johnston { 429ea3e141SMark Johnston struct hrtimer *hrtimer; 439ea3e141SMark Johnston enum hrtimer_restart ret; 449ea3e141SMark Johnston 459ea3e141SMark Johnston hrtimer = arg; 469ea3e141SMark Johnston ret = hrtimer->function(hrtimer); 47*0a854962SHans Petter Selasky 48*0a854962SHans Petter Selasky if (ret == HRTIMER_RESTART) { 49*0a854962SHans Petter Selasky callout_schedule_sbt(&hrtimer->callout, 50*0a854962SHans Petter Selasky nstosbt(hrtimer->expires), nstosbt(hrtimer->precision), 0); 51*0a854962SHans Petter Selasky } else { 52e1cf70fbSAlexander Motin callout_deactivate(&hrtimer->callout); 539ea3e141SMark Johnston } 54*0a854962SHans Petter Selasky } 559ea3e141SMark Johnston 569ea3e141SMark Johnston bool 579ea3e141SMark Johnston linux_hrtimer_active(struct hrtimer *hrtimer) 589ea3e141SMark Johnston { 599ea3e141SMark Johnston bool ret; 609ea3e141SMark Johnston 619ea3e141SMark Johnston mtx_lock(&hrtimer->mtx); 62e1cf70fbSAlexander Motin ret = callout_active(&hrtimer->callout); 639ea3e141SMark Johnston mtx_unlock(&hrtimer->mtx); 64*0a854962SHans Petter Selasky 659ea3e141SMark Johnston return (ret); 669ea3e141SMark Johnston } 679ea3e141SMark Johnston 68e1cf70fbSAlexander Motin /* 69e1cf70fbSAlexander Motin * Cancel active hrtimer. 70e1cf70fbSAlexander Motin * Return 1 if timer was active and cancellation succeeded, or 0 otherwise. 71e1cf70fbSAlexander Motin */ 729ea3e141SMark Johnston int 739ea3e141SMark Johnston linux_hrtimer_cancel(struct hrtimer *hrtimer) 749ea3e141SMark Johnston { 759ea3e141SMark Johnston 76e1cf70fbSAlexander Motin return (callout_drain(&hrtimer->callout) > 0); 779ea3e141SMark Johnston } 789ea3e141SMark Johnston 799ea3e141SMark Johnston void 809ea3e141SMark Johnston linux_hrtimer_init(struct hrtimer *hrtimer) 819ea3e141SMark Johnston { 829ea3e141SMark Johnston 83*0a854962SHans Petter Selasky memset(hrtimer, 0, sizeof(*hrtimer)); 84*0a854962SHans Petter Selasky mtx_init(&hrtimer->mtx, "hrtimer", NULL, 85*0a854962SHans Petter Selasky MTX_DEF | MTX_RECURSE | MTX_NOWITNESS); 869ea3e141SMark Johnston callout_init_mtx(&hrtimer->callout, &hrtimer->mtx, 0); 879ea3e141SMark Johnston } 889ea3e141SMark Johnston 899ea3e141SMark Johnston void 90*0a854962SHans Petter Selasky linux_hrtimer_set_expires(struct hrtimer *hrtimer, ktime_t time) 919ea3e141SMark Johnston { 92*0a854962SHans Petter Selasky hrtimer->expires = ktime_to_ns(time); 939ea3e141SMark Johnston } 949ea3e141SMark Johnston 959ea3e141SMark Johnston void 969ea3e141SMark Johnston linux_hrtimer_start(struct hrtimer *hrtimer, ktime_t time) 979ea3e141SMark Johnston { 989ea3e141SMark Johnston 999ea3e141SMark Johnston linux_hrtimer_start_range_ns(hrtimer, time, 0); 1009ea3e141SMark Johnston } 1019ea3e141SMark Johnston 1029ea3e141SMark Johnston void 103*0a854962SHans Petter Selasky linux_hrtimer_start_range_ns(struct hrtimer *hrtimer, ktime_t time, 104*0a854962SHans Petter Selasky int64_t nsec) 1059ea3e141SMark Johnston { 1069ea3e141SMark Johnston 1079ea3e141SMark Johnston mtx_lock(&hrtimer->mtx); 108*0a854962SHans Petter Selasky hrtimer->precision = nsec; 109*0a854962SHans Petter Selasky callout_reset_sbt(&hrtimer->callout, nstosbt(ktime_to_ns(time)), 110*0a854962SHans Petter Selasky nstosbt(nsec), hrtimer_call_handler, hrtimer, 0); 1119ea3e141SMark Johnston mtx_unlock(&hrtimer->mtx); 1129ea3e141SMark Johnston } 113*0a854962SHans Petter Selasky 114*0a854962SHans Petter Selasky void 115*0a854962SHans Petter Selasky linux_hrtimer_forward_now(struct hrtimer *hrtimer, ktime_t interval) 116*0a854962SHans Petter Selasky { 117*0a854962SHans Petter Selasky 118*0a854962SHans Petter Selasky mtx_lock(&hrtimer->mtx); 119*0a854962SHans Petter Selasky callout_reset_sbt(&hrtimer->callout, nstosbt(ktime_to_ns(interval)), 120*0a854962SHans Petter Selasky nstosbt(hrtimer->precision), hrtimer_call_handler, hrtimer, 0); 121*0a854962SHans Petter Selasky mtx_unlock(&hrtimer->mtx); 122*0a854962SHans Petter Selasky } 123*0a854962SHans Petter Selasky 124