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

Side by Side Diff: runtime/bin/eventhandler_linux.cc

Issue 9186035: Use hash map for event handler file descriptor map (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Also change this for Mac OS Created 8 years, 11 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 <errno.h> 5 #include <errno.h>
6 #include <poll.h> 6 #include <poll.h>
7 #include <pthread.h> 7 #include <pthread.h>
8 #include <stdio.h> 8 #include <stdio.h>
9 #include <string.h> 9 #include <string.h>
10 #include <sys/time.h> 10 #include <sys/time.h>
11 #include <unistd.h> 11 #include <unistd.h>
12 12
13 #include "bin/eventhandler.h" 13 #include "bin/eventhandler.h"
14 #include "bin/fdutils.h" 14 #include "bin/fdutils.h"
15 #include "bin/hashmap.h"
16 #include "platform/utils.h"
15 17
16 18
17 int64_t GetCurrentTimeMilliseconds() { 19 int64_t GetCurrentTimeMilliseconds() {
18 struct timeval tv; 20 struct timeval tv;
19 if (gettimeofday(&tv, NULL) < 0) { 21 if (gettimeofday(&tv, NULL) < 0) {
20 UNREACHABLE(); 22 UNREACHABLE();
21 return 0; 23 return 0;
22 } 24 }
23 return ((static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec) / 1000; 25 return ((static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec) / 1000;
24 } 26 }
25 27
26 28
27 static const int kInitialPortMapSize = 16;
28 static const int kPortMapGrowingFactor = 2; 29 static const int kPortMapGrowingFactor = 2;
29 static const int kInterruptMessageSize = sizeof(InterruptMessage); 30 static const int kInterruptMessageSize = sizeof(InterruptMessage);
30 static const int kInfinityTimeout = -1; 31 static const int kInfinityTimeout = -1;
31 static const int kTimerId = -1; 32 static const int kTimerId = -1;
32 33
33 34
34 intptr_t SocketData::GetPollEvents() { 35 intptr_t SocketData::GetPollEvents() {
35 // Do not ask for POLLERR and POLLHUP explicitly as they are 36 // Do not ask for POLLERR and POLLHUP explicitly as they are
36 // triggered anyway. 37 // triggered anyway.
37 intptr_t events = 0; 38 intptr_t events = 0;
38 if (!IsClosedRead()) { 39 if (!IsClosedRead()) {
39 if ((mask_ & (1 << kInEvent)) != 0) { 40 if ((mask_ & (1 << kInEvent)) != 0) {
40 events |= POLLIN; 41 events |= POLLIN;
41 } 42 }
42 } 43 }
43 if (!IsClosedWrite()) { 44 if (!IsClosedWrite()) {
44 if ((mask_ & (1 << kOutEvent)) != 0) { 45 if ((mask_ & (1 << kOutEvent)) != 0) {
45 events |= POLLOUT; 46 events |= POLLOUT;
46 } 47 }
47 } 48 }
48 return events; 49 return events;
49 } 50 }
50 51
51 52
52 EventHandlerImplementation::EventHandlerImplementation() { 53 EventHandlerImplementation::EventHandlerImplementation() {
53 intptr_t result; 54 intptr_t result;
54 socket_map_size_ = kInitialPortMapSize;
55 socket_map_ = reinterpret_cast<SocketData*>(calloc(socket_map_size_,
56 sizeof(SocketData)));
57 ASSERT(socket_map_ != NULL);
58 result = TEMP_FAILURE_RETRY(pipe(interrupt_fds_)); 55 result = TEMP_FAILURE_RETRY(pipe(interrupt_fds_));
59 if (result != 0) { 56 if (result != 0) {
60 FATAL("Pipe creation failed"); 57 FATAL("Pipe creation failed");
61 } 58 }
62 FDUtils::SetNonBlocking(interrupt_fds_[0]); 59 FDUtils::SetNonBlocking(interrupt_fds_[0]);
63 timeout_ = kInfinityTimeout; 60 timeout_ = kInfinityTimeout;
64 timeout_port_ = 0; 61 timeout_port_ = 0;
65 } 62 }
66 63
67 64
68 EventHandlerImplementation::~EventHandlerImplementation() { 65 EventHandlerImplementation::~EventHandlerImplementation() {
69 free(socket_map_);
70 TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); 66 TEMP_FAILURE_RETRY(close(interrupt_fds_[0]));
71 TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); 67 TEMP_FAILURE_RETRY(close(interrupt_fds_[1]));
72 } 68 }
73 69
74 70
75 // TODO(hpayer): Use hash table instead of array.
76 SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) { 71 SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) {
77 ASSERT(fd >= 0); 72 ASSERT(fd >= 0);
78 if (fd >= socket_map_size_) { 73 HashMap::Entry* entry = socket_map_.Lookup(
79 intptr_t new_socket_map_size = socket_map_size_; 74 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true);
80 do { 75 ASSERT(entry != NULL);
81 new_socket_map_size = new_socket_map_size * kPortMapGrowingFactor; 76 SocketData* sd = reinterpret_cast<SocketData*>(entry->value);
82 } while (fd >= new_socket_map_size); 77 if (sd == NULL) {
83 size_t new_socket_map_bytes = new_socket_map_size * sizeof(SocketData); 78 sd = new SocketData(fd);
84 socket_map_ = reinterpret_cast<SocketData*>(realloc(socket_map_, 79 entry->value = sd;
85 new_socket_map_bytes));
86 ASSERT(socket_map_ != NULL);
87 size_t socket_map_bytes = socket_map_size_ * sizeof(SocketData);
88 memset(socket_map_ + socket_map_size_,
89 0,
90 new_socket_map_bytes - socket_map_bytes);
91 socket_map_size_ = new_socket_map_size;
92 } 80 }
93 81 ASSERT(fd == sd->fd());
94 SocketData* sd = socket_map_ + fd;
95 sd->set_fd(fd); // For now just make sure the fd is set.
96 return sd; 82 return sd;
97 } 83 }
98 84
99 85
100 void EventHandlerImplementation::WakeupHandler(intptr_t id, 86 void EventHandlerImplementation::WakeupHandler(intptr_t id,
101 Dart_Port dart_port, 87 Dart_Port dart_port,
102 int64_t data) { 88 int64_t data) {
103 InterruptMessage msg; 89 InterruptMessage msg;
104 msg.id = id; 90 msg.id = id;
105 msg.dart_port = dart_port; 91 msg.dart_port = dart_port;
106 msg.data = data; 92 msg.data = data;
107 intptr_t result = 93 intptr_t result =
108 FDUtils::WriteToBlocking(interrupt_fds_[1], &msg, kInterruptMessageSize); 94 FDUtils::WriteToBlocking(interrupt_fds_[1], &msg, kInterruptMessageSize);
109 if (result != kInterruptMessageSize) { 95 if (result != kInterruptMessageSize) {
110 FATAL("Interrupt message failure"); 96 FATAL("Interrupt message failure");
111 } 97 }
112 } 98 }
113 99
114 100
115 struct pollfd* EventHandlerImplementation::GetPollFds(intptr_t* pollfds_size) { 101 struct pollfd* EventHandlerImplementation::GetPollFds(intptr_t* pollfds_size) {
116 struct pollfd* pollfds; 102 struct pollfd* pollfds;
117 103
118 // Calculate the number of file descriptors to poll on. 104 // Calculate the number of file descriptors to poll on.
119 intptr_t numPollfds = 1; 105 intptr_t numPollfds = 1;
120 for (int i = 0; i < socket_map_size_; i++) { 106 for (HashMap::Entry* entry = socket_map_.Start();
121 SocketData* sd = &socket_map_[i]; 107 entry != NULL;
108 entry = socket_map_.Next(entry)) {
109 SocketData* sd = reinterpret_cast<SocketData*>(entry->value);
122 if (sd->port() > 0 && sd->GetPollEvents() != 0) numPollfds++; 110 if (sd->port() > 0 && sd->GetPollEvents() != 0) numPollfds++;
123 } 111 }
124 112
125 pollfds = reinterpret_cast<struct pollfd*>(calloc(sizeof(struct pollfd), 113 pollfds = reinterpret_cast<struct pollfd*>(calloc(sizeof(struct pollfd),
126 numPollfds)); 114 numPollfds));
127 pollfds[0].fd = interrupt_fds_[0]; 115 pollfds[0].fd = interrupt_fds_[0];
128 pollfds[0].events |= POLLIN; 116 pollfds[0].events |= POLLIN;
129 117
130 // TODO(hpayer): optimize the following iteration over the hash map 118 int i = 1;
131 int j = 1; 119 for (HashMap::Entry* entry = socket_map_.Start();
132 for (int i = 0; i < socket_map_size_; i++) { 120 entry != NULL;
133 SocketData* sd = &socket_map_[i]; 121 entry = socket_map_.Next(entry)) {
122 SocketData* sd = reinterpret_cast<SocketData*>(entry->value);
134 intptr_t events = sd->GetPollEvents(); 123 intptr_t events = sd->GetPollEvents();
135 if (sd->port() > 0 && events != 0) { 124 if (sd->port() > 0 && events != 0) {
136 // Fd is added to the poll set. 125 // Fd is added to the poll set.
137 pollfds[j].fd = sd->fd(); 126 pollfds[i].fd = sd->fd();
138 pollfds[j].events = events; 127 pollfds[i].events = events;
139 j++; 128 i++;
140 } 129 }
141 } 130 }
142 ASSERT(numPollfds == j); 131 ASSERT(numPollfds == i);
143 *pollfds_size = j; 132 *pollfds_size = i;
133
144 return pollfds; 134 return pollfds;
145 } 135 }
146 136
147 137
148 bool EventHandlerImplementation::GetInterruptMessage(InterruptMessage* msg) { 138 bool EventHandlerImplementation::GetInterruptMessage(InterruptMessage* msg) {
149 int total_read = 0; 139 int total_read = 0;
150 int bytes_read = 140 int bytes_read =
151 TEMP_FAILURE_RETRY(read(interrupt_fds_[0], msg, kInterruptMessageSize)); 141 TEMP_FAILURE_RETRY(read(interrupt_fds_[0], msg, kInterruptMessageSize));
152 if (bytes_read < 0) { 142 if (bytes_read < 0) {
153 return false; 143 return false;
(...skipping 22 matching lines...) Expand all
176 ASSERT(msg.data == (1 << kShutdownReadCommand)); 166 ASSERT(msg.data == (1 << kShutdownReadCommand));
177 // Close the socket for reading. 167 // Close the socket for reading.
178 sd->ShutdownRead(); 168 sd->ShutdownRead();
179 } else if ((msg.data & (1 << kShutdownWriteCommand)) != 0) { 169 } else if ((msg.data & (1 << kShutdownWriteCommand)) != 0) {
180 ASSERT(msg.data == (1 << kShutdownWriteCommand)); 170 ASSERT(msg.data == (1 << kShutdownWriteCommand));
181 // Close the socket for writing. 171 // Close the socket for writing.
182 sd->ShutdownWrite(); 172 sd->ShutdownWrite();
183 } else if ((msg.data & (1 << kCloseCommand)) != 0) { 173 } else if ((msg.data & (1 << kCloseCommand)) != 0) {
184 ASSERT(msg.data == (1 << kCloseCommand)); 174 ASSERT(msg.data == (1 << kCloseCommand));
185 // Close the socket and free system resources. 175 // Close the socket and free system resources.
176 intptr_t fd = sd->fd();
186 sd->Close(); 177 sd->Close();
178 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
187 } else { 179 } else {
188 // Setup events to wait for. 180 // Setup events to wait for.
189 sd->SetPortAndMask(msg.dart_port, msg.data); 181 sd->SetPortAndMask(msg.dart_port, msg.data);
190 } 182 }
191 } 183 }
192 } 184 }
193 } 185 }
194 186
195 #ifdef DEBUG_POLL 187 #ifdef DEBUG_POLL
196 static void PrintEventMask(struct pollfd* pollfd) { 188 static void PrintEventMask(struct pollfd* pollfd) {
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 FATAL("Create start event handler thread"); 367 FATAL("Create start event handler thread");
376 } 368 }
377 } 369 }
378 370
379 371
380 void EventHandlerImplementation::SendData(intptr_t id, 372 void EventHandlerImplementation::SendData(intptr_t id,
381 Dart_Port dart_port, 373 Dart_Port dart_port,
382 intptr_t data) { 374 intptr_t data) {
383 WakeupHandler(id, dart_port, data); 375 WakeupHandler(id, dart_port, data);
384 } 376 }
377
378
379 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) {
380 // The hashmap does not support keys with value 0.
381 return reinterpret_cast<void*>(fd + 1);
382 }
383
384
385 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) {
386 // The hashmap does not support keys with value 0.
387 return dart::Utils::WordHash(fd + 1);
388 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698