OLD | NEW |
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/lockers.h" | 10 #include "vm/lockers.h" |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 new_ports[new_index] = entry; | 56 new_ports[new_index] = entry; |
57 } | 57 } |
58 } | 58 } |
59 delete[] map_; | 59 delete[] map_; |
60 map_ = new_ports; | 60 map_ = new_ports; |
61 capacity_ = new_capacity; | 61 capacity_ = new_capacity; |
62 deleted_ = 0; | 62 deleted_ = 0; |
63 } | 63 } |
64 | 64 |
65 | 65 |
| 66 const char* PortMap::PortStateString(PortState kind) { |
| 67 switch (kind) { |
| 68 case kNewPort: |
| 69 return "new"; |
| 70 case kLivePort: |
| 71 return "live"; |
| 72 case kControlPort: |
| 73 return "control"; |
| 74 default: |
| 75 UNREACHABLE(); |
| 76 return "UNKNOWN"; |
| 77 } |
| 78 } |
| 79 |
| 80 |
66 Dart_Port PortMap::AllocatePort() { | 81 Dart_Port PortMap::AllocatePort() { |
67 const Dart_Port kMASK = 0x3fffffff; | 82 const Dart_Port kMASK = 0x3fffffff; |
68 Dart_Port result = prng_->NextUInt32() & kMASK; | 83 Dart_Port result = prng_->NextUInt32() & kMASK; |
69 | 84 |
70 // Keep getting new values while we have an illegal port number or the port | 85 // Keep getting new values while we have an illegal port number or the port |
71 // number is already in use. | 86 // number is already in use. |
72 while ((result == 0) || (FindPort(result) >= 0)) { | 87 while ((result == 0) || (FindPort(result) >= 0)) { |
73 result = prng_->NextUInt32() & kMASK; | 88 result = prng_->NextUInt32() & kMASK; |
74 } | 89 } |
75 | 90 |
76 ASSERT(result != 0); | 91 ASSERT(result != 0); |
77 ASSERT(FindPort(result) < 0); | 92 ASSERT(FindPort(result) < 0); |
78 return result; | 93 return result; |
79 } | 94 } |
80 | 95 |
81 | 96 |
82 void PortMap::SetLive(Dart_Port port) { | 97 void PortMap::SetPortState(Dart_Port port, PortState state) { |
83 MutexLocker ml(mutex_); | 98 MutexLocker ml(mutex_); |
84 intptr_t index = FindPort(port); | 99 intptr_t index = FindPort(port); |
85 ASSERT(index >= 0); | 100 ASSERT(index >= 0); |
86 map_[index].live = true; | 101 PortState old_state = map_[index].state; |
87 map_[index].handler->increment_live_ports(); | 102 ASSERT(old_state == kNewPort); |
| 103 map_[index].state = state; |
| 104 if (state == kLivePort) { |
| 105 map_[index].handler->increment_live_ports(); |
| 106 } |
88 if (FLAG_trace_isolates) { | 107 if (FLAG_trace_isolates) { |
89 OS::Print("[^] Live port: \n" | 108 OS::Print("[^] Port (%s) -> (%s): \n" |
90 "\thandler: %s\n" | 109 "\thandler: %s\n" |
91 "\tport: %" Pd64 "\n", | 110 "\tport: %" Pd64 "\n", |
| 111 PortStateString(old_state), PortStateString(state), |
92 map_[index].handler->name(), port); | 112 map_[index].handler->name(), port); |
93 } | 113 } |
94 } | 114 } |
95 | 115 |
96 | 116 |
97 void PortMap::MaintainInvariants() { | 117 void PortMap::MaintainInvariants() { |
98 intptr_t empty = capacity_ - used_ - deleted_; | 118 intptr_t empty = capacity_ - used_ - deleted_; |
99 if (used_ > ((capacity_ / 4) * 3)) { | 119 if (used_ > ((capacity_ / 4) * 3)) { |
100 // Grow the port map. | 120 // Grow the port map. |
101 Rehash(capacity_ * 2); | 121 Rehash(capacity_ * 2); |
102 } else if (empty < deleted_) { | 122 } else if (empty < deleted_) { |
103 // Rehash without growing the table to flush the deleted slots out of the | 123 // Rehash without growing the table to flush the deleted slots out of the |
104 // map. | 124 // map. |
105 Rehash(capacity_); | 125 Rehash(capacity_); |
106 } | 126 } |
107 } | 127 } |
108 | 128 |
109 | 129 |
110 Dart_Port PortMap::CreatePort(MessageHandler* handler) { | 130 Dart_Port PortMap::CreatePort(MessageHandler* handler) { |
111 ASSERT(handler != NULL); | 131 ASSERT(handler != NULL); |
112 MutexLocker ml(mutex_); | 132 MutexLocker ml(mutex_); |
113 #if defined(DEBUG) | 133 #if defined(DEBUG) |
114 handler->CheckAccess(); | 134 handler->CheckAccess(); |
115 #endif | 135 #endif |
116 | 136 |
117 Entry entry; | 137 Entry entry; |
118 entry.port = AllocatePort(); | 138 entry.port = AllocatePort(); |
119 entry.handler = handler; | 139 entry.handler = handler; |
120 entry.live = false; | 140 entry.state = kNewPort; |
121 | 141 |
122 // Search for the first unused slot. Make use of the knowledge that here is | 142 // Search for the first unused slot. Make use of the knowledge that here is |
123 // currently no port with this id in the port map. | 143 // currently no port with this id in the port map. |
124 ASSERT(FindPort(entry.port) < 0); | 144 ASSERT(FindPort(entry.port) < 0); |
125 intptr_t index = entry.port % capacity_; | 145 intptr_t index = entry.port % capacity_; |
126 Entry cur = map_[index]; | 146 Entry cur = map_[index]; |
127 // Stop the search at the first found unused (free or deleted) slot. | 147 // Stop the search at the first found unused (free or deleted) slot. |
128 while (cur.port != 0) { | 148 while (cur.port != 0) { |
129 index = (index + 1) % capacity_; | 149 index = (index + 1) % capacity_; |
130 cur = map_[index]; | 150 cur = map_[index]; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 | 192 |
173 handler = map_[index].handler; | 193 handler = map_[index].handler; |
174 #if defined(DEBUG) | 194 #if defined(DEBUG) |
175 handler->CheckAccess(); | 195 handler->CheckAccess(); |
176 #endif | 196 #endif |
177 // Before releasing the lock mark the slot in the map as deleted. This makes | 197 // Before releasing the lock mark the slot in the map as deleted. This makes |
178 // it possible to release the port map lock before flushing all of its | 198 // it possible to release the port map lock before flushing all of its |
179 // pending messages below. | 199 // pending messages below. |
180 map_[index].port = 0; | 200 map_[index].port = 0; |
181 map_[index].handler = deleted_entry_; | 201 map_[index].handler = deleted_entry_; |
182 if (map_[index].live) { | 202 if (map_[index].state == kLivePort) { |
183 handler->decrement_live_ports(); | 203 handler->decrement_live_ports(); |
184 } | 204 } |
185 | 205 |
186 used_--; | 206 used_--; |
187 deleted_++; | 207 deleted_++; |
188 MaintainInvariants(); | 208 MaintainInvariants(); |
189 } | 209 } |
190 handler->ClosePort(port); | 210 handler->ClosePort(port); |
191 if (!handler->HasLivePorts() && handler->OwnedByPortMap()) { | 211 if (!handler->HasLivePorts() && handler->OwnedByPortMap()) { |
192 delete handler; | 212 delete handler; |
193 } | 213 } |
194 return true; | 214 return true; |
195 } | 215 } |
196 | 216 |
197 | 217 |
198 void PortMap::ClosePorts(MessageHandler* handler) { | 218 void PortMap::ClosePorts(MessageHandler* handler) { |
199 { | 219 { |
200 MutexLocker ml(mutex_); | 220 MutexLocker ml(mutex_); |
201 for (intptr_t i = 0; i < capacity_; i++) { | 221 for (intptr_t i = 0; i < capacity_; i++) { |
202 if (map_[i].handler == handler) { | 222 if (map_[i].handler == handler) { |
203 // Mark the slot as deleted. | 223 // Mark the slot as deleted. |
204 map_[i].port = 0; | 224 map_[i].port = 0; |
205 map_[i].handler = deleted_entry_; | 225 map_[i].handler = deleted_entry_; |
206 if (map_[i].live) { | 226 if (map_[i].state == kLivePort) { |
207 handler->decrement_live_ports(); | 227 handler->decrement_live_ports(); |
208 } | 228 } |
209 used_--; | 229 used_--; |
210 deleted_++; | 230 deleted_++; |
211 } | 231 } |
212 } | 232 } |
213 MaintainInvariants(); | 233 MaintainInvariants(); |
214 } | 234 } |
215 handler->CloseAllPorts(); | 235 handler->CloseAllPorts(); |
216 } | 236 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 // TODO(iposva): Verify whether we want to keep exponentially growing. | 287 // TODO(iposva): Verify whether we want to keep exponentially growing. |
268 ASSERT(Utils::IsPowerOfTwo(kInitialCapacity)); | 288 ASSERT(Utils::IsPowerOfTwo(kInitialCapacity)); |
269 map_ = new Entry[kInitialCapacity]; | 289 map_ = new Entry[kInitialCapacity]; |
270 memset(map_, 0, kInitialCapacity * sizeof(Entry)); | 290 memset(map_, 0, kInitialCapacity * sizeof(Entry)); |
271 capacity_ = kInitialCapacity; | 291 capacity_ = kInitialCapacity; |
272 used_ = 0; | 292 used_ = 0; |
273 deleted_ = 0; | 293 deleted_ = 0; |
274 } | 294 } |
275 | 295 |
276 } // namespace dart | 296 } // namespace dart |
OLD | NEW |