diff --git a/clients/drcachesim/tracer/output.cpp b/clients/drcachesim/tracer/output.cpp index 99472c41f02..ca1eac392f9 100644 --- a/clients/drcachesim/tracer/output.cpp +++ b/clients/drcachesim/tracer/output.cpp @@ -731,6 +731,7 @@ output_buffer(void *drcontext, per_thread_t *data, byte *buf_base, byte *buf_ptr byte *pipe_end = pipe_start; if (!op_offline.get_value()) { byte *post_header = buf_base + header_size; + byte *last_ok_to_split_ref = nullptr; // Pipe split headers are just the tid. header_size = instru->sizeof_entry(); for (byte *mem_ref = post_header; mem_ref < buf_ptr; @@ -752,8 +753,23 @@ output_buffer(void *drcontext, per_thread_t *data, byte *buf_base, byte *buf_ptr DR_ASSERT(is_ok_to_split_before( instru->get_entry_type(pipe_start + header_size), instru->get_entry_size(pipe_start + header_size))); - pipe_start = atomic_pipe_write(drcontext, pipe_start, pipe_end, - get_local_window(data)); + // Check if we went over the edge waiting for enough entries to + // write. If we did, we simply write till the last ok-to-split ref. + if (pipe_end - pipe_start > ipc_pipe.get_atomic_write_size()) { + // If the followin assert triggers, we found too many entries + // without an ok-to-split point. + DR_ASSERT(last_ok_to_split_ref != nullptr); + pipe_start = + atomic_pipe_write(drcontext, pipe_start, last_ok_to_split_ref, + get_local_window(data)); + last_ok_to_split_ref = pipe_end; + } else { + pipe_start = atomic_pipe_write(drcontext, pipe_start, pipe_end, + get_local_window(data)); + last_ok_to_split_ref = nullptr; + } + } else { + last_ok_to_split_ref = pipe_end; } } }