-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
alloc: initial TryBox
implementation
#196
base: main
Are you sure you want to change the base?
Conversation
For review I suggest taking a look at the public API via |
28ff8c8
to
5a5ef34
Compare
Looks good to me at the moment. Just a few questions:
|
Thanks for working in this, I think it is going into the right direction. I particularly like that the box only supports fallible allocations, forcing users to handle allocation errors. This might actually become a reason to not switch back to the standard library once these features become stable there. A few things I noticed:
|
Not really, other than diffing I don't see much that can be done sadly. On the other hand, this code should not require heavy maintenance as we likely don't want many more features. One exception would be, as I mentioned in the PR description, the support for unsized types - when the required features are stabilized, we will likely want to add those.
No, I wrote those to ensure that everything worked as expected, as there are some slight syntax changes I had to perform to avoid nightly features. Upstream does have tests but most rely on parts of the Box type that we do not support. At some point I'll revisit them to ensure that we use as much tests from upstream as possible. |
I simply placed in EDIT: technically I pulled the
Yeah the name change makes sense, I'll add it to the next version of the PR. For default allocator types, I think we can even use typedefs (but I have not tested it). Something like: static ALLOCATOR: SvsmAllocator = SvsmAllocator::new();
// ...
pub type GlobalBox<T> = TryBox<T, A = ALLOCATOR>; |
5a5ef34
to
ba1d264
Compare
SvsmBox
implementationTryBox
implementation
ba1d264
to
700c661
Compare
|
0335561
to
099c29b
Compare
Just verified that this does not really work. But we can do: pub struct GlobalBox<T>(TryBox<T, &'static SvsmAllocator>);
impl<T> GlobalBox<T> {
pub fn try_new(val: T) -> Result<Self, SvsmError> {
let inner = TryBox::try_new_in(val, &ALLOCATOR)?;
Ok(Self(inner))
}
} I'll add something like this to this PR soon. |
099c29b
to
425644d
Compare
488dcbe
to
5aea5c2
Compare
There is currently an use of the old pub struct Mapping {
mapping: RWLock<Box<dyn VirtualMapping>>,
} This is because |
8404a0b
to
427695b
Compare
901c1f1
to
0d1a197
Compare
0d1a197
to
2747b7e
Compare
I've been digging into this and we might actually be able to get it working for unsized types. The main issue to replace the use above (as far as I can tell) is that To solve this, I've come up with a macro that will do this for us. With regular coercion, we could simply do: trait MyTrait {}
impl MyTrait for usize {}
let boxed = Box::new(5usize);
let dynamic: Box<dyn MyTrait> = boxed; But we need to do: trait MyTrait {}
impl MyTrait for usize {}
let boxed = TryBox::try_new_in(5usize, Allocator)?;
let dynamic = trybox_upcast!(boxed, MyTrait); |
cd3b6ee
to
f7e59cc
Compare
|
4f6732e
to
d4f883b
Compare
d4f883b
to
a5e5634
Compare
Added a new test and rebased on main. |
e69750a
to
6964b6e
Compare
Introduce the alloc submodule and the TryBox type, a fork of the upstream alloc crate and Box type respectively. The new type behaves exactly like Box, except it only supports fallible allocations, meaning that users must always handle potential errors. Users must also explicitly set the allocator to use. Using a specific allocator by default like the standard library does is complicated. The standard library uses whichever allocator is set as global (via the #[global_allocator] macro), which can be accessed via a global instance (alloc::alloc::Global). However, the global instance is gated behind an unstable feature, and the macro cannot be reimplemented because it is a compiler intrinsic. As a workaround, one may add new higher level types in the future which use a specific allocator by default. The new type also has a few extra methods for convenience like try_default_in(), try_clone() and try_clone_in(). Signed-off-by: Carlos López <carlos.lopez@suse.com>
In order to be used along with the new TryBox type, an allocator must implement the Allocator trait, so implement it for the current global allocator. Signed-off-by: Carlos López <carlos.lopez@suse.com>
Add a new variant to hold a TryAllocError from the alloc submodule. This new error does not implement Copy, so SvsmError cannot implement it either. Signed-off-by: Carlos López <carlos.lopez@suse.com>
Add a new type, GlobalBox, which wraps around the TryBox type but uses the global SvsmAllocator transparently. The new type implements AsRef<TryBox> and Into<TryBox>, so regular TryBox methods can also be used on the new type. Signed-off-by: Carlos López <carlos.lopez@suse.com>
Allocate PageTablePart structs with the new fallible-allocation-aware GlobalBox type. Signed-off-by: Carlos López <carlos.lopez@suse.com>
Use the new fallible-allocation-aware GlobalBox type when allocating SNP request messages. Signed-off-by: Carlos López <carlos.lopez@suse.com>
Replace uses of Box with the new fallible-allocation-aware GlobalBox type. Unfortunately, replacing the Box used in the RB tree for virtual mappings is very involved. In short, the intrusive_collections crate provides an intrusive_adapter macro, which generates a new adapter type that handles the insertion and deletion of any type into an intrusive collection. Sadly, this macro is only prepared to work with the smart pointer types in the standard library. This is done by implementing the PointerOps trait for DefaultPointerOps<T>, where T is one of the regular smart pointer types (Rc, Arc, Box, etc.). The macro then generates an implementation of Adapter for the newly generated type, which uses the selected smart pointer. We define a substitute for DefaultPointerOps, CustomPointerOps, and implement PointerOps for CustomPointerOps<GlobalBox>. We then add a manual implementation of Adapter for VMMAdapter, which uses GlobalBox under the hood. Signed-off-by: Carlos López <carlos.lopez@suse.com>
Replace uses of Box in the mapping API with the new fallible-allocation-aware GlobalBox type. Signed-off-by: Carlos López <carlos.lopez@suse.com>
Use the new fallible-allocation-aware GlobalBox type when allocating a new secrets page for the given VPML. Signed-off-by: Carlos López <carlos.lopez@suse.com>
6964b6e
to
6a05132
Compare
Rebased on main and fixed conflicts |
Introduce the alloc submodule and the
TryBox
type, a fork of the upstreamalloc
crate andBox
type respectively. The new type behaves exactly likeBox
, except it only supports fallible allocations, meaning that users must always handle potential errors.Users must also explicitly set the allocator to use. Using a specific allocator by default like the standard library does is complicated. The standard library uses whichever allocator is set as global (via the
#[global_allocator]
macro), which can be accessed via a global instance (alloc::alloc::Global)
. However, the global instance is gated behind an unstable feature, and the macro cannot be reimplemented because it is a compiler intrinsic. As a workaround, one may add new higher level types in the future which use a specific allocator by default.The new. On the other hand, it has a few extra methods for convenience likeTryBox
does not support unsized types (e.g.[T]
prdyn Trait
), since that requires unstable featurestry_default_in()
,try_clone()
andtry_clone_in()
.This PR also includes a new type,
GlobalBox
, which uses the global SVSM allocator (SvsmAllocator
), and is meant to be used as a replacement for the regularBox type.
TODO:
SvsmAlloc
forSvsmAllocator
GlobalBox
, a wrapper which uses theSvsmAllocator
transparently.Box
uses withGlobalBox
.NOTE: there is a single instance that cannot be replaced, see comment below.TODO in future PRs:
TryArc
TryRc
TryVec
/RawVec
TryString