blob: 1befb91c6438dac342c8301101a13ceed644b707 [file] [log] [blame]
jam76bcf0c2015-10-02 21:01:281// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Ken Rockotdba46db2018-07-04 18:41:045#include "mojo/core/handle_table.h"
jam76bcf0c2015-10-02 21:01:286
Avi Drissman2e88ac372015-12-21 18:14:577#include <stdint.h>
8
jam76bcf0c2015-10-02 21:01:289#include <limits>
10
erikchenea7ac1322017-06-03 02:40:5711#include "base/trace_event/memory_dump_manager.h"
12
jam76bcf0c2015-10-02 21:01:2813namespace mojo {
Ken Rockotdba46db2018-07-04 18:41:0414namespace core {
jam76bcf0c2015-10-02 21:01:2815
erikchenea7ac1322017-06-03 02:40:5716namespace {
rockotce69a042016-01-26 19:23:2117
erikchenea7ac1322017-06-03 02:40:5718const char* GetNameForDispatcherType(Dispatcher::Type type) {
19 switch (type) {
20 case Dispatcher::Type::UNKNOWN:
21 return "unknown";
22 case Dispatcher::Type::MESSAGE_PIPE:
23 return "message_pipe";
24 case Dispatcher::Type::DATA_PIPE_PRODUCER:
25 return "data_pipe_producer";
26 case Dispatcher::Type::DATA_PIPE_CONSUMER:
27 return "data_pipe_consumer";
28 case Dispatcher::Type::SHARED_BUFFER:
29 return "shared_buffer";
30 case Dispatcher::Type::WATCHER:
31 return "watcher";
32 case Dispatcher::Type::PLATFORM_HANDLE:
33 return "platform_handle";
Ken Rockotf86cdb8b2018-05-19 23:35:0134 case Dispatcher::Type::INVITATION:
35 return "invitation";
erikchenea7ac1322017-06-03 02:40:5736 }
erikchen337e9da2017-06-09 17:49:4537 NOTREACHED();
erikchenea7ac1322017-06-03 02:40:5738 return "unknown";
39}
40
erikchenea7ac1322017-06-03 02:40:5741} // namespace
42
Anand K Mistry48d93df2020-06-18 00:04:2243HandleTable::HandleTable() = default;
erikchenea7ac1322017-06-03 02:40:5744
Anand K Mistry48d93df2020-06-18 00:04:2245HandleTable::~HandleTable() = default;
erikchenea7ac1322017-06-03 02:40:5746
47base::Lock& HandleTable::GetLock() {
48 return lock_;
49}
rockotce69a042016-01-26 19:23:2150
51MojoHandle HandleTable::AddDispatcher(scoped_refptr<Dispatcher> dispatcher) {
52 // Oops, we're out of handles.
53 if (next_available_handle_ == MOJO_HANDLE_INVALID)
54 return MOJO_HANDLE_INVALID;
55
56 MojoHandle handle = next_available_handle_++;
tzik1fb60dd2017-03-08 04:52:0657 auto result =
58 handles_.insert(std::make_pair(handle, Entry(std::move(dispatcher))));
rockotce69a042016-01-26 19:23:2159 DCHECK(result.second);
60
61 return handle;
jam76bcf0c2015-10-02 21:01:2862}
63
rockotce69a042016-01-26 19:23:2164bool HandleTable::AddDispatchersFromTransit(
65 const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
66 MojoHandle* handles) {
67 // Oops, we're out of handles.
Ken Rockot76eca902022-01-25 12:16:1468 if (next_available_handle_ == MOJO_HANDLE_INVALID) {
rockotce69a042016-01-26 19:23:2169 return false;
Ken Rockot76eca902022-01-25 12:16:1470 }
rockotce69a042016-01-26 19:23:2171
Ken Rockot76eca902022-01-25 12:16:1472 // MOJO_HANDLE_INVALID is zero.
73 DCHECK_GE(next_available_handle_, 1u);
74
rockotce69a042016-01-26 19:23:2175 // If this insertion would cause handle overflow, we're out of handles.
Ken Rockot8e8c8c82022-03-04 18:21:3876 const uint64_t num_handles_available =
77 std::numeric_limits<uint64_t>::max() - next_available_handle_ + 1;
Ken Rockot76eca902022-01-25 12:16:1478 if (num_handles_available < dispatchers.size()) {
rockotce69a042016-01-26 19:23:2179 return false;
Ken Rockot76eca902022-01-25 12:16:1480 }
rockotce69a042016-01-26 19:23:2181
82 for (size_t i = 0; i < dispatchers.size(); ++i) {
Ken Rockotfdf158da2017-06-12 20:45:2983 MojoHandle handle = MOJO_HANDLE_INVALID;
84 if (dispatchers[i].dispatcher) {
85 handle = next_available_handle_++;
86 auto result = handles_.insert(
87 std::make_pair(handle, Entry(dispatchers[i].dispatcher)));
88 DCHECK(result.second);
89 }
rockotce69a042016-01-26 19:23:2190 handles[i] = handle;
91 }
92
93 return true;
jam76bcf0c2015-10-02 21:01:2894}
95
rockotce69a042016-01-26 19:23:2196scoped_refptr<Dispatcher> HandleTable::GetDispatcher(MojoHandle handle) const {
97 auto it = handles_.find(handle);
98 if (it == handles_.end())
jam76bcf0c2015-10-02 21:01:2899 return nullptr;
rockotce69a042016-01-26 19:23:21100 return it->second.dispatcher;
jam76bcf0c2015-10-02 21:01:28101}
102
103MojoResult HandleTable::GetAndRemoveDispatcher(
104 MojoHandle handle,
105 scoped_refptr<Dispatcher>* dispatcher) {
rockotce69a042016-01-26 19:23:21106 auto it = handles_.find(handle);
107 if (it == handles_.end())
jam76bcf0c2015-10-02 21:01:28108 return MOJO_RESULT_INVALID_ARGUMENT;
109 if (it->second.busy)
110 return MOJO_RESULT_BUSY;
jam76bcf0c2015-10-02 21:01:28111
Ken Rockot7d291fcc2019-04-17 16:25:02112 *dispatcher = std::move(it->second.dispatcher);
rockotce69a042016-01-26 19:23:21113 handles_.erase(it);
jam76bcf0c2015-10-02 21:01:28114 return MOJO_RESULT_OK;
115}
116
rockotce69a042016-01-26 19:23:21117MojoResult HandleTable::BeginTransit(
jam76bcf0c2015-10-02 21:01:28118 const MojoHandle* handles,
Ken Rockot15b2b0b2017-06-12 20:36:05119 size_t num_handles,
rockotce69a042016-01-26 19:23:21120 std::vector<Dispatcher::DispatcherInTransit>* dispatchers) {
Ken Rockot766e7662017-08-10 05:37:15121 dispatchers->reserve(dispatchers->size() + num_handles);
rockotce69a042016-01-26 19:23:21122 for (size_t i = 0; i < num_handles; ++i) {
123 auto it = handles_.find(handles[i]);
124 if (it == handles_.end())
125 return MOJO_RESULT_INVALID_ARGUMENT;
126 if (it->second.busy)
127 return MOJO_RESULT_BUSY;
jam76bcf0c2015-10-02 21:01:28128
rockotce69a042016-01-26 19:23:21129 Dispatcher::DispatcherInTransit d;
130 d.local_handle = handles[i];
131 d.dispatcher = it->second.dispatcher;
132 if (!d.dispatcher->BeginTransit())
133 return MOJO_RESULT_BUSY;
134 it->second.busy = true;
135 dispatchers->push_back(d);
jam76bcf0c2015-10-02 21:01:28136 }
jam76bcf0c2015-10-02 21:01:28137 return MOJO_RESULT_OK;
138}
139
rockotce69a042016-01-26 19:23:21140void HandleTable::CompleteTransitAndClose(
141 const std::vector<Dispatcher::DispatcherInTransit>& dispatchers) {
142 for (const auto& dispatcher : dispatchers) {
143 auto it = handles_.find(dispatcher.local_handle);
144 DCHECK(it != handles_.end() && it->second.busy);
145 handles_.erase(it);
146 dispatcher.dispatcher->CompleteTransitAndClose();
jam76bcf0c2015-10-02 21:01:28147 }
148}
149
rockotce69a042016-01-26 19:23:21150void HandleTable::CancelTransit(
151 const std::vector<Dispatcher::DispatcherInTransit>& dispatchers) {
152 for (const auto& dispatcher : dispatchers) {
153 auto it = handles_.find(dispatcher.local_handle);
154 DCHECK(it != handles_.end() && it->second.busy);
jam76bcf0c2015-10-02 21:01:28155 it->second.busy = false;
rockotce69a042016-01-26 19:23:21156 dispatcher.dispatcher->CancelTransit();
jam76bcf0c2015-10-02 21:01:28157 }
158}
159
rockotce69a042016-01-26 19:23:21160void HandleTable::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) {
161 handles->clear();
162 for (const auto& entry : handles_)
163 handles->push_back(entry.first);
164}
165
erikchenea7ac1322017-06-03 02:40:57166// MemoryDumpProvider implementation.
167bool HandleTable::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
168 base::trace_event::ProcessMemoryDump* pmd) {
169 // Create entries for all relevant dispatcher types to ensure they are present
170 // in the final dump.
171 std::map<Dispatcher::Type, int> handle_count;
172 handle_count[Dispatcher::Type::MESSAGE_PIPE];
173 handle_count[Dispatcher::Type::DATA_PIPE_PRODUCER];
174 handle_count[Dispatcher::Type::DATA_PIPE_CONSUMER];
175 handle_count[Dispatcher::Type::SHARED_BUFFER];
176 handle_count[Dispatcher::Type::WATCHER];
177 handle_count[Dispatcher::Type::PLATFORM_HANDLE];
Ken Rockot026afc32018-06-04 19:19:18178 handle_count[Dispatcher::Type::INVITATION];
erikchenea7ac1322017-06-03 02:40:57179
180 // Count the number of each dispatcher type.
181 {
182 base::AutoLock lock(GetLock());
183 for (const auto& entry : handles_) {
184 ++handle_count[entry.second.dispatcher->GetType()];
185 }
186 }
187
erikchenea7ac1322017-06-03 02:40:57188 for (const auto& entry : handle_count) {
erikchenbf2cf912017-06-06 23:54:41189 base::trace_event::MemoryAllocatorDump* inner_dump =
190 pmd->CreateAllocatorDump(std::string("mojo/") +
191 GetNameForDispatcherType(entry.first));
192 inner_dump->AddScalar(
193 base::trace_event::MemoryAllocatorDump::kNameObjectCount,
194 base::trace_event::MemoryAllocatorDump::kUnitsObjects, entry.second);
erikchenea7ac1322017-06-03 02:40:57195 }
196
197 return true;
198}
199
Anand K Mistry48d93df2020-06-18 00:04:22200HandleTable::Entry::Entry() = default;
rockotce69a042016-01-26 19:23:21201
202HandleTable::Entry::Entry(scoped_refptr<Dispatcher> dispatcher)
tzik1fb60dd2017-03-08 04:52:06203 : dispatcher(std::move(dispatcher)) {}
rockotce69a042016-01-26 19:23:21204
vmpstr11ea3852016-02-29 20:33:57205HandleTable::Entry::Entry(const Entry& other) = default;
206
Anand K Mistry48d93df2020-06-18 00:04:22207HandleTable::Entry::~Entry() = default;
rockotce69a042016-01-26 19:23:21208
Ken Rockotdba46db2018-07-04 18:41:04209} // namespace core
jam76bcf0c2015-10-02 21:01:28210} // namespace mojo