class PerCpuState

Defined at line 47 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 3 bits: a writes enabled bit, a

pending write bit, and a timer pending bit. When a cpu wants to write, it atomically checks if

the write enabled bit is set, and if so, sets the pending write bit and checks the write-enabled

bit again before proceeding. When it is done, it resets the pending write bit, ignoring the

writes enabled 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

pending writes or timers can start. We then wait for the pending write bit and pending timer bit

to reset on each cpu. Only then do we know that no additional writes will occur.

Public Methods

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

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

bool SetPendingWrite ()

Atomically mark a pending write to the write state iff writes are enabled and returns true.

Returns false if a pending write was not set because writes are not enabled.

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

void PerCpuState ()

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

void ResetPendingWrite ()

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

void EnableWrites ()

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

void DisableWrites ()

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

zx::result<AllocatedRecord> 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 81 of file ../../zircon/kernel/lib/thread_sampler/include/lib/thread_sampler/per_cpu_state.h

size_t AvailableBytes ()

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

bool WritesEnabled ()

True if the kWritesEnabled bit is set

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

bool PendingWrites ()

True if the kPendingWrite bit is set

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

bool PendingTimer ()

True if the kPendingTimer bit is set

Defined at line 96 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 101 of file ../../zircon/kernel/lib/thread_sampler/per_cpu_state.cc

bool CancelTimer ()

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

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