vpp_plugin/vlib/main/mod.rs
1//! VPP vlib main structure wrapper
2//!
3//! This module contains abstractions around VPP's `vlib_main_t` structure.
4//! It provides safe access to the main VPP library context.
5
6use std::ops::Deref;
7
8use crate::bindings::vlib_main_t;
9
10pub mod sync;
11
12/// Reference to VPP per-thread main library context
13///
14/// This is a safe wrapper around `vlib_main_t`, providing access to its fields.
15///
16/// A `&mut MainRef` is equivalent to a `vlib_main_t *` in C (a `*mut vlib_main_t` in Rust).
17///
18/// See also [`BarrierHeldMainRef`] for a variant that indicates the caller holds the
19/// main thread barrier.
20#[repr(transparent)]
21pub struct MainRef(foreign_types::Opaque);
22
23impl MainRef {
24 /// Creates a `&mut MainRef` directly from a pointer
25 ///
26 /// # Safety
27 /// - The pointer must be valid and a properly initialised `vlib_main_t` for the thread.
28 /// - The pointer must stay valid and the contents must not be mutated for the duration of the
29 /// lifetime of the returned object.
30 /// - The `vlib_main_t` must have been created by VPP at startup and not manually by the
31 /// caller, as many datastructures size the memory they allocate by the number of threads
32 /// at startup and are subsequently indexed by thread index.
33 pub unsafe fn from_ptr_mut<'a>(ptr: *mut vlib_main_t) -> &'a mut Self {
34 // SAFETY: caller must ensure the safety requirements are met
35 unsafe { &mut *(ptr as *mut _) }
36 }
37
38 /// Returns the raw pointer to the underlying `vlib_main_t`
39 pub fn as_ptr(&self) -> *mut vlib_main_t {
40 self as *const _ as *mut _
41 }
42
43 /// Returns the 0-based thread index of this VPP main context
44 pub fn thread_index(&self) -> u16 {
45 // SAFETY: as long as `self` is a valid `MainRef`, so is the pointer dereference
46 unsafe { (*self.as_ptr()).thread_index }
47 }
48}
49
50/// Reference to VPP per-thread main library context with barrier held
51///
52/// This is a safe wrapper around `vlib_main_t`, providing access to its fields.
53///
54/// A `&mut BarrierHeldMainRef` is equivalent to a `vlib_main_t *` in C (a `*mut vlib_main_t` in
55/// Rust).
56///
57/// See also [`MainRef`] for a variant without the constraint that the caller holds the
58/// main thread barrier.
59pub struct BarrierHeldMainRef(MainRef);
60
61impl BarrierHeldMainRef {
62 /// Creates a `&mut BarrierHeldMainRef` directly from a pointer
63 ///
64 /// # Safety
65 /// - All the safety requirements of [`MainRef::from_ptr_mut`] apply.
66 /// - Additionally, the caller must that no other thread is concurrently accessing VPP data
67 /// structures. This is typically ensured by holding the main thread barrier, but also
68 /// applies during initialisation before worker threads are started or shutdown after
69 /// worker threads are stopped.
70 pub unsafe fn from_ptr_mut<'a>(ptr: *mut vlib_main_t) -> &'a mut Self {
71 // SAFETY: caller must ensure the safety requirements are met
72 unsafe {
73 // Sanity check: barrier should only ever be held on main thread
74 debug_assert!((*ptr).thread_index == 0);
75 &mut *(ptr as *mut _)
76 }
77 }
78}
79
80impl Deref for BarrierHeldMainRef {
81 type Target = MainRef;
82
83 fn deref(&self) -> &Self::Target {
84 &self.0
85 }
86}