Verified Commit dfcf21a1 authored by 4lDO2's avatar 4lDO2 🖖

Existential type attempt.

parent 1fd7d5e3
...@@ -449,7 +449,7 @@ where ...@@ -449,7 +449,7 @@ where
S: 'static, S: 'static,
C: 'static, C: 'static,
{ {
pub fn task_ref(&self) -> Option<TaskRef> { pub fn task_ref(&mut self) -> Option<TaskRef> {
Some(TaskRef { Some(TaskRef {
index: self.index, index: self.index,
priority: self.as_mut().as_task_mut()?.priority(), priority: self.as_mut().as_task_mut()?.priority(),
...@@ -490,41 +490,50 @@ impl<S: 'static, C: 'static> TaskSlot<S, C> { ...@@ -490,41 +490,50 @@ impl<S: 'static, C: 'static> TaskSlot<S, C> {
} }
} }
} }
pub fn as_vacant_next(self: Pin<&mut Self>) -> Option<&mut usize> { pub fn as_vacant_next(self: Pin<&mut Self>) -> Option<&mut usize>
unsafe { where
match self.get_mut() { S: Unpin,
&mut Self::Vacant { ref mut next } => Some(next), C: Unpin,
&mut Self::Occupied(_) => None, {
} match self.get_mut() {
&mut Self::Vacant { ref mut next } => Some(next),
&mut Self::Occupied(_) => None,
} }
} }
pub fn get_ref_if_vacant(self: Pin<&mut Self>) -> Option<&mut Self> { pub fn get_ref_if_vacant(self: Pin<&mut Self>) -> Option<&mut Self>
unsafe { where
match self.get_mut() { S: Unpin,
// Don't permit occupied entries from being accessed mutably without Pin... C: Unpin,
&mut Self::Occupied(_) => None, {
match self.get_mut() {
// Don't permit occupied entries from being accessed mutably without Pin...
&mut Self::Occupied(_) => None,
// ... but do allow vacant entries from being accessed, to occupy them // ... but do allow vacant entries from being accessed, to occupy them
this @ &mut Self::Vacant { .. } => Some(this), this @ &mut Self::Vacant { .. } => Some(this),
}
} }
} }
/// Replaces an occupied task with a new orphan vacant entry, safely dropping the future /// Replaces an occupied task with a new orphan vacant entry, safely dropping the future
/// inside. /// inside.
pub fn free(self: Pin<&mut Self>) { pub fn free(self: Pin<&mut Self>) {
unsafe { unsafe {
let pointer = self let this = self.get_unchecked_mut();
.as_task_mut() let this_ptr = this as *mut Self;
.expect("expected Task::free to free an occupied entry")
.get_unchecked_mut() as *mut Task<S, C>;
// Since the task and the future inside that task is pinned, we need to drop manually {
// with drop_in_place. let pointer = Pin::new_unchecked(this)
ptr::drop_in_place(pointer); .as_task_mut()
.expect("expected Task::free to free an occupied entry")
.get_unchecked_mut() as *mut Task<S, C>;
// Since the task and the future inside that task is pinned, we need to drop manually
// with drop_in_place.
ptr::drop_in_place(pointer);
}
// And, now that it's dropped, we cannot in any way use self again by reference, so we // And, now that it's dropped, we cannot in any way use self again by reference, so we
// need to ptr::write the new value. // need to ptr::write the new value.
ptr::write(self.get_unchecked_mut() as *mut Self, Self::Vacant { next: usize::MAX }); ptr::write(this_ptr, Self::Vacant { next: usize::MAX });
} }
} }
} }
...@@ -788,7 +797,11 @@ pub const TASK_QUOT_MUL: usize = 1; ...@@ -788,7 +797,11 @@ pub const TASK_QUOT_MUL: usize = 1;
pub const TASK_QUOT_DIV: usize = 4; pub const TASK_QUOT_DIV: usize = 4;
impl<S, C> Runqueue<S, C> { impl<S, C> Runqueue<S, C> {
pub fn new(pending_task_count: usize) -> Self { pub fn new(pending_task_count: usize) -> Self
where
S: Unpin,
C: Unpin,
{
assert_ne!(pending_task_count, usize::MAX); assert_ne!(pending_task_count, usize::MAX);
let usize_size = mem::size_of::<usize>(); let usize_size = mem::size_of::<usize>();
let lock_word_count = (pending_task_count + usize_size - 1) / usize_size * usize_size; let lock_word_count = (pending_task_count + usize_size - 1) / usize_size * usize_size;
...@@ -935,8 +948,12 @@ impl<S, C> Runqueue<S, C> { ...@@ -935,8 +948,12 @@ impl<S, C> Runqueue<S, C> {
None => usize::MAX, None => usize::MAX,
} }
} }
fn allocate_new_task_slot_inner(&self, current: usize) -> bool { fn allocate_new_task_slot_inner(&self, current: usize) -> bool
let current_slot = self.lock_task(current); where
S: Unpin,
C: Unpin,
{
let mut current_slot = self.lock_task(current);
let current_slot_next_raw = current_slot let current_slot_next_raw = current_slot
.as_mut() .as_mut()
.as_vacant_next() .as_vacant_next()
...@@ -964,7 +981,11 @@ impl<S, C> Runqueue<S, C> { ...@@ -964,7 +981,11 @@ impl<S, C> Runqueue<S, C> {
} }
} }
} }
pub fn allocate_new_task_slot<'runqueue>(&'runqueue self) -> Option<TaskGuard<'runqueue, S, C>> { pub fn allocate_new_task_slot<'runqueue>(&'runqueue self) -> Option<TaskGuard<'runqueue, S, C>>
where
S: Unpin,
C: Unpin,
{
let initial = Self::index_from_raw(self.first_vacant_slot.load(Ordering::Acquire))?; let initial = Self::index_from_raw(self.first_vacant_slot.load(Ordering::Acquire))?;
let index = match self.allocate_new_task_slot_inner(initial) { let index = match self.allocate_new_task_slot_inner(initial) {
true => initial, true => initial,
...@@ -972,7 +993,11 @@ impl<S, C> Runqueue<S, C> { ...@@ -972,7 +993,11 @@ impl<S, C> Runqueue<S, C> {
}; };
Some(self.lock_task(index)) Some(self.lock_task(index))
} }
pub fn free_task_slot<'runqueue>(&'runqueue self, at: usize) { pub fn free_task_slot<'runqueue>(&'runqueue self, at: usize)
where
S: Unpin,
C: Unpin,
{
debug_assert!( debug_assert!(
self.lock_task(at) self.lock_task(at)
.as_mut() .as_mut()
...@@ -981,7 +1006,7 @@ impl<S, C> Runqueue<S, C> { ...@@ -981,7 +1006,7 @@ impl<S, C> Runqueue<S, C> {
); );
let last_index = self.last_vacant_slot.load(Ordering::Acquire); let last_index = self.last_vacant_slot.load(Ordering::Acquire);
let last_task_slot = self.lock_task(last_index); let mut last_task_slot = self.lock_task(last_index);
*last_task_slot *last_task_slot
.as_mut() .as_mut()
......
use core::convert::{TryFrom, TryInto}; use core::convert::{TryFrom, TryInto};
use core::future::Future; use core::future::Future;
use core::intrinsics::unlikely; use core::intrinsics::unlikely;
use core::pin::Pin;
use core::ptr::NonNull; use core::ptr::NonNull;
use core::sync::atomic::Ordering; use core::sync::atomic::Ordering;
use core::{fmt, iter, mem, ptr, task}; use core::{fmt, iter, mem, ptr, task};
...@@ -755,16 +756,19 @@ where ...@@ -755,16 +756,19 @@ where
Err(Error::new(ENOSYS)) Err(Error::new(ENOSYS))
} }
async fn handle_standard_opcode<S, C>( async fn handle_standard_opcode_inner<S, C>(
consumer_state: &RingHandleConsumerState, handle: Arc<Handle>,
submission_entry: S, submission_entry: S,
opcode: StandardOpcode, opcode: StandardOpcode,
ctx: &crate::syscall::scheme::Ctx, ctx: crate::syscall::scheme::Ctx,
) -> Result<C> ) -> Result<C>
where where
S: GenericSubmissionEntry + Send + Sync + 'static, S: GenericSubmissionEntry + Send + Sync + 'static,
C: GenericCompletionEntry + Send + Sync + 'static, C: GenericCompletionEntry + Send + Sync + 'static,
{ {
let handle = handle.as_ring_handle().ok_or(Error::new(EBADF))?;
let runtime_state = handle.consumer_state.r#try().ok_or(Error::new(EBADFD))?;
fn construct<C: GenericCompletionEntry>( fn construct<C: GenericCompletionEntry>(
user_data: u64, user_data: u64,
return_value: ReturnValue, return_value: ReturnValue,
...@@ -792,7 +796,7 @@ where ...@@ -792,7 +796,7 @@ where
|fd| ReturnValue::from_status(fd.into() as u64), |fd| ReturnValue::from_status(fd.into() as u64),
), ),
StandardOpcode::Close => handle_close(&submission_entry, ctx).await.map_or_else( StandardOpcode::Close => handle_close(&submission_entry, &ctx).await.map_or_else(
|(error, successful_closes)| ReturnValue { |(error, successful_closes)| ReturnValue {
status: Error::mux64(Err(error)), status: Error::mux64(Err(error)),
flags: 0, flags: 0,
...@@ -801,8 +805,8 @@ where ...@@ -801,8 +805,8 @@ where
|_| ReturnValue::zero(), |_| ReturnValue::zero(),
), ),
StandardOpcode::Read => construct_simple(handle_read(&submission_entry, ctx).await), StandardOpcode::Read => construct_simple(handle_read(&submission_entry, &ctx).await),
StandardOpcode::Write => construct_simple(handle_write(&submission_entry, ctx).await), StandardOpcode::Write => construct_simple(handle_write(&submission_entry, &ctx).await),
StandardOpcode::Seek => return Err(Error::new(ENOSYS)), StandardOpcode::Seek => return Err(Error::new(ENOSYS)),
StandardOpcode::Fstat => return Err(Error::new(ENOSYS)), StandardOpcode::Fstat => return Err(Error::new(ENOSYS)),
StandardOpcode::Fstatvfs => return Err(Error::new(ENOSYS)), StandardOpcode::Fstatvfs => return Err(Error::new(ENOSYS)),
...@@ -811,7 +815,7 @@ where ...@@ -811,7 +815,7 @@ where
StandardOpcode::Munmap => construct_simple(handle_munmap(&submission_entry).await), StandardOpcode::Munmap => construct_simple(handle_munmap(&submission_entry).await),
StandardOpcode::Fsync => return Err(Error::new(ENOSYS)), StandardOpcode::Fsync => return Err(Error::new(ENOSYS)),
StandardOpcode::FilesUpdate => { StandardOpcode::FilesUpdate => {
construct_simple(handle_files_update(consumer_state, &submission_entry)) construct_simple(handle_files_update(runtime_state, &submission_entry))
} }
StandardOpcode::RegularSyscall => { StandardOpcode::RegularSyscall => {
construct_simple(handle_regular_syscall(&submission_entry)) construct_simple(handle_regular_syscall(&submission_entry))
...@@ -822,10 +826,22 @@ where ...@@ -822,10 +826,22 @@ where
construct(submission_entry.user_data64(), return_value) construct(submission_entry.user_data64(), return_value)
} }
async fn handle_kernel_opcode<S, C>( fn handle_standard_opcode<S, C>(
handle: Arc<Handle>,
submission_entry: S,
opcode: StandardOpcode,
ctx: crate::syscall::scheme::Ctx,
) -> HandleStandardOpcodeFuture<S, C>
where
S: GenericSubmissionEntry + Send + Sync + 'static,
C: GenericCompletionEntry + Send + Sync + 'static,
{
async move { Err(Error::new(ENOSYS)) }//handle_standard_opcode_inner(handle, submission_entry, opcode, ctx)
}
async fn handle_kernel_opcode_inner<S, C>(
submission_entry: S, submission_entry: S,
opcode: KernelOpcode, opcode: KernelOpcode,
ctx: &crate::syscall::scheme::Ctx, ctx: crate::syscall::scheme::Ctx,
) -> Result<C> ) -> Result<C>
where where
S: GenericSubmissionEntry, S: GenericSubmissionEntry,
...@@ -836,23 +852,33 @@ where ...@@ -836,23 +852,33 @@ where
_ => return Err(Error::new(ENOSYS)), _ => return Err(Error::new(ENOSYS)),
} }
} }
fn handle_kernel_opcode<S, C>(
submission_entry: S,
opcode: KernelOpcode,
ctx: crate::syscall::scheme::Ctx,
) -> HandleKernelOpcodeFuture<S, C>
where
S: GenericSubmissionEntry + Send + Sync + 'static,
C: GenericCompletionEntry + Send + Sync + 'static,
{
async move { Err(Error::new(ENOSYS)) }//handle_kernel_opcode_inner(submission_entry, opcode, ctx)
}
async fn handle_submission_raw<S, C>( fn handle_submission<S, C>(
handle: Arc<Handle>, handle: Arc<Handle>,
submission_entry: S, submission_entry: S,
ctx: crate::syscall::scheme::Ctx, ctx: crate::syscall::scheme::Ctx,
) -> Result<C> ) -> Result<HandleSubmissionFuture<S, C>>
where where
S: GenericSubmissionEntry + fmt::Debug + Send + Sync + 'static, S: GenericSubmissionEntry + fmt::Debug + Send + Sync + 'static,
C: GenericCompletionEntry + Send + Sync + 'static, C: GenericCompletionEntry + Send + Sync + 'static,
{ {
let handle = handle.as_ring_handle().ok_or(Error::new(EBADF))?;
let runtime_state = handle.consumer_state.r#try().ok_or(Error::new(EBADFD))?;
if let Some(standard_opcode) = StandardOpcode::from_raw(submission_entry.opcode()) { if let Some(standard_opcode) = StandardOpcode::from_raw(submission_entry.opcode()) {
handle_standard_opcode(runtime_state, submission_entry, standard_opcode, &ctx).await todo!();
//HandleSubmissionFuture::StandardOpcode(todo!()/*handle_standard_opcode(runtime_state, submission_entry, standard_opcode, &ctx)*/)
} else if let Some(kernel_opcode) = KernelOpcode::from_raw(submission_entry.opcode()) { } else if let Some(kernel_opcode) = KernelOpcode::from_raw(submission_entry.opcode()) {
handle_kernel_opcode(submission_entry, kernel_opcode, &ctx).await todo!();
//HandleSubmissionFuture::KernelOpcode(handle_kernel_opcode(submission_entry, kernel_opcode, &ctx))
} else { } else {
println!( println!(
"UNKNOWN OPCODE {}, full SQE: {:?}", "UNKNOWN OPCODE {}, full SQE: {:?}",
...@@ -862,19 +888,24 @@ where ...@@ -862,19 +888,24 @@ where
Err(Error::new(ENOSYS)) Err(Error::new(ENOSYS))
} }
} }
fn handle_submission<S, C>(
handle: Arc<Handle>, pub type HandleStandardOpcodeFuture<S, C> = impl Future<Output = Result<C>> + Send + Sync + 'static;
submission_entry: S, pub type HandleKernelOpcodeFuture<S, C> = impl Future<Output = Result<C>> + Send + Sync + 'static;
ctx: crate::syscall::scheme::Ctx,
) -> HandleSubmissionFuture<S, C> pub enum HandleSubmissionFuture<S, C> {
where //StandardOpcode(HandleStandardOpcodeFuture<S, C>),
S: GenericSubmissionEntry + fmt::Debug + Send + Sync + 'static, KernelOpcode(HandleKernelOpcodeFuture<S, C>),
C: GenericCompletionEntry + Send + Sync + 'static, //S(S),
{ //C(C),
handle_submission_raw(handle, submission_entry, ctx)
} }
pub type HandleSubmissionFuture<S, C> = impl Future<Output = Result<C>> + Send + Sync + 'static; impl<S, C> Future for HandleSubmissionFuture<S, C> {
type Output = Result<C>;
fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> task::Poll<Self::Output> {
todo!()
}
}
fn send_event<C>( fn send_event<C>(
info: &RingInfo<C>, info: &RingInfo<C>,
...@@ -1115,20 +1146,19 @@ fn register_event_interest(handle: &RingHandle, context: Arc<RwLock<Context>>) - ...@@ -1115,20 +1146,19 @@ fn register_event_interest(handle: &RingHandle, context: Arc<RwLock<Context>>) -
Ok(()) Ok(())
} }
fn poll_or_insert_into_pending_map<S, C>(queue: &Runqueue<S, C>, task_guard: TaskGuard<S, C>, context: &mut task::Context, tag: PendingTag) -> task::Poll<Result<C>> fn poll_or_insert_into_pending_map<S, C>(queue: &Runqueue<S, C>, mut task_guard: TaskGuard<S, C>, context: &mut task::Context, tag: PendingTag) -> task::Poll<Result<C>>
where where
S: 'static, S: 'static + Unpin,
C: 'static, C: 'static + Unpin,
{ {
let task = task_guard
.as_mut()
.as_task_mut()
.expect("expected task guard passed into poll_or_insert_into_pending_map to contain a task");
let task_ref = task_guard let task_ref = task_guard
.task_ref() .task_ref()
.expect("expected task guard to be occupied with a pending task"); .expect("expected task guard to be occupied with a pending task");
let task = task_guard
.as_mut()
.as_task_mut()
.expect("expected task guard passed into poll_or_insert_into_pending_map to contain a task");
match task.as_future_mut().poll(context) { match task.as_future_mut().poll(context) {
task::Poll::Ready(cqe) => { task::Poll::Ready(cqe) => {
...@@ -1185,8 +1215,8 @@ unsafe fn handle_submission_entries<S, C>( ...@@ -1185,8 +1215,8 @@ unsafe fn handle_submission_entries<S, C>(
ctx: crate::syscall::scheme::Ctx, ctx: crate::syscall::scheme::Ctx,
) -> Result<()> ) -> Result<()>
where where
S: GenericSubmissionEntry + fmt::Debug + Send + Sync + 'static, S: GenericSubmissionEntry + fmt::Debug + Send + Sync + 'static + Unpin,
C: GenericCompletionEntry + Send + Sync + 'static, C: GenericCompletionEntry + Send + Sync + 'static + Unpin,
{ {
// New tags only have to be created when a future returns pending, since only // New tags only have to be created when a future returns pending, since only
// then is the future getting involved in the pending map. The downside to this // then is the future getting involved in the pending map. The downside to this
...@@ -1209,7 +1239,7 @@ where ...@@ -1209,7 +1239,7 @@ where
}; };
let priority = entry.priority(); let priority = entry.priority();
let future = handle_submission(Arc::clone(handle), entry, ctx); let future = handle_submission(Arc::clone(handle), entry, ctx)?;
let task = Task { let task = Task {
future, future,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment