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/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 | |
siva
2012/01/28 00:21:05
extra blank line?
turnidge
2012/01/31 20:04:31
So when is it two and when is it one? Functions g
siva
2012/02/01 00:38:56
I think functions get 2 and vars get 1.
On 2012/0
turnidge
2012/02/01 18:51:26
Done.
| |
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 Loading... | |
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); |
siva
2012/01/28 00:21:05
#ifdef DEBUG
handler->CheckAccess();
#endif
turnidge
2012/01/31 20:04:31
Done.
| |
105 MutexLocker ml(mutex_); | 104 mutex_->Lock(); |
106 | 105 |
107 Entry entry; | 106 Entry entry; |
108 entry.port = AllocatePort(); | 107 entry.port = AllocatePort(); |
109 entry.isolate = isolate; | 108 entry.handler = handler; |
110 entry.live = false; | 109 entry.live = false; |
111 | 110 |
112 // Search for the first unused slot. Make use of the knowledge that here is | 111 // 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. | 112 // currently no port with this id in the port map. |
114 ASSERT(FindPort(entry.port) < 0); | 113 ASSERT(FindPort(entry.port) < 0); |
115 intptr_t index = entry.port % capacity_; | 114 intptr_t index = entry.port % capacity_; |
116 Entry cur = map_[index]; | 115 Entry cur = map_[index]; |
117 // Stop the search at the first found unused (free or deleted) slot. | 116 // Stop the search at the first found unused (free or deleted) slot. |
118 while (cur.port != 0) { | 117 while (cur.port != 0) { |
119 index = (index + 1) % capacity_; | 118 index = (index + 1) % capacity_; |
120 cur = map_[index]; | 119 cur = map_[index]; |
121 } | 120 } |
122 | 121 |
123 // Insert the newly created port at the index. | 122 // Insert the newly created port at the index. |
124 ASSERT(index >= 0); | 123 ASSERT(index >= 0); |
125 ASSERT(index < capacity_); | 124 ASSERT(index < capacity_); |
126 ASSERT(map_[index].port == 0); | 125 ASSERT(map_[index].port == 0); |
127 ASSERT((map_[index].isolate == NULL) || | 126 ASSERT((map_[index].handler == NULL) || |
128 (map_[index].isolate == deleted_entry_)); | 127 (map_[index].handler == deleted_entry_)); |
129 if (map_[index].isolate == deleted_entry_) { | 128 if (map_[index].handler == deleted_entry_) { |
130 // Consuming a deleted entry. | 129 // Consuming a deleted entry. |
131 deleted_--; | 130 deleted_--; |
132 } | 131 } |
133 map_[index] = entry; | 132 map_[index] = entry; |
134 isolate->increment_num_ports(); | |
135 | 133 |
136 // Increment number of used slots and grow if necessary. | 134 // Increment number of used slots and grow if necessary. |
137 used_++; | 135 used_++; |
138 MaintainInvariants(); | 136 MaintainInvariants(); |
139 | 137 |
138 mutex_->Unlock(); | |
140 return entry.port; | 139 return entry.port; |
141 } | 140 } |
142 | 141 |
143 | 142 |
144 void PortMap::ClosePort(Dart_Port port) { | 143 bool PortMap::ClosePort(Dart_Port port) { |
145 Isolate* isolate = Isolate::Current(); | 144 MessageHandler* handler = NULL; |
146 { | 145 { |
147 MutexLocker ml(mutex_); | 146 mutex_->Lock(); |
148 intptr_t index = FindPort(port); | 147 intptr_t index = FindPort(port); |
149 if (index < 0) { | 148 if (index < 0) { |
150 return; | 149 mutex_->Unlock(); |
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(); |
173 mutex_->Unlock(); | |
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 // TODO(turnidge): Add a scoped locker for mutexes which is not a |
196 // stack resource. This would probably be useful in the platform | 206 // stack resource. This would probably be useful in the platform |
197 // headers. | 207 // headers. |
198 mutex_->Lock(); | 208 mutex_->Lock(); |
199 intptr_t index = FindPort(message->dest_port()); | 209 intptr_t index = FindPort(message->dest_port()); |
200 if (index < 0) { | 210 if (index < 0) { |
201 free(message); | 211 free(message); |
202 mutex_->Unlock(); | 212 mutex_->Unlock(); |
203 return false; | 213 return false; |
204 } | 214 } |
205 ASSERT(index >= 0); | 215 ASSERT(index >= 0); |
206 ASSERT(index < capacity_); | 216 ASSERT(index < capacity_); |
207 Isolate* isolate = map_[index].isolate; | 217 MessageHandler* handler = map_[index].handler; |
208 ASSERT(map_[index].port != 0); | 218 ASSERT(map_[index].port != 0); |
209 ASSERT((isolate != NULL) && (isolate != deleted_entry_)); | 219 ASSERT((handler != NULL) && (handler != deleted_entry_)); |
210 isolate->PostMessage(message); | 220 handler->PostMessage(message); |
211 mutex_->Unlock(); | 221 mutex_->Unlock(); |
212 return true; | 222 return true; |
213 } | 223 } |
214 | 224 |
215 | 225 |
216 void PortMap::InitOnce() { | 226 void PortMap::InitOnce() { |
217 mutex_ = new Mutex(); | 227 mutex_ = new Mutex(); |
218 | 228 |
219 static const intptr_t kInitialCapacity = 8; | 229 static const intptr_t kInitialCapacity = 8; |
220 // TODO(iposva): Verify whether we want to keep exponentially growing. | 230 // TODO(iposva): Verify whether we want to keep exponentially growing. |
221 ASSERT(Utils::IsPowerOfTwo(kInitialCapacity)); | 231 ASSERT(Utils::IsPowerOfTwo(kInitialCapacity)); |
222 map_ = new Entry[kInitialCapacity]; | 232 map_ = new Entry[kInitialCapacity]; |
223 memset(map_, 0, kInitialCapacity * sizeof(Entry)); | 233 memset(map_, 0, kInitialCapacity * sizeof(Entry)); |
224 capacity_ = kInitialCapacity; | 234 capacity_ = kInitialCapacity; |
225 used_ = 0; | 235 used_ = 0; |
226 deleted_ = 0; | 236 deleted_ = 0; |
227 } | 237 } |
228 | 238 |
229 | |
230 } // namespace dart | 239 } // namespace dart |
OLD | NEW |