class PerCpuState

Defined at line 45 of file ../../zircon/kernel/lib/thread_sampler/include/lib/thread_sampler/per_cpu_state.h

When we start sampling, we assign and pin a VmObject buffer to each CPU for it to write on. We

also assign a per cpu timer. When the timer triggers, we mark a thread to write a sample to the

buffer. When the thread will at some point in the future when it is safe to do so, write a

sample.

This creates the main problem: how do we safely clean up when we stop? If we are handling a stop

request on one core, it's not safe to immediately clean up the buffers since another core could

be writing a sample or could be scheduled to write a sample. To do this safely, we have a three

phase shutdown:

1) Disable new writes and new timers

2) Cancel existing timers and wait for any lingering timers to clear out

3) Wait for any in progress writes to stop

Now it's safe to destroy our state.

So then, each cpu state also contains an atomic variable with 2 bits: a writes enabled bit, and a

timer pending bit.

The timer callback receives a pointer to the PerCpuState and the timer pending bit ensures that

the per cpu state lives longer than the timer callback.

Now, when we want to clean up, on each cpu, we reset the writes enabled bit, knowing that no new

timers can start. We then wait for the pending timer bit to reset on each cpu. We also wait for

any active references to the buffers (tracked via ref count in ThreadSampler) to be released.

Only then do we know that no additional writes will occur.

Public Methods

zx::result<> SetUp (const zx_sampler_config_t & config, cpu_num_t cpu_number)

Defined at line 8 of file ../../zircon/kernel/lib/thread_sampler/per_cpu_state.cc

void EnableWrites ()

Defined at line 21 of file ../../zircon/kernel/lib/thread_sampler/per_cpu_state.cc

void DisableWrites ()

Defined at line 25 of file ../../zircon/kernel/lib/thread_sampler/per_cpu_state.cc

bool WritesEnabled ()

True if the kWritesEnabled bit is set

Defined at line 29 of file ../../zircon/kernel/lib/thread_sampler/per_cpu_state.cc

bool PendingTimer ()

True if the kPendingTimer bit is set

Defined at line 34 of file ../../zircon/kernel/lib/thread_sampler/per_cpu_state.cc

void SetTimer ()

Atomically set a timer if writes are enabled. When the timer goes off, whatever thread is

currently active will be signaled to be sampled.

Defined at line 39 of file ../../zircon/kernel/lib/thread_sampler/per_cpu_state.cc

void PerCpuState ()

Defined at line 47 of file ../../zircon/kernel/lib/thread_sampler/include/lib/thread_sampler/per_cpu_state.h

zx::result<percpu_writer::Buffer::Reservation> Reserve (uint64_t header)

Reserve space in the assigned pinned memory. The AllocatedRecord will ensure the underlying

buffers live long enough to write to.

Defined at line 69 of file ../../zircon/kernel/lib/thread_sampler/include/lib/thread_sampler/per_cpu_state.h

template <CopyOutFunction CopyFunc>
zx::result<uint32_t> Read (CopyFunc copy_fn, uint32_t len)

Reads from the underlying SpscBuffer.

Defined at line 75 of file ../../zircon/kernel/lib/thread_sampler/include/lib/thread_sampler/per_cpu_state.h

size_t BufferSize ()

Defined at line 79 of file ../../zircon/kernel/lib/thread_sampler/include/lib/thread_sampler/per_cpu_state.h

void Drain ()

Defined at line 80 of file ../../zircon/kernel/lib/thread_sampler/include/lib/thread_sampler/per_cpu_state.h

bool CancelTimer ()

True if the per cpu timer was canceled before it was scheduled else false

Defined at line 97 of file ../../zircon/kernel/lib/thread_sampler/per_cpu_state.cc