# 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!(...);
}
```