From 79987da8219d4adfc681c10a445a488a289f2ace Mon Sep 17 00:00:00 2001 From: Anhad Singh Date: Mon, 9 Feb 2026 15:47:14 +1100 Subject: [PATCH 1/6] misc(tests/Makefile): add pthread/tls Signed-off-by: Anhad Singh --- tests/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Makefile b/tests/Makefile index 40b90dca1f..c7d4d70e1d 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -303,6 +303,7 @@ VARIED_NAMES=\ pthread/rwlock_randtest \ pthread/mutex_recursive \ pthread/timeout \ + pthread/tls \ grp/getgrouplist \ grp/getgrgid_r \ grp/getgrnam_r \ From aa317238f1ededeb33d07882d8050c75e05af449 Mon Sep 17 00:00:00 2001 From: Anhad Singh Date: Thu, 12 Feb 2026 11:57:36 +1100 Subject: [PATCH 2/6] feat(redox/fcntl): `F_SETLK` Signed-off-by: Anhad Singh --- src/platform/redox/mod.rs | 63 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index bb5d491321..ee064aeb0e 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -10,7 +10,7 @@ use redox_rt::{ sys::{Resugid, WaitpidTarget}, }; use syscall::{ - self, EILSEQ, Error, MODE_PERM, + self, EILSEQ, Error, MODE_PERM, StdFsCallKind, StdFsCallMeta, data::{Map, TimeSpec as redox_timespec}, dirent::{DirentHeader, DirentKind}, }; @@ -30,7 +30,10 @@ use crate::{ EBADF, EBADFD, EBADR, EEXIST, EFAULT, EFBIG, EINTR, EINVAL, EIO, ENAMETOOLONG, ENOENT, ENOMEM, ENOSYS, EOPNOTSUPP, EPERM, ERANGE, }, - fcntl::{self, AT_EMPTY_PATH, AT_FDCWD, AT_SYMLINK_NOFOLLOW}, + fcntl::{ + self, AT_EMPTY_PATH, AT_FDCWD, AT_SYMLINK_NOFOLLOW, F_GETLK, F_RDLCK, F_SETLK, + F_SETLKW, F_UNLCK, F_WRLCK, flock, + }, limits, pthread::{pthread_cancel, pthread_create}, signal::{NSIG, SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD, SIGRTMIN, sigevent}, @@ -293,6 +296,62 @@ impl Pal for Sys { } fn fcntl(fd: c_int, cmd: c_int, args: c_ulonglong) -> Result { + match cmd { + F_SETLK => { + let flock = unsafe { &mut *(args as *mut flock) }; + // let file_off = Self::lseek(fd, 0, SEEK_SET)?; + + // TODO: overflow checks + let (start, len) = match flock.l_whence as i32 { + SEEK_SET => { + let (start, len) = if flock.l_len < 0 { + (flock.l_start + flock.l_len, -flock.l_len) + } else { + (flock.l_start, flock.l_len) + }; + + if start < 0 { + return Err(Errno(EINVAL)); + } + + assert!(len >= 0); + (start as u64, len as u64) + } + // FIXME: SEEK_CUR, SEEK_END + c => unreachable!("{c}"), + }; + + match flock.l_type as i32 { + F_UNLCK => { + let meta = StdFsCallMeta::new(StdFsCallKind::Unlock, start, len); + syscall::std_fs_call(fd as usize, &mut [], &meta)?; + return Ok(0); + } + + F_RDLCK | F_WRLCK => { + let meta = StdFsCallMeta::new( + StdFsCallKind::Lock, + start, + len | if flock.l_type as i32 == F_WRLCK { + 1 << 63 + } else { + 0 + }, + ); + syscall::std_fs_call(fd as usize, &mut [], &meta)?; + return Ok(0); + } + + _ => return Err(Errno(EINVAL)), + }; + } + + F_GETLK => log::warn!("F_GETLK: not yet implemented"), + F_SETLKW => log::warn!("F_SETLKW: not yet implemented"), + + _ => {} + } + Ok(syscall::fcntl(fd as usize, cmd as usize, args as usize)? as c_int) } From aa79ec49ad971d8d479e63598e7341ac966ec336 Mon Sep 17 00:00:00 2001 From: Anhad Singh Date: Tue, 17 Feb 2026 15:41:48 +1100 Subject: [PATCH 3/6] misc(Makefile): cleanup Signed-off-by: Anhad Singh --- Makefile | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index bdb822d45c..3361676211 100644 --- a/Makefile +++ b/Makefile @@ -137,9 +137,7 @@ $(BUILD)/$(PROFILE)/ld_so: $(BUILD)/$(PROFILE)/ld_so.o $(BUILD)/$(PROFILE)/crti. # TODO: merge ld.so with libc.so: --dynamic-list=dynamic-list-file $(LD) --shared -Bsymbolic --no-relax -T ld_so/ld_script/$(TARGET).ld --allow-multiple-definition --gc-sections $^ -o $@ -# Debug targets - -$(BUILD)/debug/libc.a: $(BUILD)/debug/librelibc.a $(BUILD)/openlibm/libopenlibm.a +$(BUILD)/$(PROFILE)/libc.a: $(BUILD)/$(PROFILE)/librelibc.a $(BUILD)/openlibm/libopenlibm.a echo "create $@" > "$@.mri" for lib in $^; do\ echo "addlib $$lib" >> "$@.mri"; \ @@ -148,6 +146,8 @@ $(BUILD)/debug/libc.a: $(BUILD)/debug/librelibc.a $(BUILD)/openlibm/libopenlibm. echo "end" >> "$@.mri" $(AR) -M < "$@.mri" +# Debug targets + $(BUILD)/debug/librelibc.a: $(SRC) $(CARGO) rustc $(CARGOFLAGS) -- --emit link=$@ -g -C debug-assertions=no $(RUSTCFLAGS) ./renamesyms.sh "$@" "$(BUILD)/debug/deps/" @@ -172,15 +172,6 @@ $(BUILD)/debug/ld_so.o: $(SRC) # Release targets -$(BUILD)/release/libc.a: $(BUILD)/release/librelibc.a $(BUILD)/openlibm/libopenlibm.a - echo "create $@" > "$@.mri" - for lib in $^; do\ - echo "addlib $$lib" >> "$@.mri"; \ - done - echo "save" >> "$@.mri" - echo "end" >> "$@.mri" - $(AR) -M < "$@.mri" - $(BUILD)/release/librelibc.a: $(SRC) $(CARGO) rustc --release $(CARGOFLAGS) -- --emit link=$@ $(RUSTCFLAGS) @# TODO: Better to only allow a certain whitelisted set of symbols? Perhaps From 73ef851d59a52d3f2705ddf4c52891a53dbefcf7 Mon Sep 17 00:00:00 2001 From: Anhad Singh Date: Tue, 24 Feb 2026 22:36:19 +1100 Subject: [PATCH 4/6] feat(redox): `F_OFD_SETLK` Signed-off-by: Anhad Singh --- src/platform/redox/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index ee064aeb0e..d1b2c85aaa 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -31,8 +31,8 @@ use crate::{ ENOMEM, ENOSYS, EOPNOTSUPP, EPERM, ERANGE, }, fcntl::{ - self, AT_EMPTY_PATH, AT_FDCWD, AT_SYMLINK_NOFOLLOW, F_GETLK, F_RDLCK, F_SETLK, - F_SETLKW, F_UNLCK, F_WRLCK, flock, + self, AT_EMPTY_PATH, AT_FDCWD, AT_SYMLINK_NOFOLLOW, F_GETLK, F_OFD_SETLK, F_RDLCK, + F_SETLK, F_SETLKW, F_UNLCK, F_WRLCK, flock, }, limits, pthread::{pthread_cancel, pthread_create}, @@ -297,7 +297,8 @@ impl Pal for Sys { fn fcntl(fd: c_int, cmd: c_int, args: c_ulonglong) -> Result { match cmd { - F_SETLK => { + F_SETLK | F_OFD_SETLK => { + let is_ofd = cmd == F_OFD_SETLK; let flock = unsafe { &mut *(args as *mut flock) }; // let file_off = Self::lseek(fd, 0, SEEK_SET)?; @@ -321,6 +322,7 @@ impl Pal for Sys { c => unreachable!("{c}"), }; + let start = start | if is_ofd { 1 << 63 } else { 0 }; match flock.l_type as i32 { F_UNLCK => { let meta = StdFsCallMeta::new(StdFsCallKind::Unlock, start, len); From d1c031f1b56b3d896706fd96e7beaf9f4db2da60 Mon Sep 17 00:00:00 2001 From: Anhad Singh Date: Wed, 25 Feb 2026 01:43:45 +1100 Subject: [PATCH 5/6] feat(redox): F_{OFD}_{GETLK,SETLK} Signed-off-by: Anhad Singh --- src/platform/redox/mod.rs | 135 +++++++++++++++++++++++++++++++------- 1 file changed, 111 insertions(+), 24 deletions(-) diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index d1b2c85aaa..30dfbf3317 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -4,13 +4,14 @@ use core::{ num::NonZeroU64, ptr, slice, str, }; +use object::bytes_of_slice_mut; use redox_rt::{ RtTcb, protocol::{WaitFlags, wifstopped}, sys::{Resugid, WaitpidTarget}, }; use syscall::{ - self, EILSEQ, Error, MODE_PERM, StdFsCallKind, StdFsCallMeta, + self, EILSEQ, ESRCH, Error, MODE_PERM, StdFsCallKind, StdFsCallMeta, data::{Map, TimeSpec as redox_timespec}, dirent::{DirentHeader, DirentKind}, }; @@ -31,8 +32,8 @@ use crate::{ ENOMEM, ENOSYS, EOPNOTSUPP, EPERM, ERANGE, }, fcntl::{ - self, AT_EMPTY_PATH, AT_FDCWD, AT_SYMLINK_NOFOLLOW, F_GETLK, F_OFD_SETLK, F_RDLCK, - F_SETLK, F_SETLKW, F_UNLCK, F_WRLCK, flock, + self, AT_EMPTY_PATH, AT_FDCWD, AT_SYMLINK_NOFOLLOW, F_GETLK, F_OFD_GETLK, F_OFD_SETLK, + F_RDLCK, F_SETLK, F_SETLKW, F_UNLCK, F_WRLCK, flock, }, limits, pthread::{pthread_cancel, pthread_create}, @@ -300,29 +301,17 @@ impl Pal for Sys { F_SETLK | F_OFD_SETLK => { let is_ofd = cmd == F_OFD_SETLK; let flock = unsafe { &mut *(args as *mut flock) }; - // let file_off = Self::lseek(fd, 0, SEEK_SET)?; - // TODO: overflow checks - let (start, len) = match flock.l_whence as i32 { - SEEK_SET => { - let (start, len) = if flock.l_len < 0 { - (flock.l_start + flock.l_len, -flock.l_len) - } else { - (flock.l_start, flock.l_len) - }; + let (start, len) = Self::relative_to_absolute_foffset( + fd as usize, + flock.l_whence, + flock.l_start, + flock.l_len, + )?; - if start < 0 { - return Err(Errno(EINVAL)); - } + let start = start as u64 | if is_ofd { 1 << 63 } else { 0 }; + let len = len as u64; - assert!(len >= 0); - (start as u64, len as u64) - } - // FIXME: SEEK_CUR, SEEK_END - c => unreachable!("{c}"), - }; - - let start = start | if is_ofd { 1 << 63 } else { 0 }; match flock.l_type as i32 { F_UNLCK => { let meta = StdFsCallMeta::new(StdFsCallKind::Unlock, start, len); @@ -348,7 +337,71 @@ impl Pal for Sys { }; } - F_GETLK => log::warn!("F_GETLK: not yet implemented"), + F_GETLK | F_OFD_GETLK => { + let is_ofd = cmd == F_OFD_GETLK; + let flock = unsafe { &mut *(args as *mut flock) }; + + if is_ofd && flock.l_pid != 0 { + log::warn!("POSIX requires `l_pid` to be 0 on input for `F_OFD_GETLK`"); + return Err(Errno(EINVAL)); + } + + let (start, len) = Self::relative_to_absolute_foffset( + fd as usize, + flock.l_whence, + flock.l_start, + flock.l_len, + )?; + + let mut start = start as u64; + if is_ofd { + start |= 1 << 63; + } + + let mut len = len as u64; + if flock.l_type as i32 == F_WRLCK { + len |= 1 << 63; + } + + let meta = StdFsCallMeta::new(StdFsCallKind::GetLock, 0, 0); + let payload = &mut [start, len]; + // `pid` if traditional POSIX otherwise 0 + let val = + match syscall::std_fs_call(fd as usize, bytes_of_slice_mut(payload), &meta) { + // According to POSIX Issue 8: + // > If no lock is found that would prevent this lock from being created, then + // > the structure shall be left unchanged except for the lock type in `l_type` + // > which shall be set to F_UNLCK. + Err(err) if err.errno == ESRCH => { + flock.l_type = F_UNLCK as i16; + return Ok(0); + } + + Ok(val) => val, + Err(err) => return Err(Errno(err.errno)), + }; + + debug_assert_ne!(payload[0] & (1 << 63), 1 << 63); + + if is_ofd { + flock.l_pid = -1; + } else { + flock.l_pid = val as i32; + } + + let len = payload[1] & !(1 << 63); + if payload[1] & (1 << 63) == (1 << 63) { + flock.l_type = F_WRLCK as i16; + } else { + flock.l_type = F_RDLCK as i16; + } + + flock.l_whence = SEEK_SET as _; + flock.l_start = start as i64; + flock.l_len = len as i64; + return Ok(0); + } + F_SETLKW => log::warn!("F_SETLKW: not yet implemented"), _ => {} @@ -1555,3 +1608,37 @@ impl Pal for Sys { unsafe { redox_rt::thread::exit_this_thread(stack_base, stack_size) } } } + +impl Sys { + fn relative_to_absolute_foffset( + fd: usize, + whence: c_short, + start: off_t, + len: off_t, + ) -> Result<(off_t, off_t)> { + // let file_off = Self::lseek(fd, 0, SEEK_SET)?; + match whence as i32 { + SEEK_SET => { + let (start, len) = if len < 0 { + (start + len, -len) + } else { + (start, len) + }; + + if start < 0 { + return Err(Errno(EINVAL)); + } + + assert!(len >= 0); + Ok((start, len)) + } + // FIXME: andypython: SEEK_CUR, SEEK_END + c => { + log::warn!( + "Sys::relative_to_absolute_foffset: whence={whence} not yet implemented" + ); + Ok((0, 0)) + } + } + } +} From fe89f12da6124bd130660042953531c05eef3e50 Mon Sep 17 00:00:00 2001 From: Anhad Singh Date: Thu, 26 Feb 2026 02:17:53 +1100 Subject: [PATCH 6/6] chore: bump `redox_syscall` Signed-off-by: Anhad Singh --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7103310a61..d0be2734d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -463,9 +463,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" +checksum = "6d94dd2f7cd932d4dc02cc8b2b50dfd38bd079a4e5d79198b99743d7fcf9a4b4" dependencies = [ "bitflags", ]