Skip to content

Commit b9f9555

Browse files
committed
[EventPipe][BufferManager] Track thread_session_state
When the buffer_manager iterates over events across threads, it tracks the current EventPipeEventInstance, EventPipeBuffer, and EventPipeBufferList. In preparation to remove ThreadSessionStates from the buffer_manager's thread_session_state_list, tracking the current ThreadSessionState instead of the current EventPipeBufferList will allow for direct removal, as they are 1:1. ep_buffer_manager_write_all_buffers_to_file_v4 adjusts sequence points tss:sequence_number mappings whenever events have been read from the tss. Instead of having the tss' underlying buffer_list track the last read sequence point, move the counter to the tss itself.
1 parent ac26ea8 commit b9f9555

File tree

4 files changed

+37
-57
lines changed

4 files changed

+37
-57
lines changed

src/native/eventpipe/ep-buffer-manager.c

Lines changed: 28 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,7 @@ static
113113
EventPipeBuffer *
114114
buffer_manager_advance_to_non_empty_buffer (
115115
EventPipeBufferManager *buffer_manager,
116-
EventPipeBufferList *buffer_list,
117-
EventPipeBuffer *buffer,
116+
EventPipeThreadSessionState *thread_session_state,
118117
ep_timestamp_t before_timestamp);
119118

120119
// Detaches this buffer from an active writer thread and marks it read-only so that the reader
@@ -164,7 +163,6 @@ ep_buffer_list_init (
164163
buffer_list->head_buffer = NULL;
165164
buffer_list->tail_buffer = NULL;
166165
buffer_list->buffer_count = 0;
167-
buffer_list->last_read_sequence_number = 0;
168166

169167
return buffer_list;
170168
}
@@ -446,7 +444,6 @@ buffer_manager_allocate_buffer_for_thread (
446444
EP_ASSERT (request_size > 0);
447445

448446
EventPipeBuffer *new_buffer = NULL;
449-
EventPipeBufferList *thread_buffer_list = NULL;
450447
EventPipeSequencePoint* sequence_point = NULL;
451448
uint32_t sequence_number = 0;
452449

@@ -487,11 +484,9 @@ buffer_manager_allocate_buffer_for_thread (
487484
new_buffer = ep_buffer_alloc (buffer_size, ep_thread_session_state_get_thread (thread_session_state), sequence_number);
488485
ep_raise_error_if_nok (new_buffer != NULL);
489486

487+
// Allocating a new EventPipeSequencePoint and adding to the sequence_point list requires the buffer manager lock.
490488
// Adding a buffer to the buffer list requires us to take the lock.
491489
EP_SPIN_LOCK_ENTER (&buffer_manager->rt_lock, section1)
492-
thread_buffer_list = ep_thread_session_state_get_buffer_list (thread_session_state);
493-
EP_ASSERT(thread_buffer_list != NULL);
494-
495490
if (buffer_manager->sequence_point_alloc_budget != 0) {
496491
// sequence point bookkeeping
497492
if (buffer_size >= buffer_manager->remaining_sequence_point_alloc_budget) {
@@ -515,7 +510,6 @@ buffer_manager_allocate_buffer_for_thread (
515510
ep_buffer_list_insert_tail (ep_thread_session_state_get_buffer_list (thread_session_state), new_buffer);
516511
ep_thread_session_state_set_write_buffer (thread_session_state, new_buffer);
517512
}
518-
519513
EP_SPIN_LOCK_EXIT (&buffer_manager->rt_lock, section1)
520514

521515
ep_on_exit:
@@ -566,34 +560,25 @@ buffer_manager_move_next_event_any_thread (
566560

567561
buffer_manager->current_event = NULL;
568562
buffer_manager->current_buffer = NULL;
569-
buffer_manager->current_buffer_list = NULL;
563+
buffer_manager->current_thread_session_state = NULL;
570564

571565
// We need to do this in two steps because we can't hold m_lock and EventPipeThread::m_lock
572566
// at the same time.
573567

574568
// Step 1 - while holding m_lock get the oldest buffer from each thread
575569
DN_DEFAULT_LOCAL_ALLOCATOR (allocator, dn_vector_ptr_default_local_allocator_byte_size * 2);
576570

577-
dn_vector_ptr_t buffer_array;
578-
dn_vector_ptr_t buffer_list_array;
579-
580-
dn_vector_ptr_custom_init_params_t params = {0, };
581-
params.allocator = (dn_allocator_t *)&allocator;
582-
params.capacity = dn_vector_ptr_default_local_allocator_capacity_size;
583-
584-
ep_raise_error_if_nok (dn_vector_ptr_custom_init (&buffer_array, &params));
585-
ep_raise_error_if_nok (dn_vector_ptr_custom_init (&buffer_list_array, &params));
571+
dn_list_t *cached_thread_session_state_list = dn_list_alloc ();
572+
ep_raise_error_if_nok (cached_thread_session_state_list != NULL);
586573

587574
EP_SPIN_LOCK_ENTER (&buffer_manager->rt_lock, section1)
588575
EventPipeBufferList *buffer_list;
589576
EventPipeBuffer *buffer;
590577
DN_LIST_FOREACH_BEGIN (EventPipeThreadSessionState *, thread_session_state, buffer_manager->thread_session_state_list) {
591578
buffer_list = ep_thread_session_state_get_buffer_list (thread_session_state);
592579
buffer = buffer_list->head_buffer;
593-
if (buffer && ep_buffer_get_creation_timestamp (buffer) < stop_timestamp) {
594-
dn_vector_ptr_push_back (&buffer_list_array, buffer_list);
595-
dn_vector_ptr_push_back (&buffer_array, buffer);
596-
}
580+
if (buffer && ep_buffer_get_creation_timestamp (buffer) < stop_timestamp)
581+
dn_list_push_back (cached_thread_session_state_list, thread_session_state);
597582
} DN_LIST_FOREACH_END;
598583
EP_SPIN_LOCK_EXIT (&buffer_manager->rt_lock, section1)
599584

@@ -603,32 +588,26 @@ buffer_manager_move_next_event_any_thread (
603588
ep_timestamp_t oldest_timestamp;
604589
oldest_timestamp = stop_timestamp;
605590

606-
EventPipeBufferList *buffer_list;
607-
EventPipeBuffer *head_buffer;
608591
EventPipeBuffer *buffer;
609592
EventPipeEventInstance *next_event;
610-
611-
for (uint32_t i = 0; i < dn_vector_ptr_size (&buffer_array) && i < dn_vector_ptr_size (&buffer_list_array); ++i) {
612-
buffer_list = (EventPipeBufferList *)*dn_vector_ptr_index (&buffer_list_array, i);
613-
head_buffer = (EventPipeBuffer *)*dn_vector_ptr_index (&buffer_array, i);
614-
buffer = buffer_manager_advance_to_non_empty_buffer (buffer_manager, buffer_list, head_buffer, stop_timestamp);
593+
DN_LIST_FOREACH_BEGIN (EventPipeThreadSessionState *, thread_session_state, cached_thread_session_state_list) {
594+
buffer = buffer_manager_advance_to_non_empty_buffer (buffer_manager, thread_session_state, stop_timestamp);
615595
if (buffer) {
616596
// Peek the next event out of the buffer.
617597
next_event = ep_buffer_get_current_read_event (buffer);
618598
// If it's the oldest event we've seen, then save it.
619599
if (next_event && ep_event_instance_get_timestamp (next_event) < oldest_timestamp) {
620600
buffer_manager->current_event = next_event;
621601
buffer_manager->current_buffer = buffer;
622-
buffer_manager->current_buffer_list = buffer_list;
602+
buffer_manager->current_thread_session_state = thread_session_state;
623603
oldest_timestamp = ep_event_instance_get_timestamp (buffer_manager->current_event);
624604
}
625605
}
626-
}
606+
} DN_LIST_FOREACH_END;
627607

628608
ep_on_exit:
629609
ep_buffer_manager_requires_lock_not_held (buffer_manager);
630-
dn_vector_ptr_dispose (&buffer_list_array);
631-
dn_vector_ptr_dispose (&buffer_array);
610+
dn_list_free (cached_thread_session_state_list);
632611
return;
633612

634613
ep_on_error:
@@ -644,7 +623,7 @@ buffer_manager_move_next_event_same_thread (
644623
EP_ASSERT (buffer_manager != NULL);
645624
EP_ASSERT (buffer_manager->current_event != NULL);
646625
EP_ASSERT (buffer_manager->current_buffer != NULL);
647-
EP_ASSERT (buffer_manager->current_buffer_list != NULL);
626+
EP_ASSERT (buffer_manager->current_thread_session_state != NULL);
648627

649628
ep_buffer_manager_requires_lock_not_held (buffer_manager);
650629

@@ -653,11 +632,7 @@ buffer_manager_move_next_event_same_thread (
653632
ep_buffer_move_next_read_event (buffer_manager->current_buffer);
654633

655634
// Find the first buffer in the list, if any, which has an event in it
656-
buffer_manager->current_buffer = buffer_manager_advance_to_non_empty_buffer (
657-
buffer_manager,
658-
buffer_manager->current_buffer_list,
659-
buffer_manager->current_buffer,
660-
stop_timestamp);
635+
buffer_manager->current_buffer = buffer_manager_advance_to_non_empty_buffer (buffer_manager, buffer_manager->current_thread_session_state, stop_timestamp);
661636

662637
if (buffer_manager->current_buffer) {
663638
// get the event from that buffer
@@ -667,38 +642,37 @@ buffer_manager_move_next_event_same_thread (
667642
// event exists, but isn't early enough
668643
buffer_manager->current_event = NULL;
669644
buffer_manager->current_buffer = NULL;
670-
buffer_manager->current_buffer_list = NULL;
645+
buffer_manager->current_thread_session_state = NULL;
671646
} else {
672647
// event is early enough, set the new cursor
673648
buffer_manager->current_event = next_event;
674649
EP_ASSERT (buffer_manager->current_buffer != NULL);
675-
EP_ASSERT (buffer_manager->current_buffer_list != NULL);
650+
EP_ASSERT (buffer_manager->current_thread_session_state != NULL);
676651
}
677652
} else {
678653
// no more buffers prior to before_timestamp
679654
EP_ASSERT (buffer_manager->current_event == NULL);
680655
EP_ASSERT (buffer_manager->current_buffer == NULL);
681-
buffer_manager->current_buffer_list = NULL;
656+
buffer_manager->current_thread_session_state = NULL;
682657
}
683658
}
684659

685660
static
686661
EventPipeBuffer *
687662
buffer_manager_advance_to_non_empty_buffer (
688663
EventPipeBufferManager *buffer_manager,
689-
EventPipeBufferList *buffer_list,
690-
EventPipeBuffer *buffer,
664+
EventPipeThreadSessionState *thread_session_state,
691665
ep_timestamp_t before_timestamp)
692666
{
693667
EP_ASSERT (buffer_manager != NULL);
694-
EP_ASSERT (buffer_list != NULL);
695-
EP_ASSERT (buffer != NULL);
696-
EP_ASSERT (buffer_list->head_buffer == buffer);
668+
EP_ASSERT (thread_session_state != NULL);
697669

698670
ep_buffer_manager_requires_lock_not_held (buffer_manager);
699671

700-
EventPipeBuffer *current_buffer = buffer;
701-
bool done = false;
672+
EventPipeBufferList *buffer_list = ep_thread_session_state_get_buffer_list (thread_session_state);
673+
EP_ASSERT (buffer_list != NULL);
674+
EventPipeBuffer *current_buffer = buffer_list->head_buffer;
675+
EP_ASSERT (current_buffer != NULL);
702676
while (!done) {
703677
buffer_manager_convert_buffer_to_read_only (buffer_manager, current_buffer);
704678
if (ep_buffer_get_current_read_event (current_buffer) != NULL) {
@@ -818,7 +792,7 @@ ep_buffer_manager_alloc (
818792

819793
instance->current_event = NULL;
820794
instance->current_buffer = NULL;
821-
instance->current_buffer_list = NULL;
795+
instance->current_thread_session_state = NULL;
822796

823797
instance->max_size_of_all_buffers = EP_CLAMP ((size_t)100 * 1024, max_size_of_all_buffers, (size_t)UINT32_MAX);
824798

@@ -1155,7 +1129,7 @@ ep_buffer_manager_write_all_buffers_to_file_v4 (
11551129

11561130
uint64_t capture_thread_id = ep_thread_get_os_thread_id (ep_buffer_get_writer_thread (buffer_manager->current_buffer));
11571131

1158-
EventPipeBufferList *buffer_list = buffer_manager->current_buffer_list;
1132+
EventPipeThreadSessionState *current_thread_session_state = buffer_manager->current_thread_session_state;
11591133

11601134
// loop across events on this thread
11611135
bool events_written_for_thread = false;
@@ -1171,7 +1145,8 @@ ep_buffer_manager_write_all_buffers_to_file_v4 (
11711145
events_written_for_thread = true;
11721146
buffer_manager_move_next_event_same_thread (buffer_manager, current_timestamp_boundary);
11731147
}
1174-
buffer_list->last_read_sequence_number = sequence_number;
1148+
1149+
ep_thread_session_state_set_last_read_sequence_number (current_thread_session_state, sequence_number);
11751150
// Have we written events in any sequence point?
11761151
*events_written = events_written_for_thread || *events_written;
11771152
}
@@ -1193,7 +1168,7 @@ ep_buffer_manager_write_all_buffers_to_file_v4 (
11931168
EventPipeThreadSessionState *session_state = *dn_list_it_data_t (it, EventPipeThreadSessionState *);
11941169
dn_umap_it_t found = dn_umap_ptr_uint32_find (ep_sequence_point_get_thread_sequence_numbers (sequence_point), session_state);
11951170
uint32_t thread_sequence_number = !dn_umap_it_end (found) ? dn_umap_it_value_uint32_t (found) : 0;
1196-
uint32_t last_read_sequence_number = ep_thread_session_state_get_buffer_list (session_state)->last_read_sequence_number;
1171+
uint32_t last_read_sequence_number = ep_thread_session_state_get_last_read_sequence_number (session_state);
11971172
// Sequence numbers can overflow so we can't use a direct last_read > sequence_number comparison
11981173
// If a thread is able to drop more than 0x80000000 events in between sequence points then we will
11991174
// miscategorize it, but that seems unlikely.

src/native/eventpipe/ep-buffer-manager.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ struct _EventPipeBufferList_Internal {
2929
EventPipeBuffer *tail_buffer;
3030
// The number of buffers in the list.
3131
uint32_t buffer_count;
32-
// The sequence number of the last event that was read, only
33-
// updated/read by the reader thread.
34-
uint32_t last_read_sequence_number;
3532
};
3633

3734
#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_BUFFER_MANAGER_GETTER_SETTER)
@@ -97,7 +94,9 @@ struct _EventPipeBufferManager_Internal {
9794
// These are not protected by rt_lock and expected to only be used on the reader thread.
9895
EventPipeEventInstance *current_event;
9996
EventPipeBuffer *current_buffer;
100-
EventPipeBufferList *current_buffer_list;
97+
// The thread session state grabbed from the thread_session_state_list containing the current event
98+
// that is being processed by the reader thread.
99+
EventPipeThreadSessionState *current_thread_session_state;
101100
// The total allocation size of buffers under management.
102101
volatile size_t size_of_all_buffers;
103102
// The maximum allowable size of buffers under management.

src/native/eventpipe/ep-thread.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,7 @@ ep_thread_session_state_alloc (
317317

318318
instance->session = session;
319319
instance->sequence_number = 1;
320+
instance->last_read_sequence_number = 0;
320321

321322
instance->buffer_list = ep_buffer_list_alloc (buffer_manager);
322323
ep_raise_error_if_nok (instance->buffer_list != NULL);

src/native/eventpipe/ep-thread.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,9 @@ struct _EventPipeThreadSessionState_Internal {
270270
// The list of buffers that were written to by this thread.
271271
// immutable
272272
EventPipeBufferList *buffer_list;
273+
// The sequence number of the last event that was read, only
274+
// updated/read by the reader thread.
275+
uint32_t last_read_sequence_number;
273276
// The number of events that were attempted to be written by this
274277
// thread. Each event was either successfully recorded in a buffer
275278
// or it was dropped.
@@ -301,6 +304,8 @@ struct _EventPipeThreadSessionState {
301304
EP_DEFINE_GETTER_REF(EventPipeThreadSessionState *, thread_session_state, EventPipeThreadHolder *, thread_holder)
302305
EP_DEFINE_GETTER(EventPipeThreadSessionState *, thread_session_state, EventPipeBufferList *, buffer_list)
303306
EP_DEFINE_GETTER(EventPipeThreadSessionState *, thread_session_state, EventPipeSession *, session)
307+
EP_DEFINE_GETTER(EventPipeThreadSessionState *, thread_session_state, uint32_t, last_read_sequence_number);
308+
EP_DEFINE_SETTER(EventPipeThreadSessionState *, thread_session_state, uint32_t, last_read_sequence_number);
304309

305310
EventPipeThreadSessionState *
306311
ep_thread_session_state_alloc (

0 commit comments

Comments
 (0)