blob: 91ed4694303a1b7853f97190492f35742ee8e2a5 [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
5#include "mojo/edk/system/handle_table.h"
6
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 {
14namespace edk {
15
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";
34 }
erikchen337e9da2017-06-09 17:49:4535 NOTREACHED();
erikchenea7ac1322017-06-03 02:40:5736 return "unknown";
37}
38
erikchenea7ac1322017-06-03 02:40:5739} // namespace
40
41HandleTable::HandleTable() {
erikchenea7ac1322017-06-03 02:40:5742}
43
44HandleTable::~HandleTable() {
erikchenea7ac1322017-06-03 02:40:5745}
46
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.
68 if (next_available_handle_ == MOJO_HANDLE_INVALID)
69 return false;
70
71 DCHECK_LE(dispatchers.size(), std::numeric_limits<uint32_t>::max());
72 // If this insertion would cause handle overflow, we're out of handles.
73 if (next_available_handle_ + dispatchers.size() < next_available_handle_)
74 return false;
75
76 for (size_t i = 0; i < dispatchers.size(); ++i) {
Ken Rockotfdf158da2017-06-12 20:45:2977 MojoHandle handle = MOJO_HANDLE_INVALID;
78 if (dispatchers[i].dispatcher) {
79 handle = next_available_handle_++;
80 auto result = handles_.insert(
81 std::make_pair(handle, Entry(dispatchers[i].dispatcher)));
82 DCHECK(result.second);
83 }
rockotce69a042016-01-26 19:23:2184 handles[i] = handle;
85 }
86
87 return true;
jam76bcf0c2015-10-02 21:01:2888}
89
rockotce69a042016-01-26 19:23:2190scoped_refptr<Dispatcher> HandleTable::GetDispatcher(MojoHandle handle) const {
91 auto it = handles_.find(handle);
92 if (it == handles_.end())
jam76bcf0c2015-10-02 21:01:2893 return nullptr;
rockotce69a042016-01-26 19:23:2194 return it->second.dispatcher;
jam76bcf0c2015-10-02 21:01:2895}
96
97MojoResult HandleTable::GetAndRemoveDispatcher(
98 MojoHandle handle,
99 scoped_refptr<Dispatcher>* dispatcher) {
rockotce69a042016-01-26 19:23:21100 auto it = handles_.find(handle);
101 if (it == handles_.end())
jam76bcf0c2015-10-02 21:01:28102 return MOJO_RESULT_INVALID_ARGUMENT;
103 if (it->second.busy)
104 return MOJO_RESULT_BUSY;
jam76bcf0c2015-10-02 21:01:28105
tzik1fb60dd2017-03-08 04:52:06106 *dispatcher = std::move(it->second.dispatcher);
rockotce69a042016-01-26 19:23:21107 handles_.erase(it);
jam76bcf0c2015-10-02 21:01:28108 return MOJO_RESULT_OK;
109}
110
rockotce69a042016-01-26 19:23:21111MojoResult HandleTable::BeginTransit(
jam76bcf0c2015-10-02 21:01:28112 const MojoHandle* handles,
Ken Rockot15b2b0b2017-06-12 20:36:05113 size_t num_handles,
rockotce69a042016-01-26 19:23:21114 std::vector<Dispatcher::DispatcherInTransit>* dispatchers) {
Ken Rockot766e7662017-08-10 05:37:15115 dispatchers->reserve(dispatchers->size() + num_handles);
rockotce69a042016-01-26 19:23:21116 for (size_t i = 0; i < num_handles; ++i) {
117 auto it = handles_.find(handles[i]);
118 if (it == handles_.end())
119 return MOJO_RESULT_INVALID_ARGUMENT;
120 if (it->second.busy)
121 return MOJO_RESULT_BUSY;
jam76bcf0c2015-10-02 21:01:28122
rockotce69a042016-01-26 19:23:21123 Dispatcher::DispatcherInTransit d;
124 d.local_handle = handles[i];
125 d.dispatcher = it->second.dispatcher;
126 if (!d.dispatcher->BeginTransit())
127 return MOJO_RESULT_BUSY;
128 it->second.busy = true;
129 dispatchers->push_back(d);
jam76bcf0c2015-10-02 21:01:28130 }
jam76bcf0c2015-10-02 21:01:28131 return MOJO_RESULT_OK;
132}
133
rockotce69a042016-01-26 19:23:21134void HandleTable::CompleteTransitAndClose(
135 const std::vector<Dispatcher::DispatcherInTransit>& dispatchers) {
136 for (const auto& dispatcher : dispatchers) {
137 auto it = handles_.find(dispatcher.local_handle);
138 DCHECK(it != handles_.end() && it->second.busy);
139 handles_.erase(it);
140 dispatcher.dispatcher->CompleteTransitAndClose();
jam76bcf0c2015-10-02 21:01:28141 }
142}
143
rockotce69a042016-01-26 19:23:21144void HandleTable::CancelTransit(
145 const std::vector<Dispatcher::DispatcherInTransit>& dispatchers) {
146 for (const auto& dispatcher : dispatchers) {
147 auto it = handles_.find(dispatcher.local_handle);
148 DCHECK(it != handles_.end() && it->second.busy);
jam76bcf0c2015-10-02 21:01:28149 it->second.busy = false;
rockotce69a042016-01-26 19:23:21150 dispatcher.dispatcher->CancelTransit();
jam76bcf0c2015-10-02 21:01:28151 }
152}
153
rockotce69a042016-01-26 19:23:21154void HandleTable::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) {
155 handles->clear();
156 for (const auto& entry : handles_)
157 handles->push_back(entry.first);
158}
159
erikchenea7ac1322017-06-03 02:40:57160// MemoryDumpProvider implementation.
161bool HandleTable::OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
162 base::trace_event::ProcessMemoryDump* pmd) {
163 // Create entries for all relevant dispatcher types to ensure they are present
164 // in the final dump.
165 std::map<Dispatcher::Type, int> handle_count;
166 handle_count[Dispatcher::Type::MESSAGE_PIPE];
167 handle_count[Dispatcher::Type::DATA_PIPE_PRODUCER];
168 handle_count[Dispatcher::Type::DATA_PIPE_CONSUMER];
169 handle_count[Dispatcher::Type::SHARED_BUFFER];
170 handle_count[Dispatcher::Type::WATCHER];
171 handle_count[Dispatcher::Type::PLATFORM_HANDLE];
172
173 // Count the number of each dispatcher type.
174 {
175 base::AutoLock lock(GetLock());
176 for (const auto& entry : handles_) {
177 ++handle_count[entry.second.dispatcher->GetType()];
178 }
179 }
180
erikchenea7ac1322017-06-03 02:40:57181 for (const auto& entry : handle_count) {
erikchenbf2cf912017-06-06 23:54:41182 base::trace_event::MemoryAllocatorDump* inner_dump =
183 pmd->CreateAllocatorDump(std::string("mojo/") +
184 GetNameForDispatcherType(entry.first));
185 inner_dump->AddScalar(
186 base::trace_event::MemoryAllocatorDump::kNameObjectCount,
187 base::trace_event::MemoryAllocatorDump::kUnitsObjects, entry.second);
erikchenea7ac1322017-06-03 02:40:57188 }
189
190 return true;
191}
192
rockotce69a042016-01-26 19:23:21193HandleTable::Entry::Entry() {}
194
195HandleTable::Entry::Entry(scoped_refptr<Dispatcher> dispatcher)
tzik1fb60dd2017-03-08 04:52:06196 : dispatcher(std::move(dispatcher)) {}
rockotce69a042016-01-26 19:23:21197
vmpstr11ea3852016-02-29 20:33:57198HandleTable::Entry::Entry(const Entry& other) = default;
199
rockotce69a042016-01-26 19:23:21200HandleTable::Entry::~Entry() {}
201
jam76bcf0c2015-10-02 21:01:28202} // namespace edk
203} // namespace mojo