/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SRC_TRACING_CORE_SHARED_MEMORY_ARBITER_IMPL_H_ #define SRC_TRACING_CORE_SHARED_MEMORY_ARBITER_IMPL_H_ #include <stdint.h> #include <functional> #include <map> #include <memory> #include <mutex> #include <vector> #include "perfetto/ext/base/weak_ptr.h" #include "perfetto/ext/tracing/core/basic_types.h" #include "perfetto/ext/tracing/core/shared_memory_abi.h" #include "perfetto/ext/tracing/core/shared_memory_arbiter.h" #include "perfetto/tracing/core/forward_decls.h" #include "src/tracing/core/id_allocator.h" namespace perfetto { class PatchList; class Patch; class TraceWriter; class TraceWriterImpl; namespace base { class TaskRunner; } // namespace base // This class handles the shared memory buffer on the producer side. It is used // to obtain thread-local chunks and to partition pages from several threads. // There is one arbiter instance per Producer. // This class is thread-safe and uses locks to do so. Data sources are supposed // to interact with this sporadically, only when they run out of space on their // current thread-local chunk. // // The arbiter can become "unbound" as a consequence of: // (a) being created without an endpoint // (b) CreateStartupTraceWriter calls after creation (whether created with or // without endpoint). // // Entering the unbound state is only supported if all trace writers are created // in kDrop mode. In the unbound state, the arbiter buffers commit messages // until all trace writers are bound to a target buffer. // // The following state transitions are possible: // // CreateInstance() // | // | CreateUnboundInstance() // | | // | | // | V // | [ !fully_bound_, !endpoint_, 0 unbound buffer reservations ] // | | | // | | | CreateStartupTraceWriter(buf) // | | | buffer reservations += buf // | | | // | | | ---- // | | | | | CreateStartupTraceWriter(buf) // | | | | | buffer reservations += buf // | | V | V // | | [ !fully_bound_, !endpoint_, >=1 unbound buffer reservations ] // | | | // | | BindToProducerEndpoint() | // | | | // | | BindToProducerEndpoint() | // | | V // | | [ !fully_bound_, endpoint_, >=1 unbound buffer reservations ] // | | A | A | A // | | | | | | | // | | | ---- | | // | | | CreateStartupTraceWriter(buf) | | // | | | buffer reservations += buf | | // | | | | | // | | | CreateStartupTraceWriter(buf) | | // | | | where buf is not yet bound | | // | | | buffer reservations += buf | | (yes) // | | | | | // | | | BindStartupTargetBuffer(buf, id) |----- // | | | buffer reservations -= buf | reservations > 0? // | | | | // | | | | (no) // | V | V // --> [ fully_bound_, endpoint_, 0 unbound buffer reservations ] // | A // | | CreateStartupTraceWriter(buf) // | | where buf is already bound // ---- class SharedMemoryArbiterImpl : public SharedMemoryArbiter { … }; } // namespace perfetto #endif // SRC_TRACING_CORE_SHARED_MEMORY_ARBITER_IMPL_H_