Last active
April 2, 2021 07:14
-
-
Save Amanieu/d97c420c00cd51fad556b633e0d87af1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Common code for interruptible syscalls | |
macro_rules! asm_interruptible_syscall { | |
($interrupted:expr, $interrupt_flag:expr, $result:expr, $nr:expr) => { | |
asm_snippet!( | |
// If a signal interrupts us between atomic_begin and atomic_end, | |
// the signal handler will rewind the PC back to atomic_begin so | |
// that the interrupt flag check is atomic. | |
atomic_begin:, | |
"ldrb {interrupted:w}, [{interrupt_flag}]", | |
"cbnz {interrupted}, {skip}", | |
atomic_end:, | |
"svc #0", | |
skip:, | |
// Record the range of instructions which should be atomic. | |
".section interrupt_restart_list, \"aw\"", | |
".balign 8", | |
".quad {atomic_begin}", | |
".quad {atomic_end}", | |
".previous", | |
interrupted = out(reg) $interrupted, | |
interrupt_flag = in(reg) $interrupt_flag, | |
lateout("x0") $result, | |
inout("x8") $nr as u64 => _, | |
) | |
}; | |
} | |
// There are other versions of this function with different numbers of | |
// arguments, however they all share the same asm code above. | |
#[inline] | |
pub unsafe fn interruptible_syscall3( | |
interrupt_flag: &InterruptFlag, | |
nr: usize, | |
arg0: usize, | |
arg1: usize, | |
arg2: usize, | |
) -> Interruptible<usize> { | |
let result; | |
let interrupted: u64; | |
asm!( | |
asm_interruptible_syscall!(interrupted, interrupt_flag), | |
in("x0") arg0, | |
in("x1") arg1, | |
in("x2") arg2, | |
); | |
if interrupted == 0 { | |
Ok(result) | |
} else { | |
Err(Interrupted::from_flag(interrupted)) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Common code for interruptible syscalls | |
macro_rules! asm_interruptible_syscall { | |
() => { | |
r#" | |
# If a signal interrupts us between 0 and 1, the signal handler | |
# will rewind the PC back to 0 so that the interrupt flag check is | |
# atomic. | |
0: | |
ldrb {interrupted:w}, [{interrupt_flag}] | |
cbnz {interrupted}, 2f | |
1: | |
svc #0 | |
2: | |
# Record the range of instructions which should be atomic. | |
.section interrupt_restart_list, "aw" | |
.balign 8 | |
.quad 0b | |
.quad 1b | |
.previous | |
"# | |
}; | |
} | |
// There are other versions of this function with different numbers of | |
// arguments, however they all share the same asm code above. | |
#[inline] | |
pub unsafe fn interruptible_syscall3( | |
interrupt_flag: &InterruptFlag, | |
nr: usize, | |
arg0: usize, | |
arg1: usize, | |
arg2: usize, | |
) -> Interruptible<usize> { | |
let result; | |
let interrupted: u64; | |
asm!( | |
asm_interruptible_syscall!(), | |
interrupted = out(reg) interrupted, | |
interrupt_flag = in(reg) interrupt_flag, | |
lateout("x0") result, | |
in("x0") arg0, | |
in("x1") arg1, | |
in("x2") arg2, | |
inout("x8") nr as u64 => _, | |
); | |
if interrupted == 0 { | |
Ok(result) | |
} else { | |
Err(Interrupted) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment