1*6dbdd20aSAndroid Build Coastguard Worker /* 2*6dbdd20aSAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project 3*6dbdd20aSAndroid Build Coastguard Worker * 4*6dbdd20aSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*6dbdd20aSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*6dbdd20aSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*6dbdd20aSAndroid Build Coastguard Worker * 8*6dbdd20aSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*6dbdd20aSAndroid Build Coastguard Worker * 10*6dbdd20aSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*6dbdd20aSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*6dbdd20aSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*6dbdd20aSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*6dbdd20aSAndroid Build Coastguard Worker * limitations under the License. 15*6dbdd20aSAndroid Build Coastguard Worker */ 16*6dbdd20aSAndroid Build Coastguard Worker 17*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/protozero/message_arena.h" 18*6dbdd20aSAndroid Build Coastguard Worker 19*6dbdd20aSAndroid Build Coastguard Worker #include <atomic> 20*6dbdd20aSAndroid Build Coastguard Worker #include <type_traits> 21*6dbdd20aSAndroid Build Coastguard Worker 22*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/base/logging.h" 23*6dbdd20aSAndroid Build Coastguard Worker #include "perfetto/protozero/message_handle.h" 24*6dbdd20aSAndroid Build Coastguard Worker 25*6dbdd20aSAndroid Build Coastguard Worker namespace protozero { 26*6dbdd20aSAndroid Build Coastguard Worker MessageArena()27*6dbdd20aSAndroid Build Coastguard WorkerMessageArena::MessageArena() { 28*6dbdd20aSAndroid Build Coastguard Worker // The code below assumes that there is always at least one block. 29*6dbdd20aSAndroid Build Coastguard Worker blocks_.emplace_front(); 30*6dbdd20aSAndroid Build Coastguard Worker static_assert( 31*6dbdd20aSAndroid Build Coastguard Worker std::alignment_of<decltype(blocks_.front().storage[0])>::value >= 32*6dbdd20aSAndroid Build Coastguard Worker alignof(Message), 33*6dbdd20aSAndroid Build Coastguard Worker "MessageArea's storage is not properly aligned"); 34*6dbdd20aSAndroid Build Coastguard Worker } 35*6dbdd20aSAndroid Build Coastguard Worker 36*6dbdd20aSAndroid Build Coastguard Worker MessageArena::~MessageArena() = default; 37*6dbdd20aSAndroid Build Coastguard Worker NewMessage()38*6dbdd20aSAndroid Build Coastguard WorkerMessage* MessageArena::NewMessage() { 39*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DCHECK(!blocks_.empty()); // Should never become empty. 40*6dbdd20aSAndroid Build Coastguard Worker 41*6dbdd20aSAndroid Build Coastguard Worker Block* block = &blocks_.front(); 42*6dbdd20aSAndroid Build Coastguard Worker if (PERFETTO_UNLIKELY(block->entries >= Block::kCapacity)) { 43*6dbdd20aSAndroid Build Coastguard Worker blocks_.emplace_front(); 44*6dbdd20aSAndroid Build Coastguard Worker block = &blocks_.front(); 45*6dbdd20aSAndroid Build Coastguard Worker } 46*6dbdd20aSAndroid Build Coastguard Worker const auto idx = block->entries++; 47*6dbdd20aSAndroid Build Coastguard Worker void* storage = &block->storage[idx]; 48*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ASAN_UNPOISON(storage, sizeof(Message)); 49*6dbdd20aSAndroid Build Coastguard Worker return new (storage) Message(); 50*6dbdd20aSAndroid Build Coastguard Worker } 51*6dbdd20aSAndroid Build Coastguard Worker DeleteLastMessageInternal()52*6dbdd20aSAndroid Build Coastguard Workervoid MessageArena::DeleteLastMessageInternal() { 53*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DCHECK(!blocks_.empty()); // Should never be empty, see below. 54*6dbdd20aSAndroid Build Coastguard Worker Block* block = &blocks_.front(); 55*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_DCHECK(block->entries > 0); 56*6dbdd20aSAndroid Build Coastguard Worker 57*6dbdd20aSAndroid Build Coastguard Worker // This is the reason why there is no ~Message() call here. 58*6dbdd20aSAndroid Build Coastguard Worker // MessageArea::Reset() (see header) also relies on dtor being trivial. 59*6dbdd20aSAndroid Build Coastguard Worker static_assert(std::is_trivially_destructible<Message>::value, 60*6dbdd20aSAndroid Build Coastguard Worker "Message must be trivially destructible"); 61*6dbdd20aSAndroid Build Coastguard Worker 62*6dbdd20aSAndroid Build Coastguard Worker --block->entries; 63*6dbdd20aSAndroid Build Coastguard Worker PERFETTO_ASAN_POISON(&block->storage[block->entries], sizeof(Message)); 64*6dbdd20aSAndroid Build Coastguard Worker 65*6dbdd20aSAndroid Build Coastguard Worker // Don't remove the first block to avoid malloc/free calls when the root 66*6dbdd20aSAndroid Build Coastguard Worker // message is reset. Hitting the allocator all the times is a waste of time. 67*6dbdd20aSAndroid Build Coastguard Worker if (block->entries == 0 && std::next(blocks_.cbegin()) != blocks_.cend()) { 68*6dbdd20aSAndroid Build Coastguard Worker blocks_.pop_front(); 69*6dbdd20aSAndroid Build Coastguard Worker } 70*6dbdd20aSAndroid Build Coastguard Worker } 71*6dbdd20aSAndroid Build Coastguard Worker 72*6dbdd20aSAndroid Build Coastguard Worker } // namespace protozero 73