123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- //+build linux
- //+no-instrumentation
- package linux
- import "base:intrinsics"
- // Note(flysand): In the case of syscall let's get rid of extra
- // casting. First of all, let these syscalls return int, because
- // we'll need to check for Errno anyway. Second of all
- // most parameters are going to be trivially-castable to
- // uintptr, so we'll have that.
- @(private)
- syscall0 :: #force_inline proc "contextless" (nr: uintptr) -> int {
- return int(intrinsics.syscall(nr))
- }
- @(private)
- syscall1 :: #force_inline proc "contextless" (nr: uintptr, p1: $T) -> int
- where
- size_of(p1) <= size_of(uintptr)
- {
- return int(intrinsics.syscall(nr, uintptr(p1)))
- }
- @(private)
- syscall2 :: #force_inline proc "contextless" (nr: uintptr,p1: $T1, p2: $T2) -> int
- where
- size_of(p1) <= size_of(uintptr),
- size_of(p2) <= size_of(uintptr)
- {
- return int(intrinsics.syscall(nr, uintptr(p1), uintptr(p2)))
- }
- @(private)
- syscall3 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3) -> int
- where
- size_of(p1) <= size_of(uintptr),
- size_of(p2) <= size_of(uintptr),
- size_of(p3) <= size_of(uintptr)
- {
- return int(intrinsics.syscall(nr,
- uintptr(p1),
- uintptr(p2),
- uintptr(p3),
- ))
- }
- @(private)
- syscall4 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4) -> int
- where
- size_of(p1) <= size_of(uintptr),
- size_of(p2) <= size_of(uintptr),
- size_of(p3) <= size_of(uintptr),
- size_of(p4) <= size_of(uintptr)
- {
- return int(intrinsics.syscall(nr,
- uintptr(p1),
- uintptr(p2),
- uintptr(p3),
- uintptr(p4),
- ))
- }
- @(private)
- syscall5 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4, p5: $T5) -> int
- where
- size_of(p1) <= size_of(uintptr),
- size_of(p2) <= size_of(uintptr),
- size_of(p3) <= size_of(uintptr),
- size_of(p4) <= size_of(uintptr),
- size_of(p5) <= size_of(uintptr)
- {
- return int(intrinsics.syscall(nr,
- uintptr(p1),
- uintptr(p2),
- uintptr(p3),
- uintptr(p4),
- uintptr(p5),
- ))
- }
- @(private)
- syscall6 :: #force_inline proc "contextless" (nr: uintptr, p1: $T1, p2: $T2, p3: $T3, p4: $T4, p5: $T5, p6: $T6) -> int
- where
- size_of(p1) <= size_of(uintptr),
- size_of(p2) <= size_of(uintptr),
- size_of(p3) <= size_of(uintptr),
- size_of(p4) <= size_of(uintptr),
- size_of(p5) <= size_of(uintptr),
- size_of(p6) <= size_of(uintptr)
- {
- return int(intrinsics.syscall(nr,
- uintptr(p1),
- uintptr(p2),
- uintptr(p3),
- uintptr(p4),
- uintptr(p5),
- uintptr(p6),
- ))
- }
- syscall :: proc {syscall0, syscall1, syscall2, syscall3, syscall4, syscall5, syscall6}
- // Note(bumbread): This should shrug off a few lines from every syscall.
- // Since not any type can be trivially casted to another type, we take two arguments:
- // the final type to cast to, and the type to transmute to before casting.
- // One transmute + one cast should allow us to get to any type we might want
- // to return from a syscall wrapper.
- @(private)
- errno_unwrap3 :: #force_inline proc "contextless" (ret: $P, $T: typeid, $U: typeid) -> (T, Errno)
- where
- intrinsics.type_is_ordered_numeric(P)
- {
- if ret < 0 {
- default_value: T
- return default_value, Errno(-ret)
- } else {
- return T(transmute(U)ret), Errno(.NONE)
- }
- }
- @(private)
- errno_unwrap2 :: #force_inline proc "contextless" (ret: $P, $T: typeid) -> (T, Errno) {
- if ret < 0 {
- default_value: T
- return default_value, Errno(-ret)
- } else {
- return T(ret), Errno(.NONE)
- }
- }
- @(private)
- errno_unwrap :: proc {errno_unwrap2, errno_unwrap3}
- // Note(flysand): 32-bit architectures sometimes take in a 64-bit argument in a
- // register pair. This function should help me avoid typing the same code a few times..
- when size_of(int) == 4 {
- // xxx64 system calls take some parameters as pairs of ulongs rather than a single pointer
- @(private)
- compat64_arg_pair :: #force_inline proc "contextless" (a: i64) -> (hi: uint, lo: uint) {
- no_sign := uint(a)
- hi = uint(no_sign >> 32)
- lo = uint(no_sign & 0xffff_ffff)
- return
- }
- } else {
- // ... and on 64-bit architectures it's just a long
- @(private)
- compat64_arg_pair :: #force_inline proc "contextless" (a: i64) -> (uint) {
- return uint(a)
- }
- }
|