148f512ceSopenharmony_ci/* 248f512ceSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 448f512ceSopenharmony_ci * you may not use this file except in compliance with the License. 548f512ceSopenharmony_ci * You may obtain a copy of the License at 648f512ceSopenharmony_ci * 748f512ceSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 848f512ceSopenharmony_ci * 948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and 1348f512ceSopenharmony_ci * limitations under the License. 1448f512ceSopenharmony_ci */ 1548f512ceSopenharmony_ci#define HILOG_TAG "RingBuffer" 1648f512ceSopenharmony_ci 1748f512ceSopenharmony_ci#include <linux/perf_event.h> 1848f512ceSopenharmony_ci#include "ring_buffer.h" 1948f512ceSopenharmony_ci#include "perf_event_record.h" 2048f512ceSopenharmony_ci#if defined(is_ohos) && is_ohos 2148f512ceSopenharmony_ci#include "hiperf_hilog.h" 2248f512ceSopenharmony_ci#endif 2348f512ceSopenharmony_ci 2448f512ceSopenharmony_cinamespace OHOS { 2548f512ceSopenharmony_cinamespace Developtools { 2648f512ceSopenharmony_cinamespace HiPerf { 2748f512ceSopenharmony_ciRingBuffer::RingBuffer(size_t size) : size_(size) 2848f512ceSopenharmony_ci{ 2948f512ceSopenharmony_ci if (size > 0) { 3048f512ceSopenharmony_ci buf_ = std::make_unique<uint8_t[]>(size); 3148f512ceSopenharmony_ci } 3248f512ceSopenharmony_ci} 3348f512ceSopenharmony_ci 3448f512ceSopenharmony_ciRingBuffer::~RingBuffer() {} 3548f512ceSopenharmony_ci 3648f512ceSopenharmony_ci// get size of the writable space 3748f512ceSopenharmony_cisize_t RingBuffer::GetFreeSize() const 3848f512ceSopenharmony_ci{ 3948f512ceSopenharmony_ci return size_ - (head_.load(std::memory_order_relaxed) - tail_.load(std::memory_order_relaxed)); 4048f512ceSopenharmony_ci} 4148f512ceSopenharmony_ci 4248f512ceSopenharmony_ciuint8_t *RingBuffer::AllocForWrite(size_t writeSize) 4348f512ceSopenharmony_ci{ 4448f512ceSopenharmony_ci if (buf_ == nullptr || buf_.get() == nullptr) { 4548f512ceSopenharmony_ci return nullptr; 4648f512ceSopenharmony_ci } 4748f512ceSopenharmony_ci size_t writeHead = head_.load(std::memory_order_relaxed); 4848f512ceSopenharmony_ci size_t readHead = tail_.load(std::memory_order_acquire); 4948f512ceSopenharmony_ci if (size_ == 0) { 5048f512ceSopenharmony_ci return nullptr; 5148f512ceSopenharmony_ci } 5248f512ceSopenharmony_ci size_t writePos = writeHead % size_; 5348f512ceSopenharmony_ci size_t readPos = readHead % size_; 5448f512ceSopenharmony_ci writeSize_ = writeSize; 5548f512ceSopenharmony_ci if (writePos < readPos) { 5648f512ceSopenharmony_ci // |---writePos<---writeSize--->readPos---| 5748f512ceSopenharmony_ci if (writePos + writeSize > readPos) { 5848f512ceSopenharmony_ci return nullptr; 5948f512ceSopenharmony_ci } 6048f512ceSopenharmony_ci } else if (writePos == readPos and writeHead != readHead) { 6148f512ceSopenharmony_ci // writePos catch up with readPos, but buffer is full 6248f512ceSopenharmony_ci return nullptr; 6348f512ceSopenharmony_ci } else { 6448f512ceSopenharmony_ci // two cases: 1, writePos catch up with readPos, but buffer is empty 6548f512ceSopenharmony_ci // 2, |---readPos---writePos<---writeSize--->| 6648f512ceSopenharmony_ci if (writePos + writeSize > size_) { 6748f512ceSopenharmony_ci // no enough space at the end 6848f512ceSopenharmony_ci if (readPos < writeSize) { 6948f512ceSopenharmony_ci return nullptr; 7048f512ceSopenharmony_ci } 7148f512ceSopenharmony_ci // wrap to the start, set mark byte 7248f512ceSopenharmony_ci buf_.get()[writePos] = MARGIN_BYTE; 7348f512ceSopenharmony_ci writeSize_ += (size_ - writePos); 7448f512ceSopenharmony_ci writePos = 0; 7548f512ceSopenharmony_ci } 7648f512ceSopenharmony_ci } 7748f512ceSopenharmony_ci 7848f512ceSopenharmony_ci return buf_.get() + writePos; 7948f512ceSopenharmony_ci} 8048f512ceSopenharmony_ci 8148f512ceSopenharmony_civoid RingBuffer::EndWrite() 8248f512ceSopenharmony_ci{ 8348f512ceSopenharmony_ci size_t head = head_.load(std::memory_order_relaxed); 8448f512ceSopenharmony_ci head += writeSize_; 8548f512ceSopenharmony_ci head_.store(head, std::memory_order_release); 8648f512ceSopenharmony_ci} 8748f512ceSopenharmony_ci 8848f512ceSopenharmony_ciuint8_t *RingBuffer::GetReadData() 8948f512ceSopenharmony_ci{ 9048f512ceSopenharmony_ci CHECK_TRUE(buf_ == nullptr || buf_.get() == nullptr, nullptr, 0, ""); 9148f512ceSopenharmony_ci size_t writeHead = head_.load(std::memory_order_acquire); 9248f512ceSopenharmony_ci size_t readHead = tail_.load(std::memory_order_relaxed); 9348f512ceSopenharmony_ci if (writeHead == readHead) { 9448f512ceSopenharmony_ci return nullptr; 9548f512ceSopenharmony_ci } 9648f512ceSopenharmony_ci 9748f512ceSopenharmony_ci readSize_ = 0; 9848f512ceSopenharmony_ci if (size_ == 0) { 9948f512ceSopenharmony_ci return nullptr; 10048f512ceSopenharmony_ci } 10148f512ceSopenharmony_ci size_t writePos = writeHead % size_; 10248f512ceSopenharmony_ci size_t readPos = readHead % size_; 10348f512ceSopenharmony_ci if (writePos <= readPos) { 10448f512ceSopenharmony_ci // |<---data2--->writePos---readPos<---data1--->| 10548f512ceSopenharmony_ci if (buf_.get()[readPos] == MARGIN_BYTE) { 10648f512ceSopenharmony_ci CHECK_TRUE(writePos == 0, nullptr, 0, ""); 10748f512ceSopenharmony_ci readSize_ = (size_ - readPos); 10848f512ceSopenharmony_ci readPos = 0; 10948f512ceSopenharmony_ci } 11048f512ceSopenharmony_ci } 11148f512ceSopenharmony_ci // else |---readPos<---data--->writePos---| 11248f512ceSopenharmony_ci perf_event_header *header = reinterpret_cast<perf_event_header *>(buf_.get() + readPos); 11348f512ceSopenharmony_ci CHECK_TRUE(header == nullptr, nullptr, 0, ""); 11448f512ceSopenharmony_ci 11548f512ceSopenharmony_ci if (header->type == PERF_RECORD_AUXTRACE) { 11648f512ceSopenharmony_ci struct PerfRecordAuxtraceData *auxtrace = reinterpret_cast<struct PerfRecordAuxtraceData *>(header + 1); 11748f512ceSopenharmony_ci readSize_ += header->size + auxtrace->size; 11848f512ceSopenharmony_ci } else { 11948f512ceSopenharmony_ci readSize_ += header->size; 12048f512ceSopenharmony_ci } 12148f512ceSopenharmony_ci return buf_.get() + readPos; 12248f512ceSopenharmony_ci} 12348f512ceSopenharmony_ci 12448f512ceSopenharmony_civoid RingBuffer::EndRead() 12548f512ceSopenharmony_ci{ 12648f512ceSopenharmony_ci size_t tail = tail_.load(std::memory_order_relaxed); 12748f512ceSopenharmony_ci tail += readSize_; 12848f512ceSopenharmony_ci tail_.store(tail, std::memory_order_release); 12948f512ceSopenharmony_ci} 13048f512ceSopenharmony_ci} // namespace HiPerf 13148f512ceSopenharmony_ci} // namespace Developtools 13248f512ceSopenharmony_ci} // namespace OHOS 133