+1
-1
src/header/_aio/mod.rs
+1
-1
src/header/_aio/mod.rs
+17
src/header/signal/mod.rs
+17
src/header/signal/mod.rs
···
37
37
pub const SI_QUEUE: c_int = -1;
38
38
pub const SI_USER: c_int = 0;
39
39
40
+
pub const SIGEV_SIGNAL: c_int = 0;
41
+
pub const SIGEV_NONE: c_int = 1;
42
+
pub const SIGEV_THREAD: c_int = 2;
43
+
40
44
#[repr(C)]
41
45
#[derive(Clone, Debug)]
42
46
/// cbindgen:ignore
···
53
57
pub ss_sp: *mut c_void,
54
58
pub ss_flags: c_int,
55
59
pub ss_size: size_t,
60
+
}
61
+
62
+
#[repr(C)]
63
+
#[derive(Clone)]
64
+
pub struct sigevent {
65
+
pub sigev_value: sigval,
66
+
pub sigev_signo: c_int,
67
+
pub sigev_notify: c_int,
68
+
pub sigev_notify_function: Option<extern "C" fn(sigval)>,
69
+
pub sigev_notify_attributes: *mut pthread_attr_t,
56
70
}
57
71
58
72
// FIXME: This struct is wrong on Linux
···
525
539
string.as_bytes().len(),
526
540
);
527
541
}
542
+
543
+
#[unsafe(no_mangle)]
544
+
pub unsafe extern "C" fn cbindgen_stupid_struct_sigevent_for_timer(a: sigevent) {}
+4
-1
src/header/time/cbindgen.toml
+4
-1
src/header/time/cbindgen.toml
···
1
-
sys_includes = ["sys/types.h", "stdint.h", "stddef.h", "features.h"]
1
+
sys_includes = ["sys/types.h", "signal.h", "stdint.h", "stddef.h", "features.h"]
2
2
include_guard = "_RELIBC_TIME_H"
3
3
language = "C"
4
4
style = "Tag"
···
7
7
8
8
[enum]
9
9
prefix_with_name = true
10
+
11
+
[export.rename]
12
+
"sigevent" = "struct sigevent"
+62
-15
src/header/time/mod.rs
+62
-15
src/header/time/mod.rs
···
6
6
c_str::{CStr, CString},
7
7
error::ResultExt,
8
8
fs::File,
9
-
header::{errno::EOVERFLOW, fcntl::O_RDONLY, stdlib::getenv, unistd::readlink},
9
+
header::{
10
+
errno::EOVERFLOW, fcntl::O_RDONLY, signal::sigevent, stdlib::getenv, unistd::readlink,
11
+
},
10
12
io::Read,
11
13
out::Out,
12
14
platform::{self, Pal, Sys, types::*},
···
47
49
48
50
impl timespec {
49
51
// TODO: Write test
52
+
pub fn add(base: timespec, interval: timespec) -> Option<timespec> {
53
+
let base_nsec = c_ulong::try_from(base.tv_nsec).ok()?;
54
+
let interval_nsec = c_ulong::try_from(interval.tv_nsec).ok()?;
55
+
56
+
Some(if base_nsec.checked_add(interval_nsec)? < 1_000_000_000 {
57
+
timespec {
58
+
tv_sec: base.tv_sec.checked_add(interval.tv_sec)?,
59
+
tv_nsec: (base_nsec + interval_nsec) as _,
60
+
}
61
+
} else {
62
+
timespec {
63
+
tv_sec: base.tv_sec.checked_add(interval.tv_sec)?.checked_add(1)?,
64
+
tv_nsec: ((interval_nsec + base_nsec) - 1_000_000_000) as c_long,
65
+
}
66
+
})
67
+
}
68
+
// TODO: Write test
50
69
pub fn subtract(later: timespec, earlier: timespec) -> Option<timespec> {
51
-
// TODO: Can tv_nsec be negative?
52
70
let later_nsec = c_ulong::try_from(later.tv_nsec).ok()?;
53
71
let earlier_nsec = c_ulong::try_from(earlier.tv_nsec).ok()?;
54
72
55
-
Some(if later_nsec > earlier_nsec {
73
+
let time = if later_nsec > earlier_nsec {
56
74
timespec {
57
75
tv_sec: later.tv_sec.checked_sub(earlier.tv_sec)?,
58
76
tv_nsec: (later_nsec - earlier_nsec) as _,
···
62
80
tv_sec: later.tv_sec.checked_sub(earlier.tv_sec)?.checked_sub(1)?,
63
81
tv_nsec: 1_000_000_000 - (earlier_nsec - later_nsec) as c_long,
64
82
}
65
-
})
83
+
};
84
+
85
+
if time.tv_sec < 0 {
86
+
// https://man7.org/linux/man-pages/man2/settimeofday.2.html
87
+
// caller should return EINVAL
88
+
return None;
89
+
}
90
+
91
+
Some(time)
92
+
}
93
+
pub fn is_default(&self) -> bool {
94
+
return self.tv_nsec == 0 && self.tv_sec == 0;
66
95
}
67
96
}
68
97
···
74
103
tv_nsec: tp.tv_nsec as _,
75
104
}
76
105
}
106
+
}
107
+
108
+
/// timer_t internal data, ABI unstable
109
+
#[repr(C)]
110
+
#[derive(Clone)]
111
+
#[cfg(target_os = "redox")]
112
+
pub(crate) struct timer_internal_t {
113
+
pub clockid: clockid_t,
114
+
pub timerfd: usize,
115
+
pub eventfd: usize,
116
+
pub evp: sigevent,
117
+
pub thread: pthread_t,
118
+
// relibc handles it_interval, not the kernel
119
+
pub next_wake_time: itimerspec,
77
120
}
78
121
79
122
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/time.h.html>.
···
132
175
133
176
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/time.h.html>.
134
177
#[repr(C)]
178
+
#[derive(Clone, Default)]
135
179
pub struct itimerspec {
136
180
pub it_interval: timespec,
137
181
pub it_value: timespec,
138
182
}
139
-
140
-
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/time.h.html>.
141
-
pub struct sigevent;
142
183
143
184
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/asctime.html>.
144
185
///
···
493
534
}
494
535
495
536
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/timer_create.html>.
496
-
// #[unsafe(no_mangle)]
537
+
#[unsafe(no_mangle)]
497
538
pub extern "C" fn timer_create(
498
539
clock_id: clockid_t,
499
540
evp: *mut sigevent,
500
541
timerid: *mut timer_t,
501
542
) -> c_int {
502
-
unimplemented!();
543
+
Sys::timer_create(clock_id, evp, timerid)
544
+
.map(|()| 0)
545
+
.or_minus_one_errno()
503
546
}
504
547
505
548
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/timer_delete.html>.
506
-
// #[unsafe(no_mangle)]
549
+
#[unsafe(no_mangle)]
507
550
pub extern "C" fn timer_delete(timerid: timer_t) -> c_int {
508
-
unimplemented!();
551
+
Sys::timer_delete(timerid).map(|()| 0).or_minus_one_errno()
509
552
}
510
553
511
554
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/timer_getoverrun.html>.
···
515
558
}
516
559
517
560
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/timer_getoverrun.html>.
518
-
// #[unsafe(no_mangle)]
561
+
#[unsafe(no_mangle)]
519
562
pub extern "C" fn timer_gettime(timerid: timer_t, value: *mut itimerspec) -> c_int {
520
-
unimplemented!();
563
+
Sys::timer_gettime(timerid, value)
564
+
.map(|()| 0)
565
+
.or_minus_one_errno()
521
566
}
522
567
523
568
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/timer_getoverrun.html>.
524
-
// #[unsafe(no_mangle)]
569
+
#[unsafe(no_mangle)]
525
570
pub extern "C" fn timer_settime(
526
571
timerid: timer_t,
527
572
flags: c_int,
528
573
value: *const itimerspec,
529
574
ovalue: *mut itimerspec,
530
575
) -> c_int {
531
-
unimplemented!();
576
+
Sys::timer_settime(timerid, flags, value, ovalue)
577
+
.map(|()| 0)
578
+
.or_minus_one_errno()
532
579
}
533
580
534
581
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/timespec_get.html>.
+23
-1
src/platform/linux/mod.rs
+23
-1
src/platform/linux/mod.rs
···
7
7
dirent::dirent,
8
8
errno::{EINVAL, EIO, EOPNOTSUPP},
9
9
fcntl::{AT_EMPTY_PATH, AT_FDCWD, AT_REMOVEDIR, AT_SYMLINK_NOFOLLOW},
10
-
signal::SIGCHLD,
10
+
signal::{SIGCHLD, sigevent},
11
11
sys_resource::{rlimit, rusage},
12
12
sys_stat::{S_IFIFO, stat},
13
13
sys_statvfs::statvfs,
14
14
sys_time::{timeval, timezone},
15
+
time::itimerspec,
15
16
unistd::{SEEK_CUR, SEEK_SET},
16
17
},
17
18
io::Write,
···
723
724
724
725
fn sync() -> Result<()> {
725
726
e_raw(unsafe { syscall!(SYNC) }).map(|_| ())
727
+
}
728
+
729
+
fn timer_create(clock_id: clockid_t, evp: *mut sigevent, timerid: *mut timer_t) -> Result<()> {
730
+
e_raw(unsafe { syscall!(TIMER_CREATE, clock_id, evp, timerid) }).map(|_| ())
731
+
}
732
+
733
+
fn timer_delete(timerid: timer_t) -> Result<()> {
734
+
e_raw(unsafe { syscall!(TIMER_DELETE, timerid) }).map(|_| ())
735
+
}
736
+
737
+
fn timer_gettime(timerid: timer_t, value: *mut itimerspec) -> Result<()> {
738
+
e_raw(unsafe { syscall!(TIMER_GETTIME, timerid, value) }).map(|_| ())
739
+
}
740
+
741
+
fn timer_settime(
742
+
timerid: timer_t,
743
+
flags: c_int,
744
+
value: *const itimerspec,
745
+
ovalue: *mut itimerspec,
746
+
) -> Result<()> {
747
+
e_raw(unsafe { syscall!(TIMER_SETTIME, timerid, flags, value, ovalue) }).map(|_| ())
726
748
}
727
749
728
750
fn umask(mask: mode_t) -> mode_t {
+15
-1
src/platform/pal/mod.rs
+15
-1
src/platform/pal/mod.rs
···
3
3
c_str::CStr,
4
4
error::{Errno, Result},
5
5
header::{
6
+
signal::sigevent,
6
7
sys_resource::{rlimit, rusage},
7
8
sys_stat::stat,
8
9
sys_statvfs::statvfs,
9
10
sys_time::{timeval, timezone},
10
11
sys_utsname::utsname,
11
-
time::timespec,
12
+
time::{itimerspec, timespec},
12
13
},
13
14
out::Out,
14
15
pthread,
···
251
252
fn symlink(path1: CStr, path2: CStr) -> Result<()>;
252
253
253
254
fn sync() -> Result<()>;
255
+
256
+
fn timer_create(clock_id: clockid_t, evp: *mut sigevent, timerid: *mut timer_t) -> Result<()>;
257
+
258
+
fn timer_delete(timerid: timer_t) -> Result<()>;
259
+
260
+
fn timer_gettime(timerid: timer_t, value: *mut itimerspec) -> Result<()>;
261
+
262
+
fn timer_settime(
263
+
timerid: timer_t,
264
+
flags: c_int,
265
+
value: *const itimerspec,
266
+
ovalue: *mut itimerspec,
267
+
) -> Result<()>;
254
268
255
269
// Always successful
256
270
fn umask(mask: mode_t) -> mode_t;
+183
-3
src/platform/redox/mod.rs
+183
-3
src/platform/redox/mod.rs
···
21
21
header::{
22
22
dirent::dirent,
23
23
errno::{
24
-
EBADF, EBADFD, EBADR, EINTR, EINVAL, EIO, ENAMETOOLONG, ENOENT, ENOMEM, ENOSYS,
24
+
EBADF, EBADFD, EBADR, EFAULT, EINTR, EINVAL, EIO, ENAMETOOLONG, ENOENT, ENOMEM, ENOSYS,
25
25
EOPNOTSUPP, EPERM, ERANGE,
26
26
},
27
-
fcntl::{self, AT_FDCWD, O_RDONLY},
27
+
fcntl::{self, AT_FDCWD, O_CREAT, O_RDONLY, O_RDWR},
28
28
limits,
29
+
pthread::{pthread_cancel, pthread_create},
30
+
signal::{SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD, sigevent},
29
31
sys_mman::{MAP_ANONYMOUS, MAP_FAILED, PROT_READ, PROT_WRITE},
30
32
sys_random,
31
33
sys_resource::{RLIM_INFINITY, rlimit, rusage},
···
34
36
sys_time::{timeval, timezone},
35
37
sys_utsname::{UTSLENGTH, utsname},
36
38
sys_wait,
37
-
time::timespec,
39
+
time::{itimerspec, timer_internal_t, timespec},
38
40
unistd::{F_OK, R_OK, SEEK_CUR, SEEK_SET, W_OK, X_OK},
39
41
},
40
42
io::{self, BufReader, prelude::*},
41
43
out::Out,
44
+
platform::sys::{
45
+
libredox::RawResult,
46
+
timer::{timer_routine, timer_update_wake_time},
47
+
},
42
48
sync::rwlock::RwLock,
43
49
};
44
50
···
73
79
mod ptrace;
74
80
pub(crate) mod signal;
75
81
mod socket;
82
+
mod timer;
76
83
77
84
macro_rules! path_from_c_str {
78
85
($c_str:expr) => {{
···
863
870
let fd = usize::try_from(fd).map_err(|_| Errno(EBADF))?;
864
871
Ok(redox_rt::sys::posix_read(fd, buf)?)
865
872
}
873
+
866
874
fn pread(fd: c_int, buf: &mut [u8], offset: off_t) -> Result<usize> {
867
875
unsafe {
868
876
Ok(syscall::syscall5(
···
1005
1013
}
1006
1014
1007
1015
fn sync() -> Result<()> {
1016
+
Ok(())
1017
+
}
1018
+
1019
+
fn timer_create(clock_id: clockid_t, evp: *mut sigevent, timerid: *mut timer_t) -> Result<()> {
1020
+
if timerid.is_null() || evp.is_null() {
1021
+
return Err(Errno(EFAULT));
1022
+
}
1023
+
let ev = unsafe { &*evp };
1024
+
if ev.sigev_notify == SIGEV_THREAD && ev.sigev_notify_function.is_none() {
1025
+
return Err(Errno(EINVAL));
1026
+
}
1027
+
1028
+
let path = format!("/scheme/time/{clock_id}");
1029
+
let timerfd = libredox::open(&path, O_RDWR, 0)?;
1030
+
1031
+
unsafe {
1032
+
let eventfd = Error::demux(event::redox_event_queue_create_v1(0)).map_err(|e| {
1033
+
let _ = syscall::close(timerfd);
1034
+
e
1035
+
})?;
1036
+
1037
+
let timer_buf = Self::mmap(
1038
+
ptr::null_mut(),
1039
+
size_of::<timer_internal_t>(),
1040
+
PROT_READ | PROT_WRITE,
1041
+
MAP_ANONYMOUS,
1042
+
0,
1043
+
0,
1044
+
)
1045
+
.map_err(|e| {
1046
+
let _ = syscall::close(timerfd);
1047
+
let _ = syscall::close(eventfd);
1048
+
e
1049
+
})?;
1050
+
1051
+
*timerid = timer_buf;
1052
+
1053
+
let timer_ptr = timer_buf as *mut timer_internal_t;
1054
+
let timer_st = (&mut *timer_ptr);
1055
+
1056
+
timer_st.clockid = clock_id;
1057
+
timer_st.timerfd = timerfd;
1058
+
timer_st.eventfd = eventfd;
1059
+
timer_st.evp = (*evp).clone();
1060
+
timer_st.next_wake_time = itimerspec::default();
1061
+
timer_st.thread = ptr::null_mut();
1062
+
}
1063
+
Ok(())
1064
+
}
1065
+
1066
+
fn timer_delete(timerid: timer_t) -> Result<()> {
1067
+
if timerid.is_null() {
1068
+
return Err(Errno(EFAULT));
1069
+
}
1070
+
unsafe {
1071
+
let timer_ptr = timerid as *mut timer_internal_t;
1072
+
let timer_st = (&mut *timer_ptr);
1073
+
let _ = syscall::close(timer_st.timerfd);
1074
+
let _ = syscall::close(timer_st.eventfd);
1075
+
if !timer_st.thread.is_null() {
1076
+
let _ = pthread_cancel(timer_st.thread);
1077
+
}
1078
+
Self::munmap(timer_ptr as *mut c_void, size_of::<timer_internal_t>())?;
1079
+
}
1080
+
1081
+
Ok(())
1082
+
}
1083
+
1084
+
fn timer_gettime(timerid: timer_t, value: *mut itimerspec) -> Result<()> {
1085
+
if value.is_null() {
1086
+
return Err(Errno(EFAULT));
1087
+
}
1088
+
1089
+
let timer_st = unsafe { &mut *(timerid as *mut timer_internal_t) };
1090
+
let mut now = timespec::default();
1091
+
Self::clock_gettime(timer_st.clockid, Out::from_mut(&mut now))?;
1092
+
1093
+
if timer_st.evp.sigev_notify == SIGEV_NONE {
1094
+
if timespec::subtract(timer_st.next_wake_time.it_value, now).is_none() {
1095
+
// error here means the timer is disarmed
1096
+
let _ = timer_update_wake_time(timer_st);
1097
+
}
1098
+
}
1099
+
1100
+
unsafe {
1101
+
*value = if timer_st.next_wake_time.it_value.is_default() {
1102
+
// disarmed
1103
+
itimerspec::default()
1104
+
} else {
1105
+
itimerspec {
1106
+
it_interval: timer_st.next_wake_time.it_interval,
1107
+
it_value: timespec::subtract(timer_st.next_wake_time.it_value, now)
1108
+
.unwrap_or_default(),
1109
+
}
1110
+
};
1111
+
}
1112
+
1113
+
Ok(())
1114
+
}
1115
+
1116
+
fn timer_settime(
1117
+
timerid: timer_t,
1118
+
_flags: c_int,
1119
+
value: *const itimerspec,
1120
+
ovalue: *mut itimerspec,
1121
+
) -> Result<()> {
1122
+
if timerid.is_null() || value.is_null() {
1123
+
return Err(Errno(EFAULT));
1124
+
}
1125
+
1126
+
let timer_st = unsafe { &mut *(timerid as *mut timer_internal_t) };
1127
+
1128
+
if !ovalue.is_null() {
1129
+
Self::timer_gettime(timerid, ovalue)?;
1130
+
}
1131
+
1132
+
let mut now = timespec::default();
1133
+
Self::clock_gettime(timer_st.clockid, Out::from_mut(&mut now))?;
1134
+
1135
+
//FIXME: make these atomic?
1136
+
timer_st.next_wake_time = unsafe {
1137
+
let mut val = (*value).clone();
1138
+
val.it_value = timespec::add(now, val.it_value).ok_or((Errno(EINVAL)))?;
1139
+
val
1140
+
};
1141
+
1142
+
Error::demux(unsafe {
1143
+
event::redox_event_queue_ctl_v1(timer_st.eventfd, timer_st.timerfd, 1, 0)
1144
+
})?;
1145
+
1146
+
let buf_to_write = unsafe {
1147
+
slice::from_raw_parts(
1148
+
&timer_st.next_wake_time.it_value as *const _ as *const u8,
1149
+
mem::size_of::<timespec>(),
1150
+
)
1151
+
};
1152
+
1153
+
let bytes_written = redox_rt::sys::posix_write(timer_st.timerfd, buf_to_write)?;
1154
+
1155
+
if bytes_written < mem::size_of::<timespec>() {
1156
+
return Err(Errno(EIO));
1157
+
}
1158
+
1159
+
if timer_st.thread.is_null() {
1160
+
timer_st.thread = match timer_st.evp.sigev_notify {
1161
+
SIGEV_THREAD => {
1162
+
let mut tid = pthread_t::default();
1163
+
1164
+
let result = unsafe {
1165
+
pthread_create(
1166
+
&mut tid as *mut _,
1167
+
ptr::null(),
1168
+
timer_routine,
1169
+
timerid as *mut c_void,
1170
+
)
1171
+
};
1172
+
if result != 0 {
1173
+
return Err(Errno(result));
1174
+
}
1175
+
tid
1176
+
}
1177
+
//TODO
1178
+
SIGEV_SIGNAL => {
1179
+
return Err(Errno(ENOSYS));
1180
+
}
1181
+
SIGEV_NONE => ptr::null_mut(),
1182
+
_ => {
1183
+
return Err(Errno(EINVAL));
1184
+
}
1185
+
};
1186
+
}
1187
+
1008
1188
Ok(())
1009
1189
}
1010
1190
+100
src/platform/redox/timer.rs
+100
src/platform/redox/timer.rs
···
1
+
use ::event::raw::RawEventV1;
2
+
use syscall::Error;
3
+
4
+
use crate::{
5
+
error::{Errno, Result},
6
+
header::{
7
+
errno::EIO,
8
+
signal::{sigevent, sigval},
9
+
time::{timer_internal_t, timespec},
10
+
},
11
+
out::Out,
12
+
platform::{
13
+
Pal, Sys,
14
+
sys::{event, libredox},
15
+
types::c_void,
16
+
},
17
+
};
18
+
use core::{
19
+
mem::{MaybeUninit, size_of, transmute},
20
+
ops::ControlFlow,
21
+
ptr, slice,
22
+
};
23
+
24
+
pub extern "C" fn timer_routine(arg: *mut c_void) -> *mut c_void {
25
+
unsafe {
26
+
let timer_st = &mut *(arg as *mut timer_internal_t);
27
+
28
+
loop {
29
+
let mut buf = MaybeUninit::uninit();
30
+
31
+
unsafe {
32
+
let res = Error::demux(event::redox_event_queue_get_events_v1(
33
+
timer_st.eventfd,
34
+
buf.as_mut_ptr(),
35
+
1,
36
+
0,
37
+
core::ptr::null(),
38
+
core::ptr::null(),
39
+
));
40
+
if let Ok(res) = res {
41
+
assert_eq!(res, 1, "EOF is not yet well defined for event queues");
42
+
} else {
43
+
timer_st.thread = ptr::null_mut();
44
+
break;
45
+
}
46
+
47
+
if let Some(fun) = timer_st.evp.sigev_notify_function {
48
+
fun(timer_st.evp.sigev_value);
49
+
}
50
+
51
+
if timer_next_event(timer_st).is_err() {
52
+
timer_st.thread = ptr::null_mut();
53
+
break;
54
+
}
55
+
}
56
+
}
57
+
}
58
+
59
+
ptr::null_mut()
60
+
}
61
+
62
+
fn timer_next_event(timer_st: &mut timer_internal_t) -> Result<()> {
63
+
timer_update_wake_time(timer_st)?;
64
+
65
+
Error::demux(unsafe {
66
+
event::redox_event_queue_ctl_v1(timer_st.eventfd, timer_st.timerfd, 1, 0)
67
+
})?;
68
+
69
+
let buf_to_write = unsafe {
70
+
slice::from_raw_parts(
71
+
&timer_st.next_wake_time.it_value as *const _ as *const u8,
72
+
size_of::<timespec>(),
73
+
)
74
+
};
75
+
76
+
let bytes_written = redox_rt::sys::posix_write(timer_st.timerfd, buf_to_write)?;
77
+
if bytes_written < size_of::<timespec>() {
78
+
return Err(Errno(EIO));
79
+
}
80
+
Ok(())
81
+
}
82
+
83
+
pub(crate) fn timer_update_wake_time(timer_st: &mut timer_internal_t) -> Result<()> {
84
+
timer_st.next_wake_time.it_value = if timer_st.next_wake_time.it_interval.is_default() {
85
+
timespec::default()
86
+
} else {
87
+
let mut now = timespec::default();
88
+
Sys::clock_gettime(timer_st.clockid, Out::from_mut(&mut now))?;
89
+
let next_time = match timespec::add(now, timer_st.next_wake_time.it_interval) {
90
+
Some(a) => a,
91
+
None => timespec::default(),
92
+
};
93
+
94
+
next_time
95
+
};
96
+
if timer_st.next_wake_time.it_value.is_default() {
97
+
return Err(Errno(0));
98
+
}
99
+
Ok(())
100
+
}