# Meeting 2022-10-25 - [ ] (vincenzopalazzo): Comments regarding PR [910](https://github.com/Rust-for-Linux/linux/pull/910) - Why we need the `proc-macro2`? if we already have access to proc_macro? we already have access to proc-macro [here](https://github.com/Rust-for-Linux/linux/tree/rust/rust) > [name=bjorn3] proc-macro2 is used by syn because it allows using syn outside of proc-macros. - quote dependeces is really necessary? do you think that the following code is more readable of [this code](https://github.com/Rust-for-Linux/linux/blob/rust/rust/macros/module.rs#L434-L495) > [name=bjorn3] Quote is only a dependency if the `printing` feature is enabled, so disabling this feature is enough to remove the quote dependency. > [name=bjorn3] I do think quote is more readable. In addition you get syntax highlighting inside the `quote!` macro and spans are preserved by the `quote!` macro, allowing for much better error messages. ```rust let tokens = quote! { struct SerializeWith #generics #where_clause { value: &'a #field_ty, phantom: core::marker::PhantomData<#item_ty>, } impl #generics serde::Serialize for SerializeWith #generics #where_clause { fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer, { #path(self.value, serializer) } } SerializeWith { value: #value, phantom: core::marker::PhantomData::<#item_ty>, } }; ``` - it is possible enable syn to compile by using a cfg for the kernel? > [name=bjorn3] What exactly do you mean? ## RCU projection WIP Wedson's example from a few weeks ago: ## Scope This document is a discussion around how to deal with the projection of RCU fields holding pointers. Other RCU issues are out of scope for now. ## Introduction In our context, RCU allows shared pointers to be accessed without any blocking, even when they may be replaced. Below we have an example of accessing an RCU-protected boxed `u32`: ```rust fn read_ptr(rcu_ptr: &Rcu<Box<u32>>) { // Acquire the RCU read-side lock; it never blocks. let guard = rcu::read_lock(); // Access the contents of the box. The lifetime of `x` is tied to // `guard`, not `rcu_ptr`. let x = rcu_ptr.get(&guard); pr_info!("Value: {}\n", *x); } ``` The code that updates an RCU-protected pointer would look like this: ```rust fn update_ptr(rcu_ptr: &Rcu<Box<u32>>, new: Box<u32>) { // Replaces the current pointer with a new one. let old = rcu_ptr.replace(new); // The type of `old` is `rcu::ToFree<Box<u32>>`. Its `Drop` // implementation ensures that an RCU grace period has elapsed // since the pointer was updated. So we know that there are no longer // any CPUs using the old pointer. } ``` If we're replacing multiple RCU pointers, we can hold on to multiple `ToFree<T>` instances, wait for a grace period, then let them all drop. Since we know a grace period has elapsed, none of them will cause an extra sleep. For example: ```rust fn update_ptr(rcu_ptr1: &Rcu<Box<u32>>, rcu_ptr2: Rcu<Box<u32>>) -> Result { // Replace pointers. let old1 = rcu_ptr1.replace(Box::try_new(0)?); let old2 = rcu_ptr2.replace(Box::try_new(0)?); // Explicitly wait for grace period. rcu::syncronize(); // Both `old1` and `old2` are freed without further delay. } ``` ## Fields The above works well for stand-alone RCU pointers. However, it turns out that they're normally stored as fields in another struct that is normally protected by some synchronization primitive for _writes_. For example, we could have something like the following for an RCU list: ```rust struct Entry<T> { next: Rcu<Option<Box<Entry<T>>>>, value: T, } struct RcuList<T> { head: Rcu<Option<Box<Entry<T>>>>, tail: *mut Box<Entry<T>>, } ``` So let's say we have a function to get the head of the list: ```rust impl<T> RcuList<T> { pub fn head<'a>(&self, guard: &'a rcu::Guard) -> &'a T { self.head.get(guard) } } ``` When the list is modified at runtime, we need to protect it from concurrent changes, so it would be protected by some synchronisation primitive like a mutex: ```rust struct Process { thread_list: Mutex<RcuList<Thread>>; /* ... */ } ``` So when we have a `Process`, how can we access the first thread? ```rust fn example(p: &Process) { // Modification requires the mutex to be locked. { let mut guard = p.thread_list.lock(); // Here we can make changes, all is fine. } // How do access the list through rcu? { let rcu_guard = rcu::read_lock(); // How to do it? let head = p.thread_list.rcu_stuff().head; } } ``` https://github.com/nbdd0121/linux/tree/projection https://github.com/nbdd0121/linux/commit/6aaa6ac8390add6e89c676a8bec9de75c11adcbe ```rust= struct Rcu; #[derive(kernel::projection::Field, RcuField)] struct Test { a: Rcu<Box<u32>>, b: i32, next: Rcu<Box<Test>>, } struct test { struct mutex mutex; u32 __rcu *a; int b; struct test __rcu *next; }; /* unsafe auto trait NoRcu {} impl<T> !NoRcu for Rcu<T> {} impl<T> DerefMut for MutexGuard<T> where T: NoRcu {}*/ fn foo(data: &Rcu<Box<Test>>) { } fn reader(data: &RcuLock<Mutex<Test>>) { /* reader(struct test* data) */ let a_ptr /*: &Rcu<Box<u32>>*/ = project!(data => a); /* a_ptr = &data->a; */ let next_ptr = project!(data => next); /* next_ptr = &data->next; */ let rcu_guard = rcu::read_lock(); /* rcu_read_lock(); */ let a: &u32 = a_ptr.get(&rcu_guard); /* a = rcu_dereference(*a_ptr) */ let next: &Test = project!(data => next).get(&rcu_guard); /* next = rcu_dereference(*next_ptr) */ /* rcu_read_unlock(); // automatically called on rcu_guard drop */ } fn writer(data: &RcuLock<Mutex<Test>>) { let mut guard = data.lock(); // guard does not give `&mut Test`! // Use projection to get a mutable reference *project!(&mut guard => b) = 10; let _: &Rcu = project!(&mut guard => a); // This will only give an immutable reference let _: &Rcu = project!(&*data => a); // Still able to get an immutable reference while mutex is locked. drop(guard); // Read can be done directly pr_info!("Value: {}\n", data.lock().b); } ``` ## `async` roadmap https://hackmd.io/HiJs8RMZSBmQNJoWHcH3Tw ```rust= #[derive(Debug)] pub enum RustAST { /// Struct field contain 3 type of information /// `Struct(Visibility, Name, Attributes)` Struct(Option<String>, String, Vec<RustAST>), /// An attributed contains the following fields /// `Field(Visibility, Name. Type)` Field(Option<String>, String, Rc<RustAST>), /// Field Type /// `FieldType(Reference, Mutable, Lifetime, GenType, TypeName)` FieldType(bool, bool, Option<String>, Option<Rc<RustAST>>, String), } enum AST { Struct(StructAST) } struct StructAST { filed: String span: Span, } fn foo() { let ast = parse_struct!(...); } ```