0.3.0: converge kernel onto upstream master

- Rebase all Red Bear kernel changes onto upstream master (4d5d36d4).
- Update version to 0.5.12+rb0.3.0 and add Red Bear author attribution.
- Switch redox_syscall direct dependency to local fork path (../syscall).
- Bump rust-toolchain.toml to nightly-2026-05-24.
- Regenerate Cargo.lock for +rb0.3.0 suffixes and path deps.
This commit is contained in:
2026-07-06 18:43:52 +03:00
parent 4d5d36d44e
commit ca67b1da37
66 changed files with 2935 additions and 2225 deletions
+280 -64
View File
@@ -1,7 +1,6 @@
use alloc::{collections::BTreeSet, sync::Arc, vec::Vec};
use arrayvec::ArrayString;
use core::{
cmp::Reverse,
mem::{self, size_of, ManuallyDrop},
num::NonZeroUsize,
sync::atomic::{AtomicU32, Ordering},
@@ -61,9 +60,6 @@ impl Status {
pub fn is_soft_blocked(&self) -> bool {
matches!(self, Self::Blocked)
}
pub fn is_dead(&self) -> bool {
matches!(self, Self::Dead { .. })
}
}
#[derive(Clone, Debug)]
@@ -77,7 +73,7 @@ pub enum HardBlockedReason {
NotYetStarted,
}
pub const CONTEXT_NAME_CAPAC: usize = 32;
const CONTEXT_NAME_CAPAC: usize = 32;
#[derive(Debug)]
pub enum SyscallFrame {
@@ -144,16 +140,6 @@ pub struct Context {
pub fmap_ret: Option<Frame>,
/// Priority
pub prio: usize,
/// Virtual Run Time
pub vtime: u64,
/// Virtual Deadline
pub vd: u64,
/// Remaining Slice of allocated time
pub rem_slice: u64,
/// Is currently active?
pub is_active: bool,
/// Key for the RunQueue
pub queue_key: Option<(u64, Reverse<u64>, u32)>,
// TODO: id can reappear after wraparound?
pub owner_proc_id: Option<NonZeroUsize>,
@@ -162,6 +148,8 @@ pub struct Context {
pub euid: u32,
pub egid: u32,
pub pid: usize,
/// Supplementary group IDs for access control decisions.
pub groups: Vec<u32>,
// See [`PreemptGuard`]
//
@@ -212,17 +200,13 @@ impl Context {
userspace: false,
fmap_ret: None,
prio: 20,
vtime: 0,
vd: 0,
rem_slice: 0,
is_active: false,
queue_key: None,
being_sigkilled: false,
owner_proc_id,
euid: 0,
egid: 0,
pid: 0,
groups: Vec::new(),
#[cfg(feature = "syscall_debug")]
syscall_debug_info: crate::syscall::debug::SyscallDebugInfo::default(),
@@ -287,8 +271,51 @@ impl Context {
}
}
/// Bulk-insert multiple files
pub fn bulk_insert_files(
/// Add a file to the lowest available slot.
/// Return the file descriptor number or None if no slot was found
pub fn add_file(
&self,
file: FileDescriptor,
lock_token: &mut LockToken<L4>,
) -> Option<FileHandle> {
self.add_file_min(file, 0, lock_token)
}
/// Add a file to the lowest available slot greater than or equal to min.
/// Return the file descriptor number or None if no slot was found
pub fn add_file_min(
&self,
file: FileDescriptor,
min: usize,
lock_token: &mut LockToken<L4>,
) -> Option<FileHandle> {
self.files.write(lock_token.token()).add_file_min(file, min)
}
/// Bulk-add multiple files to the POSIX file table
pub fn bulk_add_files_posix(
&self,
files_to_add: Vec<FileDescriptor>,
lock_token: &mut LockToken<L4>,
) -> Option<Vec<FileHandle>> {
self.files
.write(lock_token.token())
.bulk_add_files_posix(files_to_add)
}
/// Bulk-insert multiple files into to the upper file table contiguously
pub fn bulk_insert_files_upper(
&self,
files_to_insert: Vec<FileDescriptor>,
lock_token: &mut LockToken<L4>,
) -> Option<Vec<FileHandle>> {
self.files
.write(lock_token.token())
.bulk_insert_files_upper(files_to_insert)
}
/// Bulk-insert multiple files into to the upper file table manually
pub fn bulk_insert_files_upper_manual(
&self,
files_to_insert: Vec<FileDescriptor>,
handles: &[FileHandle],
@@ -296,7 +323,7 @@ impl Context {
) -> Result<()> {
self.files
.write(lock_token.token())
.bulk_insert_files(files_to_insert, handles)
.bulk_insert_files_upper_manual(files_to_insert, handles)
}
/// Get a file
@@ -426,11 +453,12 @@ impl Context {
let kstack = self.kstack.as_ref()?;
Some(unsafe { &mut *kstack.initial_top().sub(size_of::<InterruptStack>()).cast() })
}
pub fn sigcontrol(&self) -> Option<(&Sigcontrol, &SigProcControl, &SignalState)> {
let (for_thread, for_proc) = Self::sigcontrol_raw(self.sig.as_ref()?);
Some((for_thread, for_proc, self.sig.as_ref()?))
pub fn sigcontrol(&mut self) -> Option<(&Sigcontrol, &SigProcControl, &mut SignalState)> {
Some(Self::sigcontrol_raw(self.sig.as_mut()?))
}
pub fn sigcontrol_raw(sig: &SignalState) -> (&Sigcontrol, &SigProcControl) {
pub fn sigcontrol_raw(
sig: &mut SignalState,
) -> (&Sigcontrol, &SigProcControl, &mut SignalState) {
let check = |off| {
assert_eq!(usize::from(off) % align_of::<usize>(), 0);
assert!(usize::from(off).saturating_add(size_of::<Sigcontrol>()) < PAGE_SIZE);
@@ -447,13 +475,14 @@ impl Context {
.byte_add(usize::from(sig.procctl_off))
};
(for_thread, for_proc)
(for_thread, for_proc, sig)
}
pub fn caller_ctx(&self) -> CallerCtx {
CallerCtx {
uid: self.euid,
gid: self.egid,
pid: self.pid,
groups: self.groups.clone(),
}
}
}
@@ -596,7 +625,7 @@ impl core::fmt::Debug for Kstack {
#[derive(Clone, Debug, Default)]
pub struct FdTbl {
pub lower_fdtbl: Vec<Option<FileDescriptor>>,
pub posix_fdtbl: Vec<Option<FileDescriptor>>,
pub upper_fdtbl: Vec<Option<FileDescriptor>>,
active_count: usize,
}
@@ -606,32 +635,19 @@ pub type LockedFdTbl = RwLock<L5, FdTbl>;
impl FdTbl {
pub fn new() -> Self {
Self {
lower_fdtbl: Vec::new(),
posix_fdtbl: Vec::new(),
upper_fdtbl: Vec::new(),
active_count: 0,
}
}
pub fn resize(&mut self, which: usize, size: usize) -> Result<()> {
let (fdtbl, _) = self.select_fdtbl_mut(which);
if super::CONTEXT_MAX_FILES < size {
return Err(Error::new(EMFILE));
}
if size < fdtbl.len() {
return Err(Error::new(EINVAL));
}
fdtbl.resize(size, None);
Ok(())
}
fn strip_tags(index: usize) -> usize {
index & !UPPER_FDTBL_TAG
}
fn select_fdtbl(&self, index: usize) -> (&Vec<Option<FileDescriptor>>, usize) {
if index & UPPER_FDTBL_TAG == 0 {
(&self.lower_fdtbl, index)
(&self.posix_fdtbl, index)
} else {
(&self.upper_fdtbl, Self::strip_tags(index))
}
@@ -639,7 +655,7 @@ impl FdTbl {
fn select_fdtbl_mut(&mut self, index: usize) -> (&mut Vec<Option<FileDescriptor>>, usize) {
if index & UPPER_FDTBL_TAG == 0 {
(&mut self.lower_fdtbl, index)
(&mut self.posix_fdtbl, index)
} else {
(&mut self.upper_fdtbl, Self::strip_tags(index))
}
@@ -681,6 +697,67 @@ impl FdTbl {
Ok(())
}
pub fn add_file_min(&mut self, file: FileDescriptor, min: usize) -> Option<FileHandle> {
if self.active_count >= super::CONTEXT_MAX_FILES {
return None;
}
let tag = min & UPPER_FDTBL_TAG;
let (fdtbl, min) = self.select_fdtbl_mut(min);
// Find the first empty slot in the posix_fdtbl starting from `min`.
if let Some((pos, slot)) = fdtbl
.iter_mut()
.enumerate()
.skip(min)
.find(|(_, slot)| slot.is_none())
{
*slot = Some(file);
self.active_count += 1;
return Some(FileHandle::from(pos | tag));
};
let len = fdtbl.len();
// If no empty slot was found, we need to allocate a new slot.
if len >= min {
fdtbl.push(Some(file));
self.active_count += 1;
Some(FileHandle::from(len | tag))
} else {
self.insert_file(FileHandle::from(min | tag), file)
}
}
fn bulk_add_files_posix(
&mut self,
files_to_add: Vec<FileDescriptor>,
) -> Option<Vec<FileHandle>> {
let count = files_to_add.len();
if count == 0 {
return Some(Vec::new());
}
if self.active_count + count > super::CONTEXT_MAX_FILES {
return None;
}
let handles = self.find_free_posix_slots(count);
let max_index = handles[count - 1].get();
if self.posix_fdtbl.len() <= max_index {
// Resize the posix_fdtbl to accommodate the new files.
self.posix_fdtbl.resize(max_index + 1, None);
}
for (&handle, file) in handles.iter().zip(files_to_add) {
let index = handle.get();
self.posix_fdtbl[index] = Some(file);
}
self.active_count += count;
Some(handles)
}
fn insert_file(&mut self, i: FileHandle, file: FileDescriptor) -> Option<FileHandle> {
if self.active_count >= super::CONTEXT_MAX_FILES {
return None;
@@ -705,7 +782,31 @@ impl FdTbl {
}
}
fn bulk_insert_files(
fn bulk_insert_files_upper(
&mut self,
files_to_insert: Vec<FileDescriptor>,
) -> Option<Vec<FileHandle>> {
let count = files_to_insert.len();
if count == 0 {
return Some(Vec::new());
}
if self.active_count + count > super::CONTEXT_MAX_FILES {
return None;
}
let index = Self::strip_tags(self.find_free_upper_block(count).get());
let mut handles = Vec::with_capacity(count);
for (i, file) in files_to_insert.into_iter().enumerate() {
let current_index = index + i;
self.upper_fdtbl[current_index] = Some(file);
handles.push(FileHandle::from(current_index | UPPER_FDTBL_TAG));
}
self.active_count += count;
Some(handles)
}
fn bulk_insert_files_upper_manual(
&mut self,
files_to_insert: Vec<FileDescriptor>,
handles: &[FileHandle],
@@ -722,9 +823,20 @@ impl FdTbl {
}
self.validate_free_slots(handles)?;
for (file, &handle) in files_to_insert.into_iter().zip(handles) {
self.insert_file(handle, file).ok_or(Error::new(EMFILE))?;
let max_index = handles
.iter()
.map(|h| Self::strip_tags(h.get()))
.max()
.unwrap_or(0);
if self.upper_fdtbl.len() <= max_index {
self.upper_fdtbl.resize_with(max_index + 1, || None);
}
for (file, &handle) in files_to_insert.into_iter().zip(handles) {
let index = Self::strip_tags(handle.get());
self.upper_fdtbl[index] = Some(file);
}
self.active_count += count;
Ok(())
}
@@ -774,7 +886,7 @@ impl FdTbl {
.ok_or(Error::new(EBADF))
}
pub fn remove_file(&mut self, i: FileHandle) -> Option<FileDescriptor> {
fn remove_file(&mut self, i: FileHandle) -> Option<FileDescriptor> {
let index = i.get();
let (fdtbl, real_index) = self.select_fdtbl_mut(index);
@@ -786,7 +898,7 @@ impl FdTbl {
removed_file_opt
}
pub fn bulk_remove_files(&mut self, handles: &[FileHandle]) -> Result<Vec<FileDescriptor>> {
fn bulk_remove_files(&mut self, handles: &[FileHandle]) -> Result<Vec<FileDescriptor>> {
// Validate that all handles are valid before proceeding to avoid partial results.
self.validate_handles(handles)?;
@@ -798,6 +910,56 @@ impl FdTbl {
Ok(files)
}
fn find_free_posix_slots(&self, count: usize) -> Vec<FileHandle> {
let mut free_slots = Vec::with_capacity(count);
for (i, slot) in self.posix_fdtbl.iter().enumerate() {
if slot.is_none() {
free_slots.push(FileHandle::from(i));
if free_slots.len() == count {
return free_slots;
}
}
}
let mut current_len = self.posix_fdtbl.len();
while free_slots.len() < count {
free_slots.push(FileHandle::from(current_len));
current_len += 1;
}
free_slots
}
fn find_free_upper_block(&mut self, len: usize) -> FileHandle {
let mut start = 0;
let mut count = 0;
for (i, file_opt) in self.upper_fdtbl.iter().enumerate() {
if file_opt.is_none() {
if count == 0 {
start = i;
}
count += 1;
if count == len {
break;
}
} else {
count = 0;
}
}
if count < len {
if count == 0 {
start = self.upper_fdtbl.len();
}
let needed = len - count;
self.upper_fdtbl
.resize(self.upper_fdtbl.len() + needed, None);
}
FileHandle::from(start | UPPER_FDTBL_TAG)
}
pub fn force_close_all(&mut self, token: &mut CleanLockToken) {
for file_opt in self.iter_mut() {
if let Some(file) = file_opt.take() {
@@ -810,7 +972,7 @@ impl FdTbl {
impl FdTbl {
pub fn enumerate(&self) -> impl Iterator<Item = (usize, &Option<FileDescriptor>)> {
self.lower_fdtbl.iter().enumerate().chain(
self.posix_fdtbl.iter().enumerate().chain(
self.upper_fdtbl
.iter()
.enumerate()
@@ -819,19 +981,20 @@ impl FdTbl {
}
pub fn iter(&self) -> impl Iterator<Item = &Option<FileDescriptor>> {
self.lower_fdtbl.iter().chain(self.upper_fdtbl.iter())
self.posix_fdtbl.iter().chain(self.upper_fdtbl.iter())
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Option<FileDescriptor>> {
self.lower_fdtbl
self.posix_fdtbl
.iter_mut()
.chain(self.upper_fdtbl.iter_mut())
}
}
pub fn bulk_insert_fds(
pub fn bulk_add_fds(
descriptions: Vec<Arc<LockedFileDescription>>,
payload: UserSliceRw,
cloexec: bool,
token: &mut LockToken<L1>,
) -> Result<usize> {
let cnt = descriptions.len();
@@ -841,18 +1004,71 @@ pub fn bulk_insert_fds(
if descriptions.is_empty() {
return Ok(0);
}
let files_iter = descriptions
.into_iter()
.map(|description| FileDescriptor { description });
let current_lock = context::current();
let mut current = current_lock.read(token.token());
let mut current = current_lock.write(token.token());
let (current, mut token) = current.token_split();
let handles: Vec<FileHandle> = payload
.usizes()
.map(|res| res.map(|i| FileHandle::from(i)))
.collect::<Result<_, _>>()?;
let files = files_iter.collect::<Vec<_>>();
current.bulk_insert_files(files, &handles, &mut token)?;
let files: Vec<FileDescriptor> = descriptions
.into_iter()
.map(|description| FileDescriptor {
description,
cloexec,
})
.collect();
let handles = current
.bulk_add_files_posix(files, &mut token)
.ok_or(Error::new(EMFILE))?;
let payload_chunks = payload.in_exact_chunks(size_of::<usize>());
for (handle, chunk) in handles.iter().zip(payload_chunks) {
chunk.copy_from_slice(&handle.get().to_ne_bytes())?;
}
Ok(handles.len())
}
pub fn bulk_insert_fds(
descriptions: Vec<Arc<LockedFileDescription>>,
payload: UserSliceRw,
cloexec: bool,
token: &mut LockToken<L1>,
) -> Result<usize> {
let cnt = descriptions.len();
if payload.len() != cnt * size_of::<usize>() {
return Err(Error::new(EINVAL));
}
if descriptions.is_empty() {
return Ok(0);
}
let files_iter = descriptions.into_iter().map(|description| FileDescriptor {
description,
cloexec,
});
let first_fd = payload
.in_exact_chunks(size_of::<usize>())
.next()
.ok_or(Error::new(EINVAL))?
.read_usize()?;
let current_lock = context::current();
let mut current = current_lock.write(token.token());
let (current, mut token) = current.token_split();
if first_fd == usize::MAX {
let files = files_iter.collect::<Vec<_>>();
let handles = current
.bulk_insert_files_upper(files, &mut token)
.ok_or(Error::new(EMFILE))?;
let payload_chunks = payload.in_exact_chunks(size_of::<usize>());
for (handle, chunk) in handles.iter().zip(payload_chunks) {
chunk.copy_from_slice(&handle.get().to_ne_bytes())?;
}
Ok(handles.len())
} else {
let handles: Vec<FileHandle> = payload
.usizes()
.map(|res| res.map(|i| FileHandle::from(i | syscall::UPPER_FDTBL_TAG)))
.collect::<Result<_, _>>()?;
let files = files_iter.collect::<Vec<_>>();
current.bulk_insert_files_upper_manual(files, &handles, &mut token)?;
Ok(handles.len())
}
}