| ... | @@ -323,6 +323,113 @@ pub fn futex_wake(uaddr: *const i32, futex_op: u32, val: i32) usize { | ... | @@ -323,6 +323,113 @@ pub fn futex_wake(uaddr: *const i32, futex_op: u32, val: i32) usize { |
| 323 | return syscall3(.futex, @intFromPtr(uaddr), futex_op, @as(u32, @bitCast(val))); | 323 | return syscall3(.futex, @intFromPtr(uaddr), futex_op, @as(u32, @bitCast(val))); |
| 324 | } | 324 | } |
| 325 | | 325 | |
| | 326 | /// Given an array of `futex_waitv`, wait on each uaddr. |
| | 327 | /// The thread wakes if a futex_wake() is performed at any uaddr. |
| | 328 | /// The syscall returns immediately if any waiter has *uaddr != val. |
| | 329 | /// timeout is an optional timeout value for the operation. |
| | 330 | /// Each waiter has individual flags. |
| | 331 | /// The `flags` argument for the syscall should be used solely for specifying |
| | 332 | /// the timeout as realtime, if needed. |
| | 333 | /// Flags for private futexes, sizes, etc. should be used on the |
| | 334 | /// individual flags of each waiter. |
| | 335 | /// |
| | 336 | /// Returns the array index of one of the woken futexes. |
| | 337 | /// No further information is provided: any number of other futexes may also |
| | 338 | /// have been woken by the same event, and if more than one futex was woken, |
| | 339 | /// the retrned index may refer to any one of them. |
| | 340 | /// (It is not necessaryily the futex with the smallest index, nor the one |
| | 341 | /// most recently woken, nor...) |
| | 342 | pub fn futex2_waitv( |
| | 343 | /// List of futexes to wait on. |
| | 344 | waiters: [*]futex_waitv, |
| | 345 | /// Length of `waiters`. |
| | 346 | nr_futexes: u32, |
| | 347 | /// Flag for timeout (monotonic/realtime). |
| | 348 | flags: u32, |
| | 349 | /// Optional absolute timeout. |
| | 350 | timeout: ?*const timespec, |
| | 351 | /// Clock to be used for the timeout, realtime or monotonic. |
| | 352 | clockid: i32, |
| | 353 | ) usize { |
| | 354 | return syscall6( |
| | 355 | .futex_waitv, |
| | 356 | @intFromPtr(waiters), |
| | 357 | nr_futexes, |
| | 358 | flags, |
| | 359 | @intFromPtr(timeout), |
| | 360 | @bitCast(@as(isize, clockid)), |
| | 361 | ); |
| | 362 | } |
| | 363 | |
| | 364 | /// Wait on a futex. |
| | 365 | /// Identical to `FUTEX.WAIT`, except it is part of the futex2 family of calls. |
| | 366 | pub fn futex2_wait( |
| | 367 | /// Address of the futex to wait on. |
| | 368 | uaddr: *const anyopaque, |
| | 369 | /// Value of `uaddr`. |
| | 370 | val: usize, |
| | 371 | /// Bitmask. |
| | 372 | mask: usize, |
| | 373 | /// `FUTEX2` flags. |
| | 374 | flags: u32, |
| | 375 | /// Optional absolute timeout. |
| | 376 | timeout: *const timespec, |
| | 377 | /// Clock to be used for the timeout, realtime or monotonic. |
| | 378 | clockid: i32, |
| | 379 | ) usize { |
| | 380 | return syscall6( |
| | 381 | .futex_wait, |
| | 382 | @intFromPtr(uaddr), |
| | 383 | val, |
| | 384 | mask, |
| | 385 | flags, |
| | 386 | @intFromPtr(timeout), |
| | 387 | @bitCast(@as(isize, clockid)), |
| | 388 | ); |
| | 389 | } |
| | 390 | |
| | 391 | /// Wake a number of futexes. |
| | 392 | /// Identical to `FUTEX.WAKE`, except it is part of the futex2 family of calls. |
| | 393 | pub fn futex2_wake( |
| | 394 | /// Address of the futex(es) to wake. |
| | 395 | uaddr: [*]const anyopaque, |
| | 396 | /// Bitmask |
| | 397 | mask: usize, |
| | 398 | /// Number of the futexes to wake. |
| | 399 | nr: i32, |
| | 400 | /// `FUTEX2` flags. |
| | 401 | flags: u32, |
| | 402 | ) usize { |
| | 403 | return syscall4( |
| | 404 | .futex_wake, |
| | 405 | @intFromPtr(uaddr), |
| | 406 | mask, |
| | 407 | @bitCast(@as(isize, nr)), |
| | 408 | flags, |
| | 409 | ); |
| | 410 | } |
| | 411 | |
| | 412 | /// Requeue a waiter from one futex to another. |
| | 413 | /// Identical to `FUTEX.CMP_REQUEUE`, except it is part of the futex2 family of calls. |
| | 414 | pub fn futex2_requeue( |
| | 415 | /// Array describing the source and destination futex. |
| | 416 | waiters: [*]futex_waitv, |
| | 417 | /// Unsed. |
| | 418 | flags: u32, |
| | 419 | /// Number of futexes to wake. |
| | 420 | nr_wake: i32, |
| | 421 | /// Number of futexes to requeue. |
| | 422 | nr_requeue: i32, |
| | 423 | ) usize { |
| | 424 | return syscall4( |
| | 425 | .futex_requeue, |
| | 426 | @intFromPtr(waiters), |
| | 427 | flags, |
| | 428 | @bitCast(@as(isize, nr_wake)), |
| | 429 | @bitCast(@as(isize, nr_requeue)), |
| | 430 | ); |
| | 431 | } |
| | 432 | |
| 326 | pub fn getcwd(buf: [*]u8, size: usize) usize { | 433 | pub fn getcwd(buf: [*]u8, size: usize) usize { |
| 327 | return syscall2(.getcwd, @intFromPtr(buf), size); | 434 | return syscall2(.getcwd, @intFromPtr(buf), size); |
| 328 | } | 435 | } |
| ... | @@ -1901,10 +2008,17 @@ pub fn ptrace( | ... | @@ -1901,10 +2008,17 @@ pub fn ptrace( |
| 1901 | ); | 2008 | ); |
| 1902 | } | 2009 | } |
| 1903 | | 2010 | |
| | 2011 | /// Query the page cache statistics of a file. |
| 1904 | pub fn cachestat( | 2012 | pub fn cachestat( |
| | 2013 | /// The open file descriptor to retrieve statistics from. |
| 1905 | fd: fd_t, | 2014 | fd: fd_t, |
| | 2015 | /// The byte range in `fd` to query. |
| | 2016 | /// When `len > 0`, the range is `[off..off + len]`. |
| | 2017 | /// When `len` == 0, the range is from `off` to the end of `fd`. |
| 1906 | cstat_range: *const cache_stat_range, | 2018 | cstat_range: *const cache_stat_range, |
| | 2019 | /// The structure where page cache statistics are stored. |
| 1907 | cstat: *cache_stat, | 2020 | cstat: *cache_stat, |
| | 2021 | /// Currently unused, and must be set to `0`. |
| 1908 | flags: u32, | 2022 | flags: u32, |
| 1909 | ) usize { | 2023 | ) usize { |
| 1910 | return syscall4( | 2024 | return syscall4( |
| ... | @@ -1916,6 +2030,10 @@ pub fn cachestat( | ... | @@ -1916,6 +2030,10 @@ pub fn cachestat( |
| 1916 | ); | 2030 | ); |
| 1917 | } | 2031 | } |
| 1918 | | 2032 | |
| | 2033 | pub fn map_shadow_stack(addr: u64, size: u64, flags: u32) usize { |
| | 2034 | return syscall3(.map_shadow_stack, addr, size, flags); |
| | 2035 | } |
| | 2036 | |
| 1919 | pub const E = switch (native_arch) { | 2037 | pub const E = switch (native_arch) { |
| 1920 | .mips, .mipsel => @import("linux/errno/mips.zig").E, | 2038 | .mips, .mipsel => @import("linux/errno/mips.zig").E, |
| 1921 | .sparc, .sparcel, .sparc64 => @import("linux/errno/sparc.zig").E, | 2039 | .sparc, .sparcel, .sparc64 => @import("linux/errno/sparc.zig").E, |
| ... | @@ -2016,6 +2134,19 @@ pub const FUTEX = struct { | ... | @@ -2016,6 +2134,19 @@ pub const FUTEX = struct { |
| 2016 | pub const PRIVATE_FLAG = 128; | 2134 | pub const PRIVATE_FLAG = 128; |
| 2017 | | 2135 | |
| 2018 | pub const CLOCK_REALTIME = 256; | 2136 | pub const CLOCK_REALTIME = 256; |
| | 2137 | |
| | 2138 | /// Max numbers of elements in a `futex_waitv` array. |
| | 2139 | pub const WAITV_MAX = 128; |
| | 2140 | }; |
| | 2141 | |
| | 2142 | pub const FUTEX2 = struct { |
| | 2143 | pub const SIZE_U8 = 0x00; |
| | 2144 | pub const SIZE_U16 = 0x01; |
| | 2145 | pub const SIZE_U32 = 0x02; |
| | 2146 | pub const SIZE_U64 = 0x03; |
| | 2147 | pub const NUMA = 0x04; |
| | 2148 | |
| | 2149 | pub const PRIVATE = FUTEX.PRIVATE_FLAG; |
| 2019 | }; | 2150 | }; |
| 2020 | | 2151 | |
| 2021 | pub const PROT = struct { | 2152 | pub const PROT = struct { |
| ... | @@ -6100,15 +6231,41 @@ pub const PTRACE = struct { | ... | @@ -6100,15 +6231,41 @@ pub const PTRACE = struct { |
| 6100 | pub const GET_SYSCALL_INFO = 0x420e; | 6231 | pub const GET_SYSCALL_INFO = 0x420e; |
| 6101 | }; | 6232 | }; |
| 6102 | | 6233 | |
| | 6234 | /// A waiter for vectorized wait. |
| | 6235 | pub const futex_waitv = extern struct { |
| | 6236 | // Expected value at uaddr |
| | 6237 | val: u64, |
| | 6238 | /// User address to wait on. |
| | 6239 | uaddr: u64, |
| | 6240 | /// Flags for this waiter. |
| | 6241 | flags: u32, |
| | 6242 | /// Reserved memeber to preserve alignment. |
| | 6243 | /// Should be 0. |
| | 6244 | __reserved: u32, |
| | 6245 | }; |
| | 6246 | |
| 6103 | pub const cache_stat_range = extern struct { | 6247 | pub const cache_stat_range = extern struct { |
| 6104 | off: u64, | 6248 | off: u64, |
| 6105 | len: u64, | 6249 | len: u64, |
| 6106 | }; | 6250 | }; |
| 6107 | | 6251 | |
| 6108 | pub const cache_stat = extern struct { | 6252 | pub const cache_stat = extern struct { |
| | 6253 | /// Number of cached pages. |
| 6109 | cache: u64, | 6254 | cache: u64, |
| | 6255 | /// Number of dirty pages. |
| 6110 | dirty: u64, | 6256 | dirty: u64, |
| | 6257 | /// Number of pages marked for writeback. |
| 6111 | writeback: u64, | 6258 | writeback: u64, |
| | 6259 | /// Number of pages evicted from the cache. |
| 6112 | evicted: u64, | 6260 | evicted: u64, |
| | 6261 | /// Number of recently evicted pages. |
| | 6262 | /// A page is recently evicted if its last eviction was recent enough that its |
| | 6263 | /// reentry to the cache would indicate that it is actively being used by the |
| | 6264 | /// system, and that there is memory pressure on the system. |
| 6113 | recently_evicted: u64, | 6265 | recently_evicted: u64, |
| 6114 | }; | 6266 | }; |
| | 6267 | |
| | 6268 | pub const SHADOW_STACK = struct { |
| | 6269 | /// Set up a restore token in the shadow stack. |
| | 6270 | pub const SET_TOKEN: u64 = 1 << 0; |
| | 6271 | }; |