Merge branch 'flock' into 'master'

feat(redox): flocking

See merge request redox-os/relibc!1037
This commit is contained in:
Jeremy Soller
2026-02-25 08:20:46 -07:00
4 changed files with 156 additions and 16 deletions
Generated
+2 -2
View File
@@ -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",
]
+3 -12
View File
@@ -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
+150 -2
View File
@@ -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,
self, EILSEQ, ESRCH, Error, MODE_PERM, StdFsCallKind, StdFsCallMeta,
data::{Map, TimeSpec as redox_timespec},
dirent::{DirentHeader, DirentKind},
};
@@ -30,7 +31,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_OFD_GETLK, F_OFD_SETLK,
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 +297,116 @@ impl Pal for Sys {
}
fn fcntl(fd: c_int, cmd: c_int, args: c_ulonglong) -> Result<c_int> {
match cmd {
F_SETLK | F_OFD_SETLK => {
let is_ofd = cmd == F_OFD_SETLK;
let flock = unsafe { &mut *(args as *mut flock) };
let (start, len) = Self::relative_to_absolute_foffset(
fd as usize,
flock.l_whence,
flock.l_start,
flock.l_len,
)?;
let start = start as u64 | if is_ofd { 1 << 63 } else { 0 };
let len = len as u64;
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 | 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"),
_ => {}
}
Ok(syscall::fcntl(fd as usize, cmd as usize, args as usize)? as c_int)
}
@@ -1490,3 +1604,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))
}
}
}
}
+1
View File
@@ -303,6 +303,7 @@ VARIED_NAMES=\
pthread/rwlock_randtest \
pthread/mutex_recursive \
pthread/timeout \
pthread/tls \
grp/getgrouplist \
grp/getgrgid_r \
grp/getgrnam_r \