Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
port.cc
Go to the documentation of this file.
1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/port.h"
6
7#include <utility>
8
9#include "include/dart_api.h"
10#include "platform/utils.h"
11#include "vm/dart_api_impl.h"
12#include "vm/dart_entry.h"
13#include "vm/isolate.h"
14#include "vm/lockers.h"
15#include "vm/message_handler.h"
16#include "vm/os_thread.h"
17
18namespace dart {
19
20Mutex* PortMap::mutex_ = nullptr;
21PortSet<PortMap::Entry>* PortMap::ports_ = nullptr;
22Random* PortMap::prng_ = nullptr;
23
24Dart_Port PortMap::AllocatePort() {
26
28
29 // Keep getting new values while we have an illegal port number or the port
30 // number is already in use.
31 do {
32 // Ensure port ids are never valid object pointers so that reinterpreting
33 // an object pointer as a port id never produces a used port id.
34 const Dart_Port kMask2 = 0x3;
35
36 // Ensure port ids are representable in JavaScript for the benefit of
37 // vm-service clients such as Observatory.
38 result = prng_->NextJSInt() | kMask2;
39
40 // The two special marker ports are used for the hashset implementation and
41 // cannot be used as actual ports.
42 if (result == PortSet<Entry>::kFreePort ||
43 result == PortSet<Entry>::kDeletedPort) {
44 continue;
45 }
46
47 ASSERT(!static_cast<ObjectPtr>(static_cast<uword>(result))->IsWellFormed());
48 } while (ports_->Contains(result));
49
50 ASSERT(result != 0);
51 ASSERT(!ports_->Contains(result));
52 return result;
53}
54
56 ASSERT(handler != nullptr);
57 MutexLocker ml(mutex_);
58 if (ports_ == nullptr) {
59 return ILLEGAL_PORT;
60 }
61
62#if defined(DEBUG)
63 handler->CheckAccess();
64#endif
65
66 const Dart_Port port = AllocatePort();
67
68 // The MessageHandler::ports_ is only accessed by [PortMap], it is guarded
69 // by the [PortMap::mutex_] we already hold.
70 MessageHandler::PortSetEntry isolate_entry;
71 isolate_entry.port = port;
72 handler->ports_.Insert(isolate_entry);
73
74 Entry entry;
75 entry.port = port;
76 entry.handler = handler;
77 ports_->Insert(entry);
78
79 if (FLAG_trace_isolates) {
81 "[+] Opening port: \n"
82 "\thandler: %s\n"
83 "\tport: %" Pd64 "\n",
84 handler->name(), entry.port);
85 }
86
87 return entry.port;
88}
89
90bool PortMap::ClosePort(Dart_Port port, MessageHandler** message_handler) {
91 if (message_handler != nullptr) *message_handler = nullptr;
92
93 MessageHandler* handler = nullptr;
94 {
95 MutexLocker ml(mutex_);
96 if (ports_ == nullptr) {
97 return false;
98 }
99 auto it = ports_->TryLookup(port);
100 if (it == ports_->end()) {
101 return false;
102 }
103 Entry entry = *it;
104 handler = entry.handler;
105 ASSERT(handler != nullptr);
106
107#if defined(DEBUG)
108 handler->CheckAccess();
109#endif
110
111 // Delete the port entry before releasing the lock to avoid holding the lock
112 // while flushing the messages below.
113 it.Delete();
114 ports_->Rebalance();
115
116 // The MessageHandler::ports_ is only accessed by [PortMap], it is guarded
117 // by the [PortMap::mutex_] we already hold.
118 auto isolate_it = handler->ports_.TryLookup(port);
119 ASSERT(isolate_it != handler->ports_.end());
120 isolate_it.Delete();
121 handler->ports_.Rebalance();
122 }
123 handler->ClosePort(port);
124 if (message_handler != nullptr) *message_handler = handler;
125 return true;
126}
127
129 {
130 MutexLocker ml(mutex_);
131 if (ports_ == nullptr) {
132 return;
133 }
134 // The MessageHandler::ports_ is only accessed by [PortMap], it is guarded
135 // by the [PortMap::mutex_] we already hold.
136 for (auto isolate_it = handler->ports_.begin();
137 isolate_it != handler->ports_.end(); ++isolate_it) {
138 auto it = ports_->TryLookup((*isolate_it).port);
139 ASSERT(it != ports_->end());
140 Entry entry = *it;
141 ASSERT(entry.port == (*isolate_it).port);
142 ASSERT(entry.handler == handler);
143 it.Delete();
144 isolate_it.Delete();
145 }
146 ASSERT(handler->ports_.IsEmpty());
147 ports_->Rebalance();
148 }
149 handler->CloseAllPorts();
150}
151
152bool PortMap::PostMessage(std::unique_ptr<Message> message,
153 bool before_events) {
154 MutexLocker ml(mutex_);
155 if (ports_ == nullptr) {
156 return false;
157 }
158 auto it = ports_->TryLookup(message->dest_port());
159 if (it == ports_->end()) {
160 // Ownership of external data remains with the poster.
161 message->DropFinalizers();
162 return false;
163 }
164 MessageHandler* handler = (*it).handler;
165 ASSERT(handler != nullptr);
166 handler->PostMessage(std::move(message), before_events);
167 return true;
168}
169
170#if defined(TESTING)
171bool PortMap::PortExists(Dart_Port id) {
172 MutexLocker ml(mutex_);
173 if (ports_ == nullptr) {
174 return false;
175 }
176 auto it = ports_->TryLookup(id);
177 return it != ports_->end();
178}
179#endif // defined(TESTING)
180
182 MutexLocker ml(mutex_);
183 if (ports_ == nullptr) {
184 return nullptr;
185 }
186 auto it = ports_->TryLookup(id);
187 if (it == ports_->end()) {
188 // Port does not exist.
189 return nullptr;
190 }
191
192 MessageHandler* handler = (*it).handler;
193 return handler->isolate();
194}
195
197 MutexLocker ml(mutex_);
198 if (ports_ == nullptr) {
199 return ILLEGAL_PORT;
200 }
201 auto it = ports_->TryLookup(id);
202 if (it == ports_->end()) {
203 // Port does not exist.
204 return ILLEGAL_PORT;
205 }
206
207 MessageHandler* handler = (*it).handler;
208 Isolate* isolate = handler->isolate();
209 if (isolate == nullptr) {
210 // Message handler is a native port instead of an isolate.
211 return ILLEGAL_PORT;
212 }
213 return isolate->origin_id();
214}
215
216#if defined(TESTING)
217bool PortMap::HasPorts(MessageHandler* handler) {
218 MutexLocker ml(mutex_);
219 if (ports_ == nullptr) {
220 return false;
221 }
222 // The MessageHandler::ports_ is only accessed by [PortMap], it is guarded
223 // by the [PortMap::mutex_] we already hold.
224 return !handler->ports_.IsEmpty();
225}
226#endif
227
229 IsolateGroup* group) {
230 MutexLocker ml(mutex_);
231 if (ports_ == nullptr) {
232 // Port was closed.
233 return true;
234 }
235 auto it = ports_->TryLookup(receiver);
236 if (it == ports_->end()) {
237 // Port was closed.
238 return true;
239 }
240 auto isolate = (*it).handler->isolate();
241 if (isolate == nullptr) {
242 // Port belongs to a native port instead of an isolate.
243 return false;
244 }
245 return isolate->group() == group;
246}
247
249 if (mutex_ == nullptr) {
250 mutex_ = new Mutex();
251 }
252 ASSERT(mutex_ != nullptr);
253 if (prng_ == nullptr) {
254 prng_ = new Random();
255 }
256 if (ports_ == nullptr) {
257 ports_ = new PortSet<Entry>();
258 }
259}
260
262 ASSERT(ports_ != nullptr);
263 ASSERT(prng_ != nullptr);
264 for (auto it = ports_->begin(); it != ports_->end(); ++it) {
265 const auto& entry = *it;
266 ASSERT(entry.handler != nullptr);
267 delete entry.handler;
268 it.Delete();
269 }
270 ports_->Rebalance();
271
272 // Grab the mutex and delete the port set.
273 MutexLocker ml(mutex_);
274 delete prng_;
275 prng_ = nullptr;
276 delete ports_;
277 ports_ = nullptr;
278}
279
281 JSONStream* stream) {
282#ifndef PRODUCT
283 JSONObject jsobj(stream);
284 jsobj.AddProperty("type", "_Ports");
285 Object& msg_handler = Object::Handle();
286 {
287 JSONArray ports(&jsobj, "ports");
288 SafepointMutexLocker ml(mutex_);
289 if (ports_ == nullptr) {
290 return;
291 }
292 for (auto& entry : *ports_) {
293 if (entry.handler == handler) {
294 JSONObject port(&ports);
295 port.AddProperty("type", "_Port");
296 port.AddPropertyF("name", "Isolate Port (%" Pd64 ")", entry.port);
297 msg_handler = DartLibraryCalls::LookupHandler(entry.port);
298 port.AddProperty("handler", msg_handler);
299 }
300 }
301 }
302#endif
303}
304
306 SafepointMutexLocker ml(mutex_);
307 if (ports_ == nullptr) {
308 return;
309 }
310 Object& msg_handler = Object::Handle();
311 for (auto& entry : *ports_) {
312 if (entry.handler == handler) {
313 OS::PrintErr("Port = %" Pd64 "\n", entry.port);
314 msg_handler = DartLibraryCalls::LookupHandler(entry.port);
315 OS::PrintErr("Handler = %s\n", msg_handler.ToCString());
316 }
317 }
318}
319
320} // namespace dart
static ObjectPtr LookupHandler(Dart_Port port_id)
Dart_Port origin_id()
Definition isolate.cc:1954
void AddProperty(const char *name, bool b) const
void PostMessage(std::unique_ptr< Message > message, bool before_events=false)
virtual const char * name() const
virtual Isolate * isolate() const
void ClosePort(Dart_Port port)
bool IsOwnedByCurrentThread() const
Definition os_thread.h:401
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
virtual const char * ToCString() const
Definition object.h:366
static Object & Handle()
Definition object.h:407
static Dart_Port GetOriginId(Dart_Port id)
Definition port.cc:196
static void DebugDumpForMessageHandler(MessageHandler *handler)
Definition port.cc:305
static bool PostMessage(std::unique_ptr< Message > message, bool before_events=false)
Definition port.cc:152
static Isolate * GetIsolate(Dart_Port id)
Definition port.cc:181
static void PrintPortsForMessageHandler(MessageHandler *handler, JSONStream *stream)
Definition port.cc:280
static bool ClosePort(Dart_Port id, MessageHandler **message_handler=nullptr)
Definition port.cc:90
static void Init()
Definition port.cc:248
static bool IsReceiverInThisIsolateGroupOrClosed(Dart_Port receiver, IsolateGroup *group)
Definition port.cc:228
static void ClosePorts(MessageHandler *handler)
Definition port.cc:128
static void Cleanup()
Definition port.cc:261
static Dart_Port CreatePort(MessageHandler *handler)
Definition port.cc:55
void Insert(const T &entry)
Definition port_set.h:126
Iterator TryLookup(Dart_Port port)
Definition port_set.h:156
DART_FORCE_INLINE Iterator begin()
Definition port_set.h:114
DART_FORCE_INLINE Iterator end()
Definition port_set.h:124
void Rebalance()
Definition port_set.h:165
bool IsEmpty() const
Definition port_set.h:112
bool Contains(Dart_Port port)
Definition port_set.h:162
uint64_t NextJSInt()
Definition random.h:37
#define ILLEGAL_PORT
Definition dart_api.h:1530
int64_t Dart_Port
Definition dart_api.h:1524
#define ASSERT(E)
GAsyncResult * result
Win32Message message
uintptr_t uword
Definition globals.h:501
#define Pd64
Definition globals.h:416