1.The TaskHeader

💡
There are some comments in the code above. it maybe useful to understand the following parts of the article, for the TaskHeader almost contains all information about a task.
Here, we set the poll_fn , a func pointer to TaskStorage::<F>::poll instead of our main task’s poll, which is generated by compiler. When we set the value, we won’t call the func poll .
This func will be mentioned below.
Then we set the future to our main future. And create a TaskRef , a pointer to the TaskStorage .
Finally, we wrap the task ptr to a SpawnToken so that the task will be scheduled by the executor.

2. How to make my function like async function with OSTimeDly as await

2.1 first need to understand the macro task in embassy

from file embassy-executor-macros/src/lib.rs:27
it’s easy to understand the args and item in the function signature. And the args and f in the body corresponding to the input args and item. So the important part that do the practical thing is task::run part.

2.2 the task run part

from embassy-executor-macros/src/macros/task.rs:15
this is really long to say, I beak it down.

2.2.1 check the arg input

from this part, we get the args pool_size. Below is the default value setting for unwrap_or
it construct a literal expression which has no attributes and it’s literal value is a literal int with value 1. The Span::call_site()(part of proc_macro2), where the Span object is to report the src location when error occurs and so this means it will point to the use/call of macro to help developer debug.

2.2.2 check the function input

So the function should without: generic, `where` clauses, ABI qualifier and variadic. It's return should either not return a value, return `()` or return `!`. And most importantly, it should be async.

2.2.3 tackle the input arguments of function

note the check above allow no self arguments and only allow ident pattern.

2.2.4 construct the task’s signature

this clone the ident into task_ident and give a new ident with __{task_ident}_task into the task_inner_ident
this Clone f into task_inner and Clone the visibility of task_inner then Set task_inner visibility to Inherited. Visibility::Inherited means that the visibility is not specified in the source code and should be inherited from the surrounding context. This is typically used for items within a module or a trait. finally Set task_inner identifier to task_inner_ident

2.2.5 assemble the original input arguments

Generate tokens with quote! macro: Inside the loop, the quote! macro is used to generate tokens. The quote! macro is a powerful tool in procedural macros for generating Rust code. The syntax #(#cfgs)* uses repetition inside the quote! macro to iterate over cfgs and include each element in the output. The #arg syntax injects the value of arg into the generated tokens.
this process is simple to understand if you take a closer look.
it define the origin func(which is task_ident), the body of this function is different from origin:
it define the pool_size and also new the TaskPool with the defined pool_size as pool. Finally it use spawn_async_fn of type Taskpool to set our origin task function as a future function(this future just means this function is FutFn: FnOnce() -> F and F is F: Future + 'static, which is exactly what async most does)

Conclusion

According to the research on task macro of embassy, we can find that the implementation of async in RTOS is mainly depending on the rust language itself, as we need the concept of future. The keywords async mostly convert our original plain function to the closure that is FnOnce() -> F , where F is F: Future + 'static. There seems no practical solution to support other language.
But I still have some ideas to support what we may implement in further future:

Thoughts

we can write in rust with dynamic/fixed number of async tasks which is very light and switch fast to perform what an OS do to schedule and the tasks’s job is like a tiny OS, which can perform execute multiple(also one) threads, with which it can support other language to use the async like a thread but with better performance.
But now, I think we can first do jobs based on embassy to support priority preempt and only support rust to verify our understanding and make necessary prerequisites for our next level improvements.
 
Loading...
Noah
Noah
永远年轻,永远热泪盈眶
公告
❗❗复习笔记问题❗❗
由于兼容性问题
导入md文件可能导致了一些格式错误
🌹如发现格式错误,请联系我~🌹
🌹如博客内容有误也欢迎指出~🌹