xref: /aosp_15_r20/external/libchrome/mojo/core/handle_table.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1 // 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/core/handle_table.h"
6 
7 #include <stdint.h>
8 
9 #include <limits>
10 
11 // #include "base/trace_event/memory_dump_manager.h"
12 
13 namespace mojo {
14 namespace core {
15 
16 namespace {
17 
18 // const 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 //     case Dispatcher::Type::INVITATION:
35 //       return "invitation";
36 //   }
37 //   NOTREACHED();
38 //   return "unknown";
39 // }
40 
41 }  // namespace
42 
HandleTable()43 HandleTable::HandleTable() {}
44 
~HandleTable()45 HandleTable::~HandleTable() {}
46 
GetLock()47 base::Lock& HandleTable::GetLock() {
48   return lock_;
49 }
50 
AddDispatcher(scoped_refptr<Dispatcher> dispatcher)51 MojoHandle 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_++;
57   auto result =
58       handles_.insert(std::make_pair(handle, Entry(std::move(dispatcher))));
59   DCHECK(result.second);
60 
61   return handle;
62 }
63 
AddDispatchersFromTransit(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers,MojoHandle * handles)64 bool 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 
72   // MOJO_HANDLE_INVALID is zero.
73   DCHECK_GE(next_available_handle_, 1u);
74 
75   // If this insertion would cause handle overflow, we're out of handles.
76   const uint32_t num_handles_available =
77       std::numeric_limits<uint32_t>::max() - next_available_handle_ + 1;
78   if (num_handles_available < dispatchers.size()) {
79     return false;
80   }
81 
82   for (size_t i = 0; i < dispatchers.size(); ++i) {
83     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     }
90     handles[i] = handle;
91   }
92 
93   return true;
94 }
95 
GetDispatcher(MojoHandle handle) const96 scoped_refptr<Dispatcher> HandleTable::GetDispatcher(MojoHandle handle) const {
97   auto it = handles_.find(handle);
98   if (it == handles_.end())
99     return nullptr;
100   return it->second.dispatcher;
101 }
102 
GetAndRemoveDispatcher(MojoHandle handle,scoped_refptr<Dispatcher> * dispatcher)103 MojoResult HandleTable::GetAndRemoveDispatcher(
104     MojoHandle handle,
105     scoped_refptr<Dispatcher>* dispatcher) {
106   auto it = handles_.find(handle);
107   if (it == handles_.end())
108     return MOJO_RESULT_INVALID_ARGUMENT;
109   if (it->second.busy)
110     return MOJO_RESULT_BUSY;
111 
112   *dispatcher = std::move(it->second.dispatcher);
113   handles_.erase(it);
114   return MOJO_RESULT_OK;
115 }
116 
BeginTransit(const MojoHandle * handles,size_t num_handles,std::vector<Dispatcher::DispatcherInTransit> * dispatchers)117 MojoResult HandleTable::BeginTransit(
118     const MojoHandle* handles,
119     size_t num_handles,
120     std::vector<Dispatcher::DispatcherInTransit>* dispatchers) {
121   dispatchers->reserve(dispatchers->size() + num_handles);
122   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;
128 
129     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);
136   }
137   return MOJO_RESULT_OK;
138 }
139 
CompleteTransitAndClose(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers)140 void 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();
147   }
148 }
149 
CancelTransit(const std::vector<Dispatcher::DispatcherInTransit> & dispatchers)150 void 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);
155     it->second.busy = false;
156     dispatcher.dispatcher->CancelTransit();
157   }
158 }
159 
GetActiveHandlesForTest(std::vector<MojoHandle> * handles)160 void HandleTable::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) {
161   handles->clear();
162   for (const auto& entry : handles_)
163     handles->push_back(entry.first);
164 }
165 
166 // MemoryDumpProvider implementation.
167 // bool 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];
178 //   handle_count[Dispatcher::Type::INVITATION];
179 
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 
188 //   for (const auto& entry : handle_count) {
189 //     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);
195 //   }
196 
197 //   return true;
198 // }
199 
Entry()200 HandleTable::Entry::Entry() {}
201 
Entry(scoped_refptr<Dispatcher> dispatcher)202 HandleTable::Entry::Entry(scoped_refptr<Dispatcher> dispatcher)
203     : dispatcher(std::move(dispatcher)) {}
204 
205 HandleTable::Entry::Entry(const Entry& other) = default;
206 
~Entry()207 HandleTable::Entry::~Entry() {}
208 
209 }  // namespace core
210 }  // namespace mojo
211