rtc_user.c (1534B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2020 Intel Corporation 4 * Author: Johannes Berg <johannes@sipsolutions.net> 5 */ 6#include <stdbool.h> 7#include <os.h> 8#include <errno.h> 9#include <sched.h> 10#include <unistd.h> 11#include <kern_util.h> 12#include <sys/select.h> 13#include <stdio.h> 14#include <sys/timerfd.h> 15#include "rtc.h" 16 17static int uml_rtc_irq_fds[2]; 18 19void uml_rtc_send_timetravel_alarm(void) 20{ 21 unsigned long long c = 1; 22 23 CATCH_EINTR(write(uml_rtc_irq_fds[1], &c, sizeof(c))); 24} 25 26int uml_rtc_start(bool timetravel) 27{ 28 int err; 29 30 if (timetravel) { 31 int err = os_pipe(uml_rtc_irq_fds, 1, 1); 32 if (err) 33 goto fail; 34 } else { 35 uml_rtc_irq_fds[0] = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC); 36 if (uml_rtc_irq_fds[0] < 0) { 37 err = -errno; 38 goto fail; 39 } 40 41 /* apparently timerfd won't send SIGIO, use workaround */ 42 sigio_broken(uml_rtc_irq_fds[0]); 43 err = add_sigio_fd(uml_rtc_irq_fds[0]); 44 if (err < 0) { 45 close(uml_rtc_irq_fds[0]); 46 goto fail; 47 } 48 } 49 50 return uml_rtc_irq_fds[0]; 51fail: 52 uml_rtc_stop(timetravel); 53 return err; 54} 55 56int uml_rtc_enable_alarm(unsigned long long delta_seconds) 57{ 58 struct itimerspec it = { 59 .it_value = { 60 .tv_sec = delta_seconds, 61 }, 62 }; 63 64 if (timerfd_settime(uml_rtc_irq_fds[0], 0, &it, NULL)) 65 return -errno; 66 return 0; 67} 68 69void uml_rtc_disable_alarm(void) 70{ 71 uml_rtc_enable_alarm(0); 72} 73 74void uml_rtc_stop(bool timetravel) 75{ 76 if (timetravel) 77 os_close_file(uml_rtc_irq_fds[1]); 78 else 79 ignore_sigio_fd(uml_rtc_irq_fds[0]); 80 os_close_file(uml_rtc_irq_fds[0]); 81}