Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
kernel
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Container Registry
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
4lDO2
kernel
Commits
dfcf21a1
Verified
Commit
dfcf21a1
authored
Aug 06, 2020
by
4lDO2
🖖
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Existential type attempt.
parent
1fd7d5e3
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
122 additions
and
67 deletions
+122
-67
src/io_uring/handle.rs
src/io_uring/handle.rs
+54
-29
src/io_uring/mod.rs
src/io_uring/mod.rs
+68
-38
No files found.
src/io_uring/handle.rs
View file @
dfcf21a1
...
...
@@ -449,7 +449,7 @@ where
S
:
'static
,
C
:
'static
,
{
pub
fn
task_ref
(
&
self
)
->
Option
<
TaskRef
>
{
pub
fn
task_ref
(
&
mut
self
)
->
Option
<
TaskRef
>
{
Some
(
TaskRef
{
index
:
self
.index
,
priority
:
self
.as_mut
()
.as_task_mut
()
?
.priority
(),
...
...
@@ -490,41 +490,50 @@ impl<S: 'static, C: 'static> TaskSlot<S, C> {
}
}
}
pub
fn
as_vacant_next
(
self
:
Pin
<&
mut
Self
>
)
->
Option
<&
mut
usize
>
{
unsafe
{
match
self
.get_mut
()
{
&
mut
Self
::
Vacant
{
ref
mut
next
}
=>
Some
(
next
),
&
mut
Self
::
Occupied
(
_
)
=>
None
,
}
pub
fn
as_vacant_next
(
self
:
Pin
<&
mut
Self
>
)
->
Option
<&
mut
usize
>
where
S
:
Unpin
,
C
:
Unpin
,
{
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
>
{
unsafe
{
match
self
.get_mut
()
{
// Don't permit occupied entries from being accessed mutably without Pin...
&
mut
Self
::
Occupied
(
_
)
=>
None
,
pub
fn
get_ref_if_vacant
(
self
:
Pin
<&
mut
Self
>
)
->
Option
<&
mut
Self
>
where
S
:
Unpin
,
C
:
Unpin
,
{
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
this
@
&
mut
Self
::
Vacant
{
..
}
=>
Some
(
this
),
}
// ... but do allow vacant entries from being accessed, to occupy them
this
@
&
mut
Self
::
Vacant
{
..
}
=>
Some
(
this
),
}
}
/// Replaces an occupied task with a new orphan vacant entry, safely dropping the future
/// inside.
pub
fn
free
(
self
:
Pin
<&
mut
Self
>
)
{
unsafe
{
let
pointer
=
self
.as_task_mut
()
.expect
(
"expected Task::free to free an occupied entry"
)
.get_unchecked_mut
()
as
*
mut
Task
<
S
,
C
>
;
let
this
=
self
.get_unchecked_mut
();
let
this_ptr
=
this
as
*
mut
Self
;
// 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
);
{
let
pointer
=
Pin
::
new_unchecked
(
this
)
.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
// 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;
pub
const
TASK_QUOT_DIV
:
usize
=
4
;
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
);
let
usize_size
=
mem
::
size_of
::
<
usize
>
();
let
lock_word_count
=
(
pending_task_count
+
usize_size
-
1
)
/
usize_size
*
usize_size
;
...
...
@@ -935,8 +948,12 @@ impl<S, C> Runqueue<S, C> {
None
=>
usize
::
MAX
,
}
}
fn
allocate_new_task_slot_inner
(
&
self
,
current
:
usize
)
->
bool
{
let
current_slot
=
self
.lock_task
(
current
);
fn
allocate_new_task_slot_inner
(
&
self
,
current
:
usize
)
->
bool
where
S
:
Unpin
,
C
:
Unpin
,
{
let
mut
current_slot
=
self
.lock_task
(
current
);
let
current_slot_next_raw
=
current_slot
.as_mut
()
.as_vacant_next
()
...
...
@@ -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
index
=
match
self
.allocate_new_task_slot_inner
(
initial
)
{
true
=>
initial
,
...
...
@@ -972,7 +993,11 @@ impl<S, C> Runqueue<S, C> {
};
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!
(
self
.lock_task
(
at
)
.as_mut
()
...
...
@@ -981,7 +1006,7 @@ impl<S, C> Runqueue<S, C> {
);
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
.as_mut
()
...
...
src/io_uring/mod.rs
View file @
dfcf21a1
use
core
::
convert
::{
TryFrom
,
TryInto
};
use
core
::
future
::
Future
;
use
core
::
intrinsics
::
unlikely
;
use
core
::
pin
::
Pin
;
use
core
::
ptr
::
NonNull
;
use
core
::
sync
::
atomic
::
Ordering
;
use
core
::{
fmt
,
iter
,
mem
,
ptr
,
task
};
...
...
@@ -755,16 +756,19 @@ where
Err
(
Error
::
new
(
ENOSYS
))
}
async
fn
handle_standard_opcode
<
S
,
C
>
(
consumer_state
:
&
RingHandleConsumerState
,
async
fn
handle_standard_opcode
_inner
<
S
,
C
>
(
handle
:
Arc
<
Handle
>
,
submission_entry
:
S
,
opcode
:
StandardOpcode
,
ctx
:
&
crate
::
syscall
::
scheme
::
Ctx
,
ctx
:
crate
::
syscall
::
scheme
::
Ctx
,
)
->
Result
<
C
>
where
S
:
GenericSubmissionEntry
+
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
>
(
user_data
:
u64
,
return_value
:
ReturnValue
,
...
...
@@ -792,7 +796,7 @@ where
|
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
{
status
:
Error
::
mux64
(
Err
(
error
)),
flags
:
0
,
...
...
@@ -801,8 +805,8 @@ where
|
_
|
ReturnValue
::
zero
(),
),
StandardOpcode
::
Read
=>
construct_simple
(
handle_read
(
&
submission_entry
,
ctx
)
.await
),
StandardOpcode
::
Write
=>
construct_simple
(
handle_write
(
&
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
::
Seek
=>
return
Err
(
Error
::
new
(
ENOSYS
)),
StandardOpcode
::
Fstat
=>
return
Err
(
Error
::
new
(
ENOSYS
)),
StandardOpcode
::
Fstatvfs
=>
return
Err
(
Error
::
new
(
ENOSYS
)),
...
...
@@ -811,7 +815,7 @@ where
StandardOpcode
::
Munmap
=>
construct_simple
(
handle_munmap
(
&
submission_entry
)
.await
),
StandardOpcode
::
Fsync
=>
return
Err
(
Error
::
new
(
ENOSYS
)),
StandardOpcode
::
FilesUpdate
=>
{
construct_simple
(
handle_files_update
(
consumer
_state
,
&
submission_entry
))
construct_simple
(
handle_files_update
(
runtime
_state
,
&
submission_entry
))
}
StandardOpcode
::
RegularSyscall
=>
{
construct_simple
(
handle_regular_syscall
(
&
submission_entry
))
...
...
@@ -822,10 +826,22 @@ where
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
,
opcode
:
KernelOpcode
,
ctx
:
&
crate
::
syscall
::
scheme
::
Ctx
,
ctx
:
crate
::
syscall
::
scheme
::
Ctx
,
)
->
Result
<
C
>
where
S
:
GenericSubmissionEntry
,
...
...
@@ -836,23 +852,33 @@ where
_
=>
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
>
,
submission_entry
:
S
,
ctx
:
crate
::
syscall
::
scheme
::
Ctx
,
)
->
Result
<
C
>
)
->
Result
<
HandleSubmissionFuture
<
S
,
C
>
>
where
S
:
GenericSubmissionEntry
+
fmt
::
Debug
+
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
())
{
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
())
{
handle_kernel_opcode
(
submission_entry
,
kernel_opcode
,
&
ctx
)
.await
todo!
();
//HandleSubmissionFuture::KernelOpcode(handle_kernel_opcode(submission_entry, kernel_opcode, &ctx))
}
else
{
println!
(
"UNKNOWN OPCODE {}, full SQE: {:?}"
,
...
...
@@ -862,19 +888,24 @@ where
Err
(
Error
::
new
(
ENOSYS
))
}
}
fn
handle_submission
<
S
,
C
>
(
handle
:
Arc
<
Handle
>
,
submission_entry
:
S
,
ctx
:
crate
::
syscall
::
scheme
::
Ctx
,
)
->
HandleSubmissionFuture
<
S
,
C
>
where
S
:
GenericSubmissionEntry
+
fmt
::
Debug
+
Send
+
Sync
+
'static
,
C
:
GenericCompletionEntry
+
Send
+
Sync
+
'static
,
{
handle_submission_raw
(
handle
,
submission_entry
,
ctx
)
pub
type
HandleStandardOpcodeFuture
<
S
,
C
>
=
impl
Future
<
Output
=
Result
<
C
>>
+
Send
+
Sync
+
'static
;
pub
type
HandleKernelOpcodeFuture
<
S
,
C
>
=
impl
Future
<
Output
=
Result
<
C
>>
+
Send
+
Sync
+
'static
;
pub
enum
HandleSubmissionFuture
<
S
,
C
>
{
//StandardOpcode(HandleStandardOpcodeFuture<S, C>),
KernelOpcode
(
HandleKernelOpcodeFuture
<
S
,
C
>
),
//S(S),
//C(C),
}
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
>
(
info
:
&
RingInfo
<
C
>
,
...
...
@@ -1115,20 +1146,19 @@ fn register_event_interest(handle: &RingHandle, context: Arc<RwLock<Context>>) -
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
S
:
'static
,
C
:
'static
,
S
:
'static
+
Unpin
,
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
.task_ref
()
.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
)
{
task
::
Poll
::
Ready
(
cqe
)
=>
{
...
...
@@ -1185,8 +1215,8 @@ unsafe fn handle_submission_entries<S, C>(
ctx
:
crate
::
syscall
::
scheme
::
Ctx
,
)
->
Result
<
()
>
where
S
:
GenericSubmissionEntry
+
fmt
::
Debug
+
Send
+
Sync
+
'static
,
C
:
GenericCompletionEntry
+
Send
+
Sync
+
'static
,
S
:
GenericSubmissionEntry
+
fmt
::
Debug
+
Send
+
Sync
+
'static
+
Unpin
,
C
:
GenericCompletionEntry
+
Send
+
Sync
+
'static
+
Unpin
,
{
// 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
...
...
@@ -1209,7 +1239,7 @@ where
};
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
{
future
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment