Macro scall::syscall_args64 [−][src]
A version of syscall!
that makes it easier to pass 64-bit arguments.
WARNING: Make sure to read “Important notes” below before attempting to use this macro!
Background
On 32-bit architectures, system calls that accept 64-bit arguments (i.e. file offsets) must
split the argument between two registers. Additionally, some on architectures (for example,
ARM, PowerPC, and MIPS), the value must be aligned to an even pair of registers. More
information, including a list of affected syscalls, can be found in syscall(2)
.
This macro doesn’t completely eliminate the architecture-specific differences, but it makes them easier to handle.
Usage
This macro can be invoked just like syscall!
, except that any 64-bit arguments should have
@u64
added before them. For example:
unsafe fn readahead(fd: i32, offset: u64, count: usize) -> Result<(), i32> { syscall_args64!(READAHEAD, fd, @u64 offset, count)?; Ok(()) }
On 32-bit systems, the offset
argument will be split and/or aligned appropriately; on 64-bit
systems it will be passed directly.
Important notes
-
Due to limitations of Rust’s macro system, at least one
@u64
argument must be passed. For example,syscall_args64!(READ, 0, 0, 0)
is invalid; you should usesyscall!
instead if you don’t need to pass 64-bit arguments.Additionally, all of the
@u64
arguments must be listed consecutively; for example,syscall_args64!(READ, @u64 0, 0, @u64 0)
is invalid. In practice, this shouldn’t be an issue because all of the syscalls that require 64-bit arguments have them listed consecutively. -
The prefix
@u64
should be used even if the kernel will interpret the argument as a signed number (i.e.i64
). -
This macro makes it easier to split 64-bit arguments between registers. However, some of the syscalls that accept 64-bit arguments have other architecture-specific differences.
scall
does not account for these differences; that is left to the user.sync_file_range(2)
is a good example of this. Architectures that require even-register alignment havesync_file_range2()
, which swaps the argument order to avoid requiring 7 arguments, instead ofsync_file_range()
. -
On 32-bit systems,
@u64
arguments will (out of necessity) be evaluated twice. As a result, if evaluating the expression changes its value, behavior is undefined (a problem that may be familiar to C/C++ users). For example, this code will behave differently on 32-bit and 64-bit systems:
unsafe { let mut x = 0; // DO **NOT** DO THIS!!! syscall_args64!(READAHEAD, 0, @u64 { x += 1; x }, 0).unwrap(); }
Safety
See syscall!
(and also read “Important notes” above).