Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(698)

Side by Side Diff: runtime/vm/port.cc

Issue 9169063: Add support for native ports in the vm. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 8 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/port.h ('k') | runtime/vm/port_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/port.h" 5 #include "vm/port.h"
6 6
7 #include "platform/utils.h" 7 #include "platform/utils.h"
8 #include "vm/dart_api_impl.h" 8 #include "vm/dart_api_impl.h"
9 #include "vm/isolate.h" 9 #include "vm/isolate.h"
10 #include "vm/message_queue.h" 10 #include "vm/message.h"
11 #include "vm/thread.h" 11 #include "vm/thread.h"
12 12
13 namespace dart { 13 namespace dart {
14 14
15 DECLARE_FLAG(bool, trace_isolates); 15 DECLARE_FLAG(bool, trace_isolates);
16 16
17 Mutex* PortMap::mutex_ = NULL; 17 Mutex* PortMap::mutex_ = NULL;
18
19 PortMap::Entry* PortMap::map_ = NULL; 18 PortMap::Entry* PortMap::map_ = NULL;
20 Isolate* PortMap::deleted_entry_ = reinterpret_cast<Isolate*>(1); 19 MessageHandler* PortMap::deleted_entry_ = reinterpret_cast<MessageHandler*>(1);
21 intptr_t PortMap::capacity_ = 0; 20 intptr_t PortMap::capacity_ = 0;
22 intptr_t PortMap::used_ = 0; 21 intptr_t PortMap::used_ = 0;
23 intptr_t PortMap::deleted_ = 0; 22 intptr_t PortMap::deleted_ = 0;
24
25 Dart_Port PortMap::next_port_ = 7111; 23 Dart_Port PortMap::next_port_ = 7111;
26 24
27 25
28 intptr_t PortMap::FindPort(Dart_Port port) { 26 intptr_t PortMap::FindPort(Dart_Port port) {
29 intptr_t index = port % capacity_; 27 intptr_t index = port % capacity_;
30 intptr_t start_index = index; 28 intptr_t start_index = index;
31 Entry entry = map_[index]; 29 Entry entry = map_[index];
32 while (entry.isolate != NULL) { 30 while (entry.handler != NULL) {
33 if (entry.port == port) { 31 if (entry.port == port) {
34 return index; 32 return index;
35 } 33 }
36 index = (index + 1) % capacity_; 34 index = (index + 1) % capacity_;
37 // Prevent endless loops. 35 // Prevent endless loops.
38 ASSERT(index != start_index); 36 ASSERT(index != start_index);
39 entry = map_[index]; 37 entry = map_[index];
40 } 38 }
41 return -1; 39 return -1;
42 } 40 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 ASSERT(result != 0); 74 ASSERT(result != 0);
77 return result; 75 return result;
78 } 76 }
79 77
80 78
81 void PortMap::SetLive(Dart_Port port) { 79 void PortMap::SetLive(Dart_Port port) {
82 MutexLocker ml(mutex_); 80 MutexLocker ml(mutex_);
83 intptr_t index = FindPort(port); 81 intptr_t index = FindPort(port);
84 ASSERT(index >= 0); 82 ASSERT(index >= 0);
85 map_[index].live = true; 83 map_[index].live = true;
86 map_[index].isolate->increment_live_ports(); 84 map_[index].handler->increment_live_ports();
87 } 85 }
88 86
89 87
90 void PortMap::MaintainInvariants() { 88 void PortMap::MaintainInvariants() {
91 intptr_t empty = capacity_ - used_ - deleted_; 89 intptr_t empty = capacity_ - used_ - deleted_;
92 if (used_ > ((capacity_ / 4) * 3)) { 90 if (used_ > ((capacity_ / 4) * 3)) {
93 // Grow the port map. 91 // Grow the port map.
94 Rehash(capacity_ * 2); 92 Rehash(capacity_ * 2);
95 } else if (empty < deleted_) { 93 } else if (empty < deleted_) {
96 // Rehash without growing the table to flush the deleted slots out of the 94 // Rehash without growing the table to flush the deleted slots out of the
97 // map. 95 // map.
98 Rehash(capacity_); 96 Rehash(capacity_);
99 } 97 }
100 } 98 }
101 99
102 100
103 Dart_Port PortMap::CreatePort() { 101 Dart_Port PortMap::CreatePort(MessageHandler* handler) {
104 Isolate* isolate = Isolate::Current(); 102 ASSERT(handler != NULL);
105 MutexLocker ml(mutex_); 103 MutexLocker ml(mutex_);
104 #if defined(DEBUG)
105 handler->CheckAccess();
106 #endif
106 107
107 Entry entry; 108 Entry entry;
108 entry.port = AllocatePort(); 109 entry.port = AllocatePort();
109 entry.isolate = isolate; 110 entry.handler = handler;
110 entry.live = false; 111 entry.live = false;
111 112
112 // Search for the first unused slot. Make use of the knowledge that here is 113 // Search for the first unused slot. Make use of the knowledge that here is
113 // currently no port with this id in the port map. 114 // currently no port with this id in the port map.
114 ASSERT(FindPort(entry.port) < 0); 115 ASSERT(FindPort(entry.port) < 0);
115 intptr_t index = entry.port % capacity_; 116 intptr_t index = entry.port % capacity_;
116 Entry cur = map_[index]; 117 Entry cur = map_[index];
117 // Stop the search at the first found unused (free or deleted) slot. 118 // Stop the search at the first found unused (free or deleted) slot.
118 while (cur.port != 0) { 119 while (cur.port != 0) {
119 index = (index + 1) % capacity_; 120 index = (index + 1) % capacity_;
120 cur = map_[index]; 121 cur = map_[index];
121 } 122 }
122 123
123 // Insert the newly created port at the index. 124 // Insert the newly created port at the index.
124 ASSERT(index >= 0); 125 ASSERT(index >= 0);
125 ASSERT(index < capacity_); 126 ASSERT(index < capacity_);
126 ASSERT(map_[index].port == 0); 127 ASSERT(map_[index].port == 0);
127 ASSERT((map_[index].isolate == NULL) || 128 ASSERT((map_[index].handler == NULL) ||
128 (map_[index].isolate == deleted_entry_)); 129 (map_[index].handler == deleted_entry_));
129 if (map_[index].isolate == deleted_entry_) { 130 if (map_[index].handler == deleted_entry_) {
130 // Consuming a deleted entry. 131 // Consuming a deleted entry.
131 deleted_--; 132 deleted_--;
132 } 133 }
133 map_[index] = entry; 134 map_[index] = entry;
134 isolate->increment_num_ports();
135 135
136 // Increment number of used slots and grow if necessary. 136 // Increment number of used slots and grow if necessary.
137 used_++; 137 used_++;
138 MaintainInvariants(); 138 MaintainInvariants();
139 139
140 return entry.port; 140 return entry.port;
141 } 141 }
142 142
143 143
144 void PortMap::ClosePort(Dart_Port port) { 144 bool PortMap::ClosePort(Dart_Port port) {
145 Isolate* isolate = Isolate::Current(); 145 MessageHandler* handler = NULL;
146 { 146 {
147 MutexLocker ml(mutex_); 147 MutexLocker ml(mutex_);
148 intptr_t index = FindPort(port); 148 intptr_t index = FindPort(port);
149 if (index < 0) { 149 if (index < 0) {
150 return; 150 return false;
151 } 151 }
152 ASSERT(index < capacity_); 152 ASSERT(index < capacity_);
153 ASSERT(map_[index].port != 0); 153 ASSERT(map_[index].port != 0);
154 ASSERT(map_[index].isolate == isolate); 154 ASSERT(map_[index].handler != deleted_entry_);
155 ASSERT(map_[index].handler != NULL);
156
157 handler = map_[index].handler;
158 #if defined(DEBUG)
159 handler->CheckAccess();
160 #endif
155 // Before releasing the lock mark the slot in the map as deleted. This makes 161 // Before releasing the lock mark the slot in the map as deleted. This makes
156 // it possible to release the port map lock before flushing all of its 162 // it possible to release the port map lock before flushing all of its
157 // pending messages below. 163 // pending messages below.
158 map_[index].port = 0; 164 map_[index].port = 0;
159 map_[index].isolate = deleted_entry_; 165 map_[index].handler = deleted_entry_;
160 isolate->decrement_num_ports();
161 if (map_[index].live) { 166 if (map_[index].live) {
162 isolate->decrement_live_ports(); 167 handler->decrement_live_ports();
163 } 168 }
164 169
165 used_--; 170 used_--;
166 deleted_++; 171 deleted_++;
167 MaintainInvariants(); 172 MaintainInvariants();
168 } 173 }
169 isolate->ClosePort(port); 174 handler->ClosePort(port);
175 if (!handler->HasLivePorts() && handler->OwnedByPortMap()) {
176 delete handler;
177 }
178 return true;
170 } 179 }
171 180
172 181
173 void PortMap::ClosePorts() { 182 void PortMap::ClosePorts(MessageHandler* handler) {
174 Isolate* isolate = Isolate::Current();
175 { 183 {
176 MutexLocker ml(mutex_); 184 MutexLocker ml(mutex_);
177 for (intptr_t i = 0; i < capacity_; i++) { 185 for (intptr_t i = 0; i < capacity_; i++) {
178 if (map_[i].isolate == isolate) { 186 if (map_[i].handler == handler) {
179 // Mark the slot as deleted. 187 // Mark the slot as deleted.
180 map_[i].port = 0; 188 map_[i].port = 0;
181 map_[i].isolate = deleted_entry_; 189 map_[i].handler = deleted_entry_;
182 isolate->decrement_num_ports(); 190 if (map_[i].live) {
183 191 handler->decrement_live_ports();
192 }
184 used_--; 193 used_--;
185 deleted_++; 194 deleted_++;
186 } 195 }
187 } 196 }
188 MaintainInvariants(); 197 MaintainInvariants();
189 } 198 }
190 isolate->CloseAllPorts(); 199 handler->CloseAllPorts();
191 } 200 }
192 201
193 202
194 bool PortMap::PostMessage(Message* message) { 203 bool PortMap::PostMessage(Message* message) {
195 // TODO(turnidge): Add a scoped locker for mutexes which is not a 204 MutexLocker ml(mutex_);
196 // stack resource. This would probably be useful in the platform
197 // headers.
198 mutex_->Lock();
199 intptr_t index = FindPort(message->dest_port()); 205 intptr_t index = FindPort(message->dest_port());
200 if (index < 0) { 206 if (index < 0) {
201 free(message); 207 free(message);
202 mutex_->Unlock();
203 return false; 208 return false;
204 } 209 }
205 ASSERT(index >= 0); 210 ASSERT(index >= 0);
206 ASSERT(index < capacity_); 211 ASSERT(index < capacity_);
207 Isolate* isolate = map_[index].isolate; 212 MessageHandler* handler = map_[index].handler;
208 ASSERT(map_[index].port != 0); 213 ASSERT(map_[index].port != 0);
209 ASSERT((isolate != NULL) && (isolate != deleted_entry_)); 214 ASSERT((handler != NULL) && (handler != deleted_entry_));
210 isolate->PostMessage(message); 215 handler->PostMessage(message);
211 mutex_->Unlock();
212 return true; 216 return true;
213 } 217 }
214 218
215 219
216 void PortMap::InitOnce() { 220 void PortMap::InitOnce() {
217 mutex_ = new Mutex(); 221 mutex_ = new Mutex();
218 222
219 static const intptr_t kInitialCapacity = 8; 223 static const intptr_t kInitialCapacity = 8;
220 // TODO(iposva): Verify whether we want to keep exponentially growing. 224 // TODO(iposva): Verify whether we want to keep exponentially growing.
221 ASSERT(Utils::IsPowerOfTwo(kInitialCapacity)); 225 ASSERT(Utils::IsPowerOfTwo(kInitialCapacity));
222 map_ = new Entry[kInitialCapacity]; 226 map_ = new Entry[kInitialCapacity];
223 memset(map_, 0, kInitialCapacity * sizeof(Entry)); 227 memset(map_, 0, kInitialCapacity * sizeof(Entry));
224 capacity_ = kInitialCapacity; 228 capacity_ = kInitialCapacity;
225 used_ = 0; 229 used_ = 0;
226 deleted_ = 0; 230 deleted_ = 0;
227 } 231 }
228 232
229
230 } // namespace dart 233 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/port.h ('k') | runtime/vm/port_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698