| 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 |