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
+41 -23
View File
@@ -2,7 +2,7 @@ use alloc::collections::VecDeque;
use syscall::{EAGAIN, EINTR};
use crate::{
sync::{CleanLockToken, LockToken, Mutex, WaitCondition, L1, L2},
sync::{CleanLockToken, LockToken, Mutex, MutexGuard, WaitCondition, L1, L2, L3},
syscall::{
error::{Error, Result, EINVAL},
usercopy::UserSliceWo,
@@ -11,20 +11,24 @@ use crate::{
#[derive(Debug)]
pub struct WaitQueue<T> {
inner: Mutex<L2, VecDeque<T>>,
incoming: Mutex<L3, VecDeque<T>>,
outgoing: Mutex<L2, VecDeque<T>>,
pub condition: WaitCondition,
}
impl<T> WaitQueue<T> {
pub const fn new() -> WaitQueue<T> {
WaitQueue {
inner: Mutex::new(VecDeque::new()),
incoming: Mutex::new(VecDeque::new()),
outgoing: Mutex::new(VecDeque::new()),
condition: WaitCondition::new(),
}
}
pub fn is_currently_empty(&self, token: &mut CleanLockToken) -> bool {
self.inner.lock(token.token()).is_empty()
self.incoming.lock(token.token()).is_empty() && self.outgoing.lock(token.token()).is_empty()
}
pub fn receive_into_user(
&self,
buf: UserSliceWo,
@@ -32,17 +36,42 @@ impl<T> WaitQueue<T> {
reason: &'static str,
token: &mut CleanLockToken,
) -> Result<usize> {
let mut out_guard = self.outgoing.lock(token.token());
loop {
let inner = self.inner.lock(token.token());
let (mut inner, mut token) = inner.into_split();
let (mut outgoing, mut token) = out_guard.into_split();
if !outgoing.is_empty() {
let (s1, s2) = outgoing.as_slices();
let s1_bytes = unsafe {
core::slice::from_raw_parts(s1.as_ptr().cast::<u8>(), size_of_val(s1))
};
let s2_bytes = unsafe {
core::slice::from_raw_parts(s2.as_ptr().cast::<u8>(), size_of_val(s2))
};
if inner.is_empty() {
let mut bytes_copied = buf.copy_common_bytes_from_slice(s1_bytes)?;
if let Some(buf_for_s2) = buf.advance(s1_bytes.len()) {
bytes_copied += buf_for_s2.copy_common_bytes_from_slice(s2_bytes)?;
}
let _ = outgoing.drain(..bytes_copied / size_of::<T>());
return Ok(bytes_copied);
}
let mut incoming = self.incoming.lock(token.token());
if incoming.is_empty() {
if block {
drop(incoming);
// SAFETY: Uses wait_inner because this inner is L2. It's guaranteed there's no other
// lock held at this point because clean token is provided from caller.
if !self.condition.wait_inner(inner, reason, &mut token) {
if !self
.condition
.wait_inner(outgoing, reason, &mut token.token())
{
return Err(Error::new(EINTR));
}
out_guard = unsafe { self.outgoing.relock(token) };
continue;
} else if buf.is_empty() {
return Ok(0);
@@ -54,21 +83,10 @@ impl<T> WaitQueue<T> {
}
}
let (s1, s2) = inner.as_slices();
let s1_bytes =
unsafe { core::slice::from_raw_parts(s1.as_ptr().cast::<u8>(), size_of_val(s1)) };
let s2_bytes =
unsafe { core::slice::from_raw_parts(s2.as_ptr().cast::<u8>(), size_of_val(s2)) };
core::mem::swap(&mut *incoming, &mut outgoing);
drop(incoming);
let mut bytes_copied = buf.copy_common_bytes_from_slice(s1_bytes)?;
if let Some(buf_for_s2) = buf.advance(s1_bytes.len()) {
bytes_copied += buf_for_s2.copy_common_bytes_from_slice(s2_bytes)?;
}
let _ = inner.drain(..bytes_copied / size_of::<T>());
return Ok(bytes_copied);
out_guard = MutexGuard::from_split(outgoing, token);
}
}
@@ -78,7 +96,7 @@ impl<T> WaitQueue<T> {
pub fn send_locked(&self, value: T, mut token: LockToken<'_, L1>) -> usize {
let len = {
let mut inner = self.inner.lock(token.token());
let mut inner = self.incoming.lock(token.token());
inner.push_back(value);
inner.len()
};