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:
+280
-64
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user