Skip to content

Commit

Permalink
WIPrust
Browse files Browse the repository at this point in the history
  • Loading branch information
douglas-raillard-arm committed Jan 15, 2024
1 parent 53dbb01 commit 074f424
Showing 1 changed file with 51 additions and 51 deletions.
102 changes: 51 additions & 51 deletions tools/trace-parser/traceevent/src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ use crate::{
// Keep a BTreeMap for fast lookup and to avoid huge Vec allocation in case
// some event ids are very large. Since most traces will contain just a few
// types of events, build up the smallest mapping as it goes.
struct EventDescMap<'h, T, InitDescF> {
struct EventDescMap<'h, Ctx, MakeCtx> {
header: &'h Header,
cold_map: BTreeMap<EventId, &'h EventDesc>,
hot_map: BTreeMap<EventId, (&'h EventDesc, T)>,
init_desc: Arc<Mutex<InitDescF>>,
hot_map: BTreeMap<EventId, (&'h EventDesc, Ctx)>,
make_ctx: Arc<Mutex<MakeCtx>>,
}

impl<'h, T: Debug, InitDescF> Debug for EventDescMap<'h, T, InitDescF> {
impl<'h, Ctx: Debug, MakeCtx> Debug for EventDescMap<'h, Ctx, MakeCtx> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
f.debug_struct("EventDescMap")
.field("cold_map", &self.cold_map)
Expand All @@ -53,11 +53,11 @@ impl<'h, T: Debug, InitDescF> Debug for EventDescMap<'h, T, InitDescF> {
}
}

impl<'h, T, InitDescF> EventDescMap<'h, T, InitDescF>
impl<'h, Ctx, MakeCtx> EventDescMap<'h, Ctx, MakeCtx>
where
InitDescF: FnMut(&'h Header, &'h EventDesc) -> T + 'h,
MakeCtx: FnMut(&'h Header, &'h EventDesc) -> Ctx + 'h,
{
fn new(header: &'h Header, init_desc: Arc<Mutex<InitDescF>>) -> Self {
fn new(header: &'h Header, make_ctx: Arc<Mutex<MakeCtx>>) -> Self {
EventDescMap {
header,
cold_map: header
Expand All @@ -66,20 +66,20 @@ where
.map(|desc| (desc.id, desc))
.collect(),
hot_map: BTreeMap::new(),
init_desc,
make_ctx,
}
}
#[inline]
fn lookup<'edm>(&'edm mut self, id: EventId) -> Option<(&'h EventDesc, &'edm T)> {
fn lookup<'edm>(&'edm mut self, id: EventId) -> Option<(&'h EventDesc, &'edm Ctx)> {
match self.hot_map.entry(id) {
Entry::Occupied(entry) => {
let (desc, ctx) = entry.into_mut();
Some((*desc, ctx))
}
Entry::Vacant(entry) => match self.cold_map.remove(&id) {
Some(desc) => {
let mut init_desc = self.init_desc.lock().unwrap();
let (desc, ctx) = entry.insert((desc, init_desc(self.header, desc)));
let mut make_ctx = self.make_ctx.lock().unwrap();
let (desc, ctx) = entry.insert((desc, make_ctx(self.header, desc)));
Some((*desc, ctx))
}
None => None,
Expand All @@ -88,7 +88,7 @@ where
}
}

pub struct EventVisitor<'i, 'h, 'edm, InitDescF, T = ()> {
pub struct EventVisitor<'i, 'h, 'edm, MakeCtx, Ctx = ()> {
pub data: &'i [u8],
pub header: &'h Header,

Expand All @@ -99,19 +99,19 @@ pub struct EventVisitor<'i, 'h, 'edm, InitDescF, T = ()> {
// stored in it can change at any time, even if the EventVisitor is only manipulated via shared
// ref.
_desc_map: UnsafeCell<
// Using *mut here means EventVisitor is invariant in any lifetime contained in T.
// Using *mut here means EventVisitor is invariant in any lifetime contained in Ctx.
// However, the only values we store in the EventDescMap are either owned by it or have a
// longer lifetime ('h outlives 'edm), so it's sound to be covariant in 'edm. So in
// practice we use 'static but then we cast back to 'h.
*mut EventDescMap<'static, T, InitDescF>,
*mut EventDescMap<'static, Ctx, MakeCtx>,
>,
// What we really store is:
// &'edm mut EventDescMap<'h, T, InitDescF>,
// &'edm mut EventDescMap<'h, Ctx, MakeCtx>,
// But because of variance limitation, we use *mut instead of &mut and we use 'static instead
// of 'h
_phantom_desc_map: PhantomData<(
&'edm mut EventDescMap<'static, T, InitDescF>,
&'edm EventDescMap<'h, T, InitDescF>,
&'edm mut EventDescMap<'static, Ctx, MakeCtx>,
&'edm EventDescMap<'h, Ctx, MakeCtx>,
)>,

scratch: &'i ScratchAlloc,
Expand All @@ -123,25 +123,25 @@ pub struct EventVisitor<'i, 'h, 'edm, InitDescF, T = ()> {
// So to stay covariant in 'h, we use *const instead of &'h. This is fine as we only initialize
// the OnceCell with a value that does live for 'h, as all the inputs of that computation are
// stored when the EventVisitor is created.
event_desc: OnceCell<(*const EventDesc, *const T)>,
event_desc: OnceCell<(*const EventDesc, *const Ctx)>,
}

impl<'i, 'h, 'edm, InitDescF, T> EventVisitor<'i, 'h, 'edm, InitDescF, T> {
impl<'i, 'h, 'edm, MakeCtx, Ctx> EventVisitor<'i, 'h, 'edm, MakeCtx, Ctx> {
fn new(
header: &'h Header,
buffer_id: &'h BufferId,
timestamp: Timestamp,
data: &'i [u8],
scratch: &'i ScratchAlloc,
desc_map: &'edm mut EventDescMap<'h, T, InitDescF>,
desc_map: &'edm mut EventDescMap<'h, Ctx, MakeCtx>,
) -> Self {
// SAFETY: Erase the lifetime 'h and replace by 'static so that we stay covariant in 'h. We
// won't be using the desc_map reference past 'h since:
// * 'h outlives 'edm
// * we don't leak self.desc_map anywhere without attaching the 'edm lifetime to what was
// leaked
let desc_map: &'edm mut EventDescMap<'static, T, InitDescF> = {
let desc_map: &'edm mut EventDescMap<'h, T, InitDescF> = desc_map;
let desc_map: &'edm mut EventDescMap<'static, Ctx, MakeCtx> = {
let desc_map: &'edm mut EventDescMap<'h, Ctx, MakeCtx> = desc_map;
unsafe { core::mem::transmute(desc_map) }
};

Expand All @@ -157,19 +157,19 @@ impl<'i, 'h, 'edm, InitDescF, T> EventVisitor<'i, 'h, 'edm, InitDescF, T> {
}
}

fn __check_covariance_i<'i1>(self) -> EventVisitor<'i1, 'h, 'edm, InitDescF, T>
fn __check_covariance_i<'i1>(self) -> EventVisitor<'i1, 'h, 'edm, MakeCtx, Ctx>
where
'i: 'i1,
{
self
}
fn __check_covariance_h<'h1>(self) -> EventVisitor<'i, 'h1, 'edm, InitDescF, T>
fn __check_covariance_h<'h1>(self) -> EventVisitor<'i, 'h1, 'edm, MakeCtx, Ctx>
where
'h: 'h1,
{
self
}
fn __check_covariance_edm<'edm1>(self) -> EventVisitor<'i, 'h, 'edm1, InitDescF, T>
fn __check_covariance_edm<'edm1>(self) -> EventVisitor<'i, 'h, 'edm1, MakeCtx, Ctx>
where
'edm: 'edm1,
{
Expand All @@ -181,9 +181,9 @@ impl<'i, 'h, 'edm, InitDescF, T> EventVisitor<'i, 'h, 'edm, InitDescF, T> {
pub trait CaptureLifetime<'a> {}
impl<T: ?Sized> CaptureLifetime<'_> for T {}

impl<'i, 'h, 'edm, InitDescF, T> EventVisitor<'i, 'h, 'edm, InitDescF, T>
impl<'i, 'h, 'edm, MakeCtx, Ctx> EventVisitor<'i, 'h, 'edm, MakeCtx, Ctx>
where
InitDescF: 'h + FnMut(&'h Header, &'h EventDesc) -> T,
MakeCtx: 'h + FnMut(&'h Header, &'h EventDesc) -> Ctx,
{
pub fn fields<'a>(
&'a self,
Expand Down Expand Up @@ -248,19 +248,19 @@ where

// FIXME: is it sound to derive that &mut EventDescMap from an &self ? Could this lead to
// creating multiple &mut ref alive at the same time ?
fn desc_map(&'edm self) -> &'edm mut EventDescMap<'h, T, InitDescF> {
fn desc_map(&'edm self) -> &'edm mut EventDescMap<'h, Ctx, MakeCtx> {
// SAFETY: This comes from an &'edm mut reference in the first place, and since
// EventVisitor::new() requires an &'edm mut EventDescMap, we cannot accidentally
// borrow it mutably more than once. This makes it safe to turn it back to an &'edm
// mut.
let desc_map: *mut *mut EventDescMap<'static, T, InitDescF> = self._desc_map.get();
let desc_map: &'edm mut EventDescMap<'static, T, InitDescF> = unsafe { &mut **desc_map };
let desc_map: &'edm mut EventDescMap<'h, T, InitDescF> =
let desc_map: *mut *mut EventDescMap<'static, Ctx, MakeCtx> = self._desc_map.get();
let desc_map: &'edm mut EventDescMap<'static, Ctx, MakeCtx> = unsafe { &mut **desc_map };
let desc_map: &'edm mut EventDescMap<'h, Ctx, MakeCtx> =
unsafe { core::mem::transmute(desc_map) };
desc_map
}

fn event_entry(&self) -> Result<(&'h EventDesc, &'edm T), BufferError> {
fn event_entry(&self) -> Result<(&'h EventDesc, &'edm Ctx), BufferError> {
self.event_desc
.get_or_try_init(|| {
let event_id = self.event_id()?;
Expand All @@ -269,13 +269,13 @@ where
Ok((desc, ctx))
})
.map(|(desc, ctx)| {
let ctx: *const T = *ctx;
let ctx: *const Ctx = *ctx;
let desc: *const EventDesc = *desc;
// SAFETY: EventDescMap::lookup() returns (&'h EventDesc, &'edm T), which we store
// as (*const EventDesc, *const T) to avoid variance issues. It's therefore
// SAFETY: EventDescMap::lookup() returns (&'h EventDesc, &'edm Ctx), which we store
// as (*const EventDesc, *const Ctx) to avoid variance issues. It's therefore
// completely safe to just cast it back to &'h EventDesc.
let desc: &'h EventDesc = unsafe { &*desc };
let ctx: &'edm T = unsafe { &*ctx };
let ctx: &'edm Ctx = unsafe { &*ctx };
(desc, ctx)
})
}
Expand All @@ -284,7 +284,7 @@ where
Ok(self.event_entry()?.0)
}

pub fn event_ctx(&self) -> Result<&'edm T, BufferError> {
pub fn event_ctx(&self) -> Result<&'edm Ctx, BufferError> {
Ok(self.event_entry()?.1)
}

Expand Down Expand Up @@ -646,11 +646,11 @@ impl Type {

use core::cmp::Ordering;
#[derive(Debug)]
struct BufferItem<'a, T, InitDescF>(
struct BufferItem<'a, Ctx, MakeCtx>(
Result<
(
&'a Header,
&'a mut EventDescMap<'a, T, InitDescF>,
&'a mut EventDescMap<'a, Ctx, MakeCtx>,
&'a BufferId,
Timestamp,
&'a [u8],
Expand All @@ -659,7 +659,7 @@ struct BufferItem<'a, T, InitDescF>(
>,
);

impl<'a, T, InitDescF> PartialEq for BufferItem<'a, T, InitDescF> {
impl<'a, Ctx, MakeCtx> PartialEq for BufferItem<'a, Ctx, MakeCtx> {
#[inline]
fn eq(&self, other: &Self) -> bool {
match (&self.0, &other.0) {
Expand All @@ -669,16 +669,16 @@ impl<'a, T, InitDescF> PartialEq for BufferItem<'a, T, InitDescF> {
}
}

impl<'a, T, InitDescF> Eq for BufferItem<'a, T, InitDescF> {}
impl<'a, Ctx, MakeCtx> Eq for BufferItem<'a, Ctx, MakeCtx> {}

impl<'a, T, InitDescF> PartialOrd for BufferItem<'a, T, InitDescF> {
impl<'a, Ctx, MakeCtx> PartialOrd for BufferItem<'a, Ctx, MakeCtx> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl<'a, T, InitDescF> Ord for BufferItem<'a, T, InitDescF> {
impl<'a, Ctx, MakeCtx> Ord for BufferItem<'a, Ctx, MakeCtx> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
match (&self.0, &other.0) {
Expand Down Expand Up @@ -857,34 +857,34 @@ unsafe fn transmute_lifetime_mut<'b, T: ?Sized>(x: &mut T) -> &'b mut T {
core::mem::transmute(x)
}

pub fn flyrecord<'i, 'h, R, F, InitDescF, T, IntoIter>(
pub fn flyrecord<'i, 'h, R, F, IntoIter, MakeCtx, Ctx>(
buffers: IntoIter,
mut f: F,
init_desc: InitDescF,
make_ctx: MakeCtx,
) -> Result<impl IntoIterator<Item = R> + 'h + CaptureLifetime<'i>, BufferError>
where
IntoIter: IntoIterator<Item = Buffer<'i, 'h>>,
F: 'h
+ for<'i1, 'edm> FnMut(Result<EventVisitor<'i1, 'h, 'edm, InitDescF, T>, BufferError>) -> R,
InitDescF: 'h + FnMut(&'h Header, &'h EventDesc) -> T,
T: 'h,
+ for<'i1, 'edm> FnMut(Result<EventVisitor<'i1, 'h, 'edm, MakeCtx, Ctx>, BufferError>) -> R,
MakeCtx: 'h + FnMut(&'h Header, &'h EventDesc) -> Ctx,
Ctx: 'h,
'i: 'h,
{
let init_desc = Arc::new(Mutex::new(init_desc));
let make_ctx = Arc::new(Mutex::new(make_ctx));

macro_rules! make_record_iter {
($buffer:expr) => {{
let mut buffer = $buffer;
let buf_id = buffer.id;
let header = buffer.header;
let timestamp_fixer = header.timestamp_fixer();
let init_desc = Arc::clone(&init_desc);
let make_ctx = Arc::clone(&make_ctx);

// Each buffer will have its own hot map which is not ideal, but the
// maps contain &EventDesc so the descriptor itself actually lives
// in the header and is shared. This ensures we will not parse event
// format more than once, which is the main cost here.
let mut desc_map = EventDescMap::new(header, init_desc);
let mut desc_map = EventDescMap::new(header, make_ctx);
gen!({
loop {
match extract_page(header, &buf_id, &mut buffer.reader, buffer.page_size) {
Expand Down

0 comments on commit 074f424

Please sign in to comment.