// SPDX-License-Identifier: MPL-2.0 use crate::{ prelude::*, process::posix_thread::futex::{ futex_op_and_flags_from_u32, futex_requeue, futex_wait, futex_wait_bitset, futex_wake, futex_wake_bitset, FutexOp, FutexTimeout, }, syscall::SyscallReturn, }; pub fn sys_futex( futex_addr: Vaddr, futex_op: i32, futex_val: u32, utime_addr: u64, futex_new_addr: u64, bitset: u64, ctx: &Context, ) -> Result { // FIXME: we current ignore futex flags let (futex_op, futex_flags) = futex_op_and_flags_from_u32(futex_op as _)?; debug!( "futex_op = {:?}, futex_flags = {:?}, futex_addr = 0x{:x}", futex_op, futex_flags, futex_addr ); let get_futex_val = |val: i32| -> Result { if val < 0 { return_errno_with_message!(Errno::EINVAL, "the futex val must not be negative"); } Ok(val as usize) }; let get_futex_timeout = |timeout_addr| -> Result> { if timeout_addr == 0 { return Ok(None); } // TODO: parse a timeout todo!() }; let res = match futex_op { FutexOp::FUTEX_WAIT => { let timeout = get_futex_timeout(utime_addr)?; futex_wait(futex_addr as _, futex_val as _, &timeout).map(|_| 0) } FutexOp::FUTEX_WAIT_BITSET => { let timeout = get_futex_timeout(utime_addr)?; futex_wait_bitset(futex_addr as _, futex_val as _, &timeout, bitset as _).map(|_| 0) } FutexOp::FUTEX_WAKE => { let max_count = get_futex_val(futex_val as i32)?; futex_wake(futex_addr as _, max_count).map(|count| count as isize) } FutexOp::FUTEX_WAKE_BITSET => { let max_count = get_futex_val(futex_val as i32)?; futex_wake_bitset(futex_addr as _, max_count, bitset as _).map(|count| count as isize) } FutexOp::FUTEX_REQUEUE => { let max_nwakes = get_futex_val(futex_val as i32)?; let max_nrequeues = get_futex_val(utime_addr as i32)?; futex_requeue( futex_addr as _, max_nwakes, max_nrequeues, futex_new_addr as _, ) .map(|nwakes| nwakes as _) } _ => panic!("Unsupported futex operations"), }?; debug!("futex returns, tid= {} ", ctx.thread.tid()); Ok(SyscallReturn::Return(res as _)) }