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

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
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
17 Mutex* PortMap::mutex_ = NULL; 18 Mutex* PortMap::mutex_ = NULL;
18
19 PortMap::Entry* PortMap::map_ = NULL; 19 PortMap::Entry* PortMap::map_ = NULL;
20 Isolate* PortMap::deleted_entry_ = reinterpret_cast<Isolate*>(1); 20 MessageHandler* PortMap::deleted_entry_ = reinterpret_cast<MessageHandler*>(1);
21 intptr_t PortMap::capacity_ = 0; 21 intptr_t PortMap::capacity_ = 0;
22 intptr_t PortMap::used_ = 0; 22 intptr_t PortMap::used_ = 0;
23 intptr_t PortMap::deleted_ = 0; 23 intptr_t PortMap::deleted_ = 0;
24
25 Dart_Port PortMap::next_port_ = 7111; 24 Dart_Port PortMap::next_port_ = 7111;
26 25
27 26
28 intptr_t PortMap::FindPort(Dart_Port port) { 27 intptr_t PortMap::FindPort(Dart_Port port) {
29 intptr_t index = port % capacity_; 28 intptr_t index = port % capacity_;
30 intptr_t start_index = index; 29 intptr_t start_index = index;
31 Entry entry = map_[index]; 30 Entry entry = map_[index];
32 while (entry.isolate != NULL) { 31 while (entry.handler != NULL) {
33 if (entry.port == port) { 32 if (entry.port == port) {
34 return index; 33 return index;
35 } 34 }
36 index = (index + 1) % capacity_; 35 index = (index + 1) % capacity_;
37 // Prevent endless loops. 36 // Prevent endless loops.
38 ASSERT(index != start_index); 37 ASSERT(index != start_index);
39 entry = map_[index]; 38 entry = map_[index];
40 } 39 }
41 return -1; 40 return -1;
42 } 41 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 ASSERT(result != 0); 75 ASSERT(result != 0);
77 return result; 76 return result;
78 } 77 }
79 78
80 79
81 void PortMap::SetLive(Dart_Port port) { 80 void PortMap::SetLive(Dart_Port port) {
82 MutexLocker ml(mutex_); 81 MutexLocker ml(mutex_);
83 intptr_t index = FindPort(port); 82 intptr_t index = FindPort(port);
84 ASSERT(index >= 0); 83 ASSERT(index >= 0);
85 map_[index].live = true; 84 map_[index].live = true;
86 map_[index].isolate->increment_live_ports(); 85 map_[index].handler->increment_live_ports();
87 } 86 }
88 87
89 88
90 void PortMap::MaintainInvariants() { 89 void PortMap::MaintainInvariants() {
91 intptr_t empty = capacity_ - used_ - deleted_; 90 intptr_t empty = capacity_ - used_ - deleted_;
92 if (used_ > ((capacity_ / 4) * 3)) { 91 if (used_ > ((capacity_ / 4) * 3)) {
93 // Grow the port map. 92 // Grow the port map.
94 Rehash(capacity_ * 2); 93 Rehash(capacity_ * 2);
95 } else if (empty < deleted_) { 94 } else if (empty < deleted_) {
96 // Rehash without growing the table to flush the deleted slots out of the 95 // Rehash without growing the table to flush the deleted slots out of the
97 // map. 96 // map.
98 Rehash(capacity_); 97 Rehash(capacity_);
99 } 98 }
100 } 99 }
101 100
102 101
103 Dart_Port PortMap::CreatePort() { 102 Dart_Port PortMap::CreatePort(MessageHandler* handler) {
104 Isolate* isolate = Isolate::Current(); 103 ASSERT(handler != NULL);
105 MutexLocker ml(mutex_); 104 MutexLocker ml(mutex_);
105 #if defined(DEBUG)
106 handler->CheckAccess();
107 #endif
106 108
107 Entry entry; 109 Entry entry;
108 entry.port = AllocatePort(); 110 entry.port = AllocatePort();
109 entry.isolate = isolate; 111 entry.handler = handler;
110 entry.live = false; 112 entry.live = false;
111 113
112 // Search for the first unused slot. Make use of the knowledge that here is 114 // 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. 115 // currently no port with this id in the port map.
114 ASSERT(FindPort(entry.port) < 0); 116 ASSERT(FindPort(entry.port) < 0);
115 intptr_t index = entry.port % capacity_; 117 intptr_t index = entry.port % capacity_;
116 Entry cur = map_[index]; 118 Entry cur = map_[index];
117 // Stop the search at the first found unused (free or deleted) slot. 119 // Stop the search at the first found unused (free or deleted) slot.
118 while (cur.port != 0) { 120 while (cur.port != 0) {
119 index = (index + 1) % capacity_; 121 index = (index + 1) % capacity_;
120 cur = map_[index]; 122 cur = map_[index];
121 } 123 }
122 124
123 // Insert the newly created port at the index. 125 // Insert the newly created port at the index.
124 ASSERT(index >= 0); 126 ASSERT(index >= 0);
125 ASSERT(index < capacity_); 127 ASSERT(index < capacity_);
126 ASSERT(map_[index].port == 0); 128 ASSERT(map_[index].port == 0);
127 ASSERT((map_[index].isolate == NULL) || 129 ASSERT((map_[index].handler == NULL) ||
128 (map_[index].isolate == deleted_entry_)); 130 (map_[index].handler == deleted_entry_));
129 if (map_[index].isolate == deleted_entry_) { 131 if (map_[index].handler == deleted_entry_) {
130 // Consuming a deleted entry. 132 // Consuming a deleted entry.
131 deleted_--; 133 deleted_--;
132 } 134 }
133 map_[index] = entry; 135 map_[index] = entry;
134 isolate->increment_num_ports();
135 136
136 // Increment number of used slots and grow if necessary. 137 // Increment number of used slots and grow if necessary.
137 used_++; 138 used_++;
138 MaintainInvariants(); 139 MaintainInvariants();
139 140
140 return entry.port; 141 return entry.port;
141 } 142 }
142 143
143 144
144 void PortMap::ClosePort(Dart_Port port) { 145 bool PortMap::ClosePort(Dart_Port port) {
145 Isolate* isolate = Isolate::Current(); 146 MessageHandler* handler = NULL;
146 { 147 {
147 MutexLocker ml(mutex_); 148 MutexLocker ml(mutex_);
148 intptr_t index = FindPort(port); 149 intptr_t index = FindPort(port);
149 if (index < 0) { 150 if (index < 0) {
150 return; 151 return false;
151 } 152 }
152 ASSERT(index < capacity_); 153 ASSERT(index < capacity_);
153 ASSERT(map_[index].port != 0); 154 ASSERT(map_[index].port != 0);
154 ASSERT(map_[index].isolate == isolate); 155 ASSERT(map_[index].handler != deleted_entry_);
156 ASSERT(map_[index].handler != NULL);
157
158 handler = map_[index].handler;
159 #if defined(DEBUG)
160 handler->CheckAccess();
161 #endif
155 // Before releasing the lock mark the slot in the map as deleted. This makes 162 // 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 163 // it possible to release the port map lock before flushing all of its
157 // pending messages below. 164 // pending messages below.
158 map_[index].port = 0; 165 map_[index].port = 0;
159 map_[index].isolate = deleted_entry_; 166 map_[index].handler = deleted_entry_;
160 isolate->decrement_num_ports();
161 if (map_[index].live) { 167 if (map_[index].live) {
162 isolate->decrement_live_ports(); 168 handler->decrement_live_ports();
163 } 169 }
164 170
165 used_--; 171 used_--;
166 deleted_++; 172 deleted_++;
167 MaintainInvariants(); 173 MaintainInvariants();
168 } 174 }
169 isolate->ClosePort(port); 175 handler->ClosePort(port);
176 if (!handler->HasLivePorts() && handler->OwnedByPortMap()) {
177 delete handler;
178 }
179 return true;
170 } 180 }
171 181
172 182
173 void PortMap::ClosePorts() { 183 void PortMap::ClosePorts(MessageHandler* handler) {
174 Isolate* isolate = Isolate::Current();
175 { 184 {
176 MutexLocker ml(mutex_); 185 MutexLocker ml(mutex_);
177 for (intptr_t i = 0; i < capacity_; i++) { 186 for (intptr_t i = 0; i < capacity_; i++) {
178 if (map_[i].isolate == isolate) { 187 if (map_[i].handler == handler) {
179 // Mark the slot as deleted. 188 // Mark the slot as deleted.
180 map_[i].port = 0; 189 map_[i].port = 0;
181 map_[i].isolate = deleted_entry_; 190 map_[i].handler = deleted_entry_;
182 isolate->decrement_num_ports(); 191 if (map_[i].live) {
183 192 handler->decrement_live_ports();
193 }
184 used_--; 194 used_--;
185 deleted_++; 195 deleted_++;
186 } 196 }
187 } 197 }
188 MaintainInvariants(); 198 MaintainInvariants();
189 } 199 }
190 isolate->CloseAllPorts(); 200 handler->CloseAllPorts();
191 } 201 }
192 202
193 203
194 bool PortMap::PostMessage(Message* message) { 204 bool PortMap::PostMessage(Message* message) {
195 // TODO(turnidge): Add a scoped locker for mutexes which is not a 205 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()); 206 intptr_t index = FindPort(message->dest_port());
200 if (index < 0) { 207 if (index < 0) {
201 free(message); 208 free(message);
202 mutex_->Unlock();
203 return false; 209 return false;
204 } 210 }
205 ASSERT(index >= 0); 211 ASSERT(index >= 0);
206 ASSERT(index < capacity_); 212 ASSERT(index < capacity_);
207 Isolate* isolate = map_[index].isolate; 213 MessageHandler* handler = map_[index].handler;
208 ASSERT(map_[index].port != 0); 214 ASSERT(map_[index].port != 0);
209 ASSERT((isolate != NULL) && (isolate != deleted_entry_)); 215 ASSERT((handler != NULL) && (handler != deleted_entry_));
210 isolate->PostMessage(message); 216 handler->PostMessage(message);
211 mutex_->Unlock();
212 return true; 217 return true;
213 } 218 }
214 219
215 220
216 void PortMap::InitOnce() { 221 void PortMap::InitOnce() {
217 mutex_ = new Mutex(); 222 mutex_ = new Mutex();
218 223
219 static const intptr_t kInitialCapacity = 8; 224 static const intptr_t kInitialCapacity = 8;
220 // TODO(iposva): Verify whether we want to keep exponentially growing. 225 // TODO(iposva): Verify whether we want to keep exponentially growing.
221 ASSERT(Utils::IsPowerOfTwo(kInitialCapacity)); 226 ASSERT(Utils::IsPowerOfTwo(kInitialCapacity));
222 map_ = new Entry[kInitialCapacity]; 227 map_ = new Entry[kInitialCapacity];
223 memset(map_, 0, kInitialCapacity * sizeof(Entry)); 228 memset(map_, 0, kInitialCapacity * sizeof(Entry));
224 capacity_ = kInitialCapacity; 229 capacity_ = kInitialCapacity;
225 used_ = 0; 230 used_ = 0;
226 deleted_ = 0; 231 deleted_ = 0;
227 } 232 }
228 233
229
230 } // namespace dart 234 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698