Skip to content

uefi-macros: Drop !Send and !Sync from unsafe_protocol macro #758

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

Merged
merged 1 commit into from
Apr 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@

## uefi-macros - [Unreleased]

- The `unsafe_protocol` struct no longer makes protocols `!Send` and
`!Sync`. Protocols can only be used while boot services are active, and that's
already a single-threaded environment, so these negative traits do not have
any effect.

## uefi-services - [Unreleased]

## uefi - 0.20.0 (2023-03-19)
Expand Down
31 changes: 10 additions & 21 deletions uefi-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use proc_macro2::{TokenStream as TokenStream2, TokenTree};
use quote::{quote, quote_spanned, ToTokens, TokenStreamExt};
use syn::spanned::Spanned;
use syn::{
parse_macro_input, parse_quote, Error, Fields, FnArg, Ident, ItemFn, ItemStruct, LitStr, Pat,
parse_macro_input, parse_quote, Error, FnArg, Ident, ItemFn, ItemStruct, LitStr, Pat,
Visibility,
};

Expand All @@ -25,11 +25,9 @@ macro_rules! err {
///
/// The macro takes one argument, a GUID string.
///
/// The macro can only be applied to a struct, and the struct must have
/// named fields (i.e. not a unit or tuple struct). It implements the
/// The macro can only be applied to a struct. It implements the
/// [`Protocol`] trait and the `unsafe` [`Identify`] trait for the
/// struct. It also adds a hidden field that causes the struct to be
/// marked as [`!Send` and `!Sync`][send-and-sync].
/// struct.
///
/// # Safety
///
Expand Down Expand Up @@ -64,25 +62,16 @@ pub fn unsafe_protocol(args: TokenStream, input: TokenStream) -> TokenStream {
let item_struct = parse_macro_input!(input as ItemStruct);

let ident = &item_struct.ident;
let struct_attrs = &item_struct.attrs;
let struct_vis = &item_struct.vis;
let struct_fields = if let Fields::Named(struct_fields) = &item_struct.fields {
&struct_fields.named
} else {
return err!(item_struct, "Protocol struct must used named fields").into();
};
let struct_generics = &item_struct.generics;
let (impl_generics, ty_generics, where_clause) = item_struct.generics.split_for_impl();

quote! {
#(#struct_attrs)*
#struct_vis struct #ident #struct_generics {
// Add a hidden field with `PhantomData` of a raw
// pointer. This has the implicit side effect of making the
// struct !Send and !Sync.
_no_send_or_sync: ::core::marker::PhantomData<*const u8>,
#struct_fields
}
// Disable this lint for now. It doesn't account for the fact that
// currently it doesn't work to `derive(Debug)` on structs that have
// `extern "efiapi" fn` fields, which most protocol structs have. The
// derive _does_ work in current nightly (1.70.0) though, so hopefully
// in a couple Rust releases we can drop this.
#[allow(missing_debug_implementations)]
#item_struct

unsafe impl #impl_generics ::uefi::Identify for #ident #ty_generics #where_clause {
const GUID: ::uefi::Guid = ::uefi::Guid::from_values(
Expand Down
6 changes: 2 additions & 4 deletions uefi/src/proto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,8 @@ use core::ffi::c_void;

/// Common trait implemented by all standard UEFI protocols.
///
/// According to the UEFI's specification, protocols are `!Send` (they expect to
/// be run on the bootstrap processor) and `!Sync` (they are not thread-safe).
/// You can derive the `Protocol` trait, add these bounds, and specify the
/// protocol's GUID using the [`unsafe_protocol`] macro.
/// You can derive the `Protocol` trait and specify the protocol's GUID using
/// the [`unsafe_protocol`] macro.
///
/// # Example
///
Expand Down