1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "perfetto/protozero/scattered_stream_writer.h" 18 19#include <algorithm> 20 21#include "perfetto/base/logging.h" 22 23namespace protozero { 24 25ScatteredStreamWriter::Delegate::~Delegate() {} 26 27ScatteredStreamWriter::ScatteredStreamWriter(Delegate* delegate) 28 : delegate_(delegate), 29 cur_range_({nullptr, nullptr}), 30 write_ptr_(nullptr) {} 31 32ScatteredStreamWriter::~ScatteredStreamWriter() {} 33 34void ScatteredStreamWriter::Reset(ContiguousMemoryRange range) { 35 cur_range_ = range; 36 write_ptr_ = range.begin; 37 PERFETTO_DCHECK(!write_ptr_ || write_ptr_ < cur_range_.end); 38} 39 40void ScatteredStreamWriter::Extend() { 41 Reset(delegate_->GetNewBuffer()); 42} 43 44void ScatteredStreamWriter::WriteBytesSlowPath(const uint8_t* src, 45 size_t size) { 46 size_t bytes_left = size; 47 while (bytes_left > 0) { 48 if (write_ptr_ >= cur_range_.end) 49 Extend(); 50 const size_t burst_size = std::min(bytes_available(), bytes_left); 51 WriteBytesUnsafe(src, burst_size); 52 bytes_left -= burst_size; 53 src += burst_size; 54 } 55} 56 57// TODO(primiano): perf optimization: I suspect that at the end this will always 58// be called with |size| == 4, in which case we might just hardcode it. 59uint8_t* ScatteredStreamWriter::ReserveBytes(size_t size) { 60 if (write_ptr_ + size > cur_range_.end) { 61 // Assume the reservations are always < Delegate::GetNewBuffer().size(), 62 // so that one single call to Extend() will definitely give enough headroom. 63 Extend(); 64 PERFETTO_DCHECK(write_ptr_ + size <= cur_range_.end); 65 } 66 uint8_t* begin = write_ptr_; 67 write_ptr_ += size; 68#if PERFETTO_DCHECK_IS_ON() 69 memset(begin, 0, size); 70#endif 71 return begin; 72} 73 74} // namespace protozero 75