| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/tools/epoll_server/epoll_server.h" | 5 #include "net/tools/epoll_server/epoll_server.h" |
| 6 | 6 |
| 7 #include <unistd.h> // For read, pipe, close and write. | 7 #include <unistd.h> // For read, pipe, close and write. |
| 8 #include <stdlib.h> // for abort | 8 #include <stdlib.h> // for abort |
| 9 #include <errno.h> // for errno and strerror_r | 9 #include <errno.h> // for errno and strerror_r |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 #include <utility> | 11 #include <utility> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/timer/timer.h" | 15 #include "base/timer/timer.h" |
| 16 | 16 |
| 17 // Design notes: An efficient implementation of ready list has the following | 17 // Design notes: An efficient implementation of ready list has the following |
| 18 // desirable properties: | 18 // desirable properties: |
| 19 // | 19 // |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 public: | 62 public: |
| 63 virtual void OnEvent(int fd, EpollEvent* event) OVERRIDE { | 63 virtual void OnEvent(int fd, EpollEvent* event) OVERRIDE { |
| 64 DCHECK(event->in_events == EPOLLIN); | 64 DCHECK(event->in_events == EPOLLIN); |
| 65 int data; | 65 int data; |
| 66 int data_read = 1; | 66 int data_read = 1; |
| 67 // Read until the pipe is empty. | 67 // Read until the pipe is empty. |
| 68 while (data_read > 0) { | 68 while (data_read > 0) { |
| 69 data_read = read(fd, &data, sizeof(data)); | 69 data_read = read(fd, &data, sizeof(data)); |
| 70 } | 70 } |
| 71 } | 71 } |
| 72 virtual void OnShutdown(EpollServer *eps, int fd) OVERRIDE {} | 72 virtual void OnShutdown(EpollServer* eps, int fd) OVERRIDE {} |
| 73 virtual void OnRegistration(EpollServer*, int, int) OVERRIDE {} | 73 virtual void OnRegistration(EpollServer*, int, int) OVERRIDE {} |
| 74 virtual void OnModification(int, int) OVERRIDE {} // COV_NF_LINE | 74 virtual void OnModification(int, int) OVERRIDE {} // COV_NF_LINE |
| 75 virtual void OnUnregistration(int, bool) OVERRIDE {} // COV_NF_LINE | 75 virtual void OnUnregistration(int, bool) OVERRIDE {} // COV_NF_LINE |
| 76 }; | 76 }; |
| 77 | 77 |
| 78 //////////////////////////////////////////////////////////////////////////////// | 78 //////////////////////////////////////////////////////////////////////////////// |
| 79 //////////////////////////////////////////////////////////////////////////////// | 79 //////////////////////////////////////////////////////////////////////////////// |
| 80 | 80 |
| 81 EpollServer::EpollServer() | 81 EpollServer::EpollServer() |
| 82 : epoll_fd_(epoll_create(1024)), | 82 : epoll_fd_(epoll_create(1024)), |
| 83 timeout_in_us_(0), | 83 timeout_in_us_(0), |
| 84 recorded_now_in_us_(0), | 84 recorded_now_in_us_(0), |
| 85 ready_list_size_(0), | 85 ready_list_size_(0), |
| 86 wake_cb_(new ReadPipeCallback), | 86 wake_cb_(new ReadPipeCallback), |
| 87 read_fd_(-1), | 87 read_fd_(-1), |
| 88 write_fd_(-1), | 88 write_fd_(-1), |
| 89 in_wait_for_events_and_execute_callbacks_(false), | 89 in_wait_for_events_and_execute_callbacks_(false), |
| 90 in_shutdown_(false) { | 90 in_shutdown_(false) { |
| 91 // ensure that the epoll_fd_ is valid. | 91 // ensure that the epoll_fd_ is valid. |
| 92 CHECK_NE(epoll_fd_, -1); | 92 CHECK_NE(epoll_fd_, -1); |
| 93 LIST_INIT(&ready_list_); | 93 LIST_INIT(&ready_list_); |
| 94 LIST_INIT(&tmp_list_); | 94 LIST_INIT(&tmp_list_); |
| 95 | 95 |
| 96 int pipe_fds[2]; | 96 int pipe_fds[2]; |
| 97 if (pipe(pipe_fds) < 0) { | 97 if (pipe(pipe_fds) < 0) { |
| 98 // Unfortunately, it is impossible to test any such initialization in | 98 // Unfortunately, it is impossible to test any such initialization in |
| 99 // a constructor (as virtual methods do not yet work). | 99 // a constructor (as virtual methods do not yet work). |
| 100 // This -could- be solved by moving initialization to an outside | 100 // This -could- be solved by moving initialization to an outside |
| (...skipping 23 matching lines...) Expand all Loading... |
| 124 cb_iter = cb_map_.begin(); | 124 cb_iter = cb_map_.begin(); |
| 125 } | 125 } |
| 126 } | 126 } |
| 127 | 127 |
| 128 void EpollServer::CleanupTimeToAlarmCBMap() { | 128 void EpollServer::CleanupTimeToAlarmCBMap() { |
| 129 TimeToAlarmCBMap::iterator erase_it; | 129 TimeToAlarmCBMap::iterator erase_it; |
| 130 | 130 |
| 131 // Call OnShutdown() on alarms. Note that the structure of the loop | 131 // Call OnShutdown() on alarms. Note that the structure of the loop |
| 132 // is similar to the structure of loop in the function HandleAlarms() | 132 // is similar to the structure of loop in the function HandleAlarms() |
| 133 for (TimeToAlarmCBMap::iterator i = alarm_map_.begin(); | 133 for (TimeToAlarmCBMap::iterator i = alarm_map_.begin(); |
| 134 i != alarm_map_.end(); | 134 i != alarm_map_.end();) { |
| 135 ) { | |
| 136 // Note that OnShutdown() can call UnregisterAlarm() on | 135 // Note that OnShutdown() can call UnregisterAlarm() on |
| 137 // other iterators. OnShutdown() should not call UnregisterAlarm() | 136 // other iterators. OnShutdown() should not call UnregisterAlarm() |
| 138 // on self because by definition the iterator is not valid any more. | 137 // on self because by definition the iterator is not valid any more. |
| 139 i->second->OnShutdown(this); | 138 i->second->OnShutdown(this); |
| 140 erase_it = i; | 139 erase_it = i; |
| 141 ++i; | 140 ++i; |
| 142 alarm_map_.erase(erase_it); | 141 alarm_map_.erase(erase_it); |
| 143 } | 142 } |
| 144 } | 143 } |
| 145 | 144 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 207 AddFD(fd, event_mask); | 206 AddFD(fd, event_mask); |
| 208 } | 207 } |
| 209 fd_i->cb = cb; | 208 fd_i->cb = cb; |
| 210 fd_i->event_mask = event_mask; | 209 fd_i->event_mask = event_mask; |
| 211 fd_i->events_to_fake = 0; | 210 fd_i->events_to_fake = 0; |
| 212 } else { | 211 } else { |
| 213 AddFD(fd, event_mask); | 212 AddFD(fd, event_mask); |
| 214 cb_map_.insert(CBAndEventMask(cb, event_mask, fd)); | 213 cb_map_.insert(CBAndEventMask(cb, event_mask, fd)); |
| 215 } | 214 } |
| 216 | 215 |
| 217 | |
| 218 // set the FD to be non-blocking. | 216 // set the FD to be non-blocking. |
| 219 SetNonblocking(fd); | 217 SetNonblocking(fd); |
| 220 | 218 |
| 221 cb->OnRegistration(this, fd, event_mask); | 219 cb->OnRegistration(this, fd, event_mask); |
| 222 } | 220 } |
| 223 | 221 |
| 224 int EpollServer::GetFlags(int fd) { | 222 int EpollServer::GetFlags(int fd) { |
| 225 return fcntl(fd, F_GETFL, 0); | 223 return fcntl(fd, F_GETFL, 0); |
| 226 } | 224 } |
| 227 | 225 |
| 228 void EpollServer::SetNonblocking(int fd) { | 226 void EpollServer::SetNonblocking(int fd) { |
| 229 int flags = GetFlags(fd); | 227 int flags = GetFlags(fd); |
| 230 if (flags == -1) { | 228 if (flags == -1) { |
| 231 int saved_errno = errno; | 229 int saved_errno = errno; |
| 232 char buf[kErrorBufferSize]; | 230 char buf[kErrorBufferSize]; |
| 233 LOG(FATAL) << "Error " << saved_errno | 231 LOG(FATAL) << "Error " << saved_errno << " doing fcntl(" << fd |
| 234 << " doing fcntl(" << fd << ", F_GETFL, 0): " | 232 << ", F_GETFL, 0): " |
| 235 << strerror_r(saved_errno, buf, sizeof(buf)); | 233 << strerror_r(saved_errno, buf, sizeof(buf)); |
| 236 } | 234 } |
| 237 if (!(flags & O_NONBLOCK)) { | 235 if (!(flags & O_NONBLOCK)) { |
| 238 int saved_flags = flags; | 236 int saved_flags = flags; |
| 239 flags = SetFlags(fd, flags | O_NONBLOCK); | 237 flags = SetFlags(fd, flags | O_NONBLOCK); |
| 240 if (flags == -1) { | 238 if (flags == -1) { |
| 241 // bad. | 239 // bad. |
| 242 int saved_errno = errno; | 240 int saved_errno = errno; |
| 243 char buf[kErrorBufferSize]; | 241 char buf[kErrorBufferSize]; |
| 244 LOG(FATAL) << "Error " << saved_errno | 242 LOG(FATAL) << "Error " << saved_errno << " doing fcntl(" << fd |
| 245 << " doing fcntl(" << fd << ", F_SETFL, " << saved_flags << "): " | 243 << ", F_SETFL, " << saved_flags |
| 246 << strerror_r(saved_errno, buf, sizeof(buf)); | 244 << "): " << strerror_r(saved_errno, buf, sizeof(buf)); |
| 247 } | 245 } |
| 248 } | 246 } |
| 249 } | 247 } |
| 250 | 248 |
| 251 int EpollServer::epoll_wait_impl(int epfd, | 249 int EpollServer::epoll_wait_impl(int epfd, |
| 252 struct epoll_event* events, | 250 struct epoll_event* events, |
| 253 int max_events, | 251 int max_events, |
| 254 int timeout_in_ms) { | 252 int timeout_in_ms) { |
| 255 return epoll_wait(epfd, events, max_events, timeout_in_ms); | 253 return epoll_wait(epfd, events, max_events, timeout_in_ms); |
| 256 } | 254 } |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 338 AddToReadyList(cb_and_mask); | 336 AddToReadyList(cb_and_mask); |
| 339 } | 337 } |
| 340 | 338 |
| 341 class TrueFalseGuard { | 339 class TrueFalseGuard { |
| 342 public: | 340 public: |
| 343 explicit TrueFalseGuard(bool* guarded_bool) : guarded_bool_(guarded_bool) { | 341 explicit TrueFalseGuard(bool* guarded_bool) : guarded_bool_(guarded_bool) { |
| 344 DCHECK(guarded_bool_ != NULL); | 342 DCHECK(guarded_bool_ != NULL); |
| 345 DCHECK(*guarded_bool_ == false); | 343 DCHECK(*guarded_bool_ == false); |
| 346 *guarded_bool_ = true; | 344 *guarded_bool_ = true; |
| 347 } | 345 } |
| 348 ~TrueFalseGuard() { | 346 ~TrueFalseGuard() { *guarded_bool_ = false; } |
| 349 *guarded_bool_ = false; | 347 |
| 350 } | |
| 351 private: | 348 private: |
| 352 bool* guarded_bool_; | 349 bool* guarded_bool_; |
| 353 }; | 350 }; |
| 354 | 351 |
| 355 void EpollServer::WaitForEventsAndExecuteCallbacks() { | 352 void EpollServer::WaitForEventsAndExecuteCallbacks() { |
| 356 if (in_wait_for_events_and_execute_callbacks_) { | 353 if (in_wait_for_events_and_execute_callbacks_) { |
| 357 LOG(DFATAL) << | 354 LOG(DFATAL) << "Attempting to call WaitForEventsAndExecuteCallbacks" |
| 358 "Attempting to call WaitForEventsAndExecuteCallbacks" | 355 " when an ancestor to the current function is already" |
| 359 " when an ancestor to the current function is already" | 356 " WaitForEventsAndExecuteCallbacks!"; |
| 360 " WaitForEventsAndExecuteCallbacks!"; | |
| 361 // The line below is actually tested, but in coverage mode, | 357 // The line below is actually tested, but in coverage mode, |
| 362 // we never see it. | 358 // we never see it. |
| 363 return; // COV_NF_LINE | 359 return; // COV_NF_LINE |
| 364 } | 360 } |
| 365 TrueFalseGuard recursion_guard(&in_wait_for_events_and_execute_callbacks_); | 361 TrueFalseGuard recursion_guard(&in_wait_for_events_and_execute_callbacks_); |
| 366 if (alarm_map_.empty()) { | 362 if (alarm_map_.empty()) { |
| 367 // no alarms, this is business as usual. | 363 // no alarms, this is business as usual. |
| 368 WaitForEventsAndCallHandleEvents(timeout_in_us_, | 364 WaitForEventsAndCallHandleEvents(timeout_in_us_, events_, events_size_); |
| 369 events_, | |
| 370 events_size_); | |
| 371 recorded_now_in_us_ = 0; | 365 recorded_now_in_us_ = 0; |
| 372 return; | 366 return; |
| 373 } | 367 } |
| 374 | 368 |
| 375 // store the 'now'. If we recomputed 'now' every iteration | 369 // store the 'now'. If we recomputed 'now' every iteration |
| 376 // down below, then we might never exit that loop-- any | 370 // down below, then we might never exit that loop-- any |
| 377 // long-running alarms might install other long-running | 371 // long-running alarms might install other long-running |
| 378 // alarms, etc. By storing it here now, we ensure that | 372 // alarms, etc. By storing it here now, we ensure that |
| 379 // a more reasonable amount of work is done here. | 373 // a more reasonable amount of work is done here. |
| 380 int64 now_in_us = NowInUsec(); | 374 int64 now_in_us = NowInUsec(); |
| 381 | 375 |
| 382 // Get the first timeout from the alarm_map where it is | 376 // Get the first timeout from the alarm_map where it is |
| 383 // stored in absolute time. | 377 // stored in absolute time. |
| 384 int64 next_alarm_time_in_us = alarm_map_.begin()->first; | 378 int64 next_alarm_time_in_us = alarm_map_.begin()->first; |
| 385 VLOG(4) << "next_alarm_time = " << next_alarm_time_in_us | 379 VLOG(4) << "next_alarm_time = " << next_alarm_time_in_us |
| 386 << " now = " << now_in_us | 380 << " now = " << now_in_us |
| 387 << " timeout_in_us = " << timeout_in_us_; | 381 << " timeout_in_us = " << timeout_in_us_; |
| 388 | 382 |
| 389 int64 wait_time_in_us; | 383 int64 wait_time_in_us; |
| 390 int64 alarm_timeout_in_us = next_alarm_time_in_us - now_in_us; | 384 int64 alarm_timeout_in_us = next_alarm_time_in_us - now_in_us; |
| 391 | 385 |
| 392 // If the next alarm is sooner than the default timeout, or if there is no | 386 // If the next alarm is sooner than the default timeout, or if there is no |
| 393 // timeout (timeout_in_us_ == -1), wake up when the alarm should fire. | 387 // timeout (timeout_in_us_ == -1), wake up when the alarm should fire. |
| 394 // Otherwise use the default timeout. | 388 // Otherwise use the default timeout. |
| 395 if (alarm_timeout_in_us < timeout_in_us_ || timeout_in_us_ < 0) { | 389 if (alarm_timeout_in_us < timeout_in_us_ || timeout_in_us_ < 0) { |
| 396 wait_time_in_us = std::max(alarm_timeout_in_us, static_cast<int64>(0)); | 390 wait_time_in_us = std::max(alarm_timeout_in_us, static_cast<int64>(0)); |
| 397 } else { | 391 } else { |
| 398 wait_time_in_us = timeout_in_us_; | 392 wait_time_in_us = timeout_in_us_; |
| 399 } | 393 } |
| 400 | 394 |
| 401 VLOG(4) << "wait_time_in_us = " << wait_time_in_us; | 395 VLOG(4) << "wait_time_in_us = " << wait_time_in_us; |
| 402 | 396 |
| 403 // wait for events. | 397 // wait for events. |
| 404 | 398 |
| 405 WaitForEventsAndCallHandleEvents(wait_time_in_us, | 399 WaitForEventsAndCallHandleEvents(wait_time_in_us, events_, events_size_); |
| 406 events_, | |
| 407 events_size_); | |
| 408 CallAndReregisterAlarmEvents(); | 400 CallAndReregisterAlarmEvents(); |
| 409 recorded_now_in_us_ = 0; | 401 recorded_now_in_us_ = 0; |
| 410 } | 402 } |
| 411 | 403 |
| 412 void EpollServer::SetFDReady(int fd, int events_to_fake) { | 404 void EpollServer::SetFDReady(int fd, int events_to_fake) { |
| 413 FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); | 405 FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); |
| 414 if (cb_map_.end() != fd_i && fd_i->cb != NULL) { | 406 if (cb_map_.end() != fd_i && fd_i->cb != NULL) { |
| 415 // This const_cast is necessary for LIST_HEAD_INSERT to work. Declaring | 407 // This const_cast is necessary for LIST_HEAD_INSERT to work. Declaring |
| 416 // entry mutable is insufficient because LIST_HEAD_INSERT assigns the | 408 // entry mutable is insufficient because LIST_HEAD_INSERT assigns the |
| 417 // forward pointer of the list head to the current cb_and_mask, and the | 409 // forward pointer of the list head to the current cb_and_mask, and the |
| (...skipping 14 matching lines...) Expand all Loading... |
| 432 | 424 |
| 433 void EpollServer::SetFDNotReady(int fd) { | 425 void EpollServer::SetFDNotReady(int fd) { |
| 434 FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); | 426 FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); |
| 435 if (cb_map_.end() != fd_i) { | 427 if (cb_map_.end() != fd_i) { |
| 436 RemoveFromReadyList(*fd_i); | 428 RemoveFromReadyList(*fd_i); |
| 437 } | 429 } |
| 438 } | 430 } |
| 439 | 431 |
| 440 bool EpollServer::IsFDReady(int fd) const { | 432 bool EpollServer::IsFDReady(int fd) const { |
| 441 FDToCBMap::const_iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); | 433 FDToCBMap::const_iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); |
| 442 return (cb_map_.end() != fd_i && | 434 return (cb_map_.end() != fd_i && fd_i->cb != NULL && |
| 443 fd_i->cb != NULL && | |
| 444 fd_i->entry.le_prev != NULL); | 435 fd_i->entry.le_prev != NULL); |
| 445 } | 436 } |
| 446 | 437 |
| 447 void EpollServer::VerifyReadyList() const { | 438 void EpollServer::VerifyReadyList() const { |
| 448 int count = 0; | 439 int count = 0; |
| 449 CBAndEventMask* cur = ready_list_.lh_first; | 440 CBAndEventMask* cur = ready_list_.lh_first; |
| 450 for (; cur; cur = cur->entry.le_next) { | 441 for (; cur; cur = cur->entry.le_next) { |
| 451 ++count; | 442 ++count; |
| 452 } | 443 } |
| 453 for (cur = tmp_list_.lh_first; cur; cur = cur->entry.le_next) { | 444 for (cur = tmp_list_.lh_first; cur; cur = cur->entry.le_next) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 | 489 |
| 499 int64 EpollServer::ApproximateNowInUsec() const { | 490 int64 EpollServer::ApproximateNowInUsec() const { |
| 500 if (recorded_now_in_us_ != 0) { | 491 if (recorded_now_in_us_ != 0) { |
| 501 return recorded_now_in_us_; | 492 return recorded_now_in_us_; |
| 502 } | 493 } |
| 503 return this->NowInUsec(); | 494 return this->NowInUsec(); |
| 504 } | 495 } |
| 505 | 496 |
| 506 std::string EpollServer::EventMaskToString(int event_mask) { | 497 std::string EpollServer::EventMaskToString(int event_mask) { |
| 507 std::string s; | 498 std::string s; |
| 508 if (event_mask & EPOLLIN) s += "EPOLLIN "; | 499 if (event_mask & EPOLLIN) |
| 509 if (event_mask & EPOLLPRI) s += "EPOLLPRI "; | 500 s += "EPOLLIN "; |
| 510 if (event_mask & EPOLLOUT) s += "EPOLLOUT "; | 501 if (event_mask & EPOLLPRI) |
| 511 if (event_mask & EPOLLRDNORM) s += "EPOLLRDNORM "; | 502 s += "EPOLLPRI "; |
| 512 if (event_mask & EPOLLRDBAND) s += "EPOLLRDBAND "; | 503 if (event_mask & EPOLLOUT) |
| 513 if (event_mask & EPOLLWRNORM) s += "EPOLLWRNORM "; | 504 s += "EPOLLOUT "; |
| 514 if (event_mask & EPOLLWRBAND) s += "EPOLLWRBAND "; | 505 if (event_mask & EPOLLRDNORM) |
| 515 if (event_mask & EPOLLMSG) s += "EPOLLMSG "; | 506 s += "EPOLLRDNORM "; |
| 516 if (event_mask & EPOLLERR) s += "EPOLLERR "; | 507 if (event_mask & EPOLLRDBAND) |
| 517 if (event_mask & EPOLLHUP) s += "EPOLLHUP "; | 508 s += "EPOLLRDBAND "; |
| 518 if (event_mask & EPOLLONESHOT) s += "EPOLLONESHOT "; | 509 if (event_mask & EPOLLWRNORM) |
| 519 if (event_mask & EPOLLET) s += "EPOLLET "; | 510 s += "EPOLLWRNORM "; |
| 511 if (event_mask & EPOLLWRBAND) |
| 512 s += "EPOLLWRBAND "; |
| 513 if (event_mask & EPOLLMSG) |
| 514 s += "EPOLLMSG "; |
| 515 if (event_mask & EPOLLERR) |
| 516 s += "EPOLLERR "; |
| 517 if (event_mask & EPOLLHUP) |
| 518 s += "EPOLLHUP "; |
| 519 if (event_mask & EPOLLONESHOT) |
| 520 s += "EPOLLONESHOT "; |
| 521 if (event_mask & EPOLLET) |
| 522 s += "EPOLLET "; |
| 520 return s; | 523 return s; |
| 521 } | 524 } |
| 522 | 525 |
| 523 void EpollServer::LogStateOnCrash() { | 526 void EpollServer::LogStateOnCrash() { |
| 524 LOG(ERROR) << "----------------------Epoll Server---------------------------"; | 527 LOG(ERROR) << "----------------------Epoll Server---------------------------"; |
| 525 LOG(ERROR) << "Epoll server " << this << " polling on fd " << epoll_fd_; | 528 LOG(ERROR) << "Epoll server " << this << " polling on fd " << epoll_fd_; |
| 526 LOG(ERROR) << "timeout_in_us_: " << timeout_in_us_; | 529 LOG(ERROR) << "timeout_in_us_: " << timeout_in_us_; |
| 527 | 530 |
| 528 // Log sessions with alarms. | 531 // Log sessions with alarms. |
| 529 LOG(ERROR) << alarm_map_.size() << " alarms registered."; | 532 LOG(ERROR) << alarm_map_.size() << " alarms registered."; |
| 530 for (TimeToAlarmCBMap::iterator it = alarm_map_.begin(); | 533 for (TimeToAlarmCBMap::iterator it = alarm_map_.begin(); |
| 531 it != alarm_map_.end(); | 534 it != alarm_map_.end(); |
| 532 ++it) { | 535 ++it) { |
| 533 const bool skipped = | 536 const bool skipped = |
| 534 alarms_reregistered_and_should_be_skipped_.find(it->second) | 537 alarms_reregistered_and_should_be_skipped_.find(it->second) != |
| 535 != alarms_reregistered_and_should_be_skipped_.end(); | 538 alarms_reregistered_and_should_be_skipped_.end(); |
| 536 LOG(ERROR) << "Alarm " << it->second << " registered at time " << it->first | 539 LOG(ERROR) << "Alarm " << it->second << " registered at time " << it->first |
| 537 << " and should be skipped = " << skipped; | 540 << " and should be skipped = " << skipped; |
| 538 } | 541 } |
| 539 | 542 |
| 540 LOG(ERROR) << cb_map_.size() << " fd callbacks registered."; | 543 LOG(ERROR) << cb_map_.size() << " fd callbacks registered."; |
| 541 for (FDToCBMap::iterator it = cb_map_.begin(); | 544 for (FDToCBMap::iterator it = cb_map_.begin(); it != cb_map_.end(); ++it) { |
| 542 it != cb_map_.end(); | |
| 543 ++it) { | |
| 544 LOG(ERROR) << "fd: " << it->fd << " with mask " << it->event_mask | 545 LOG(ERROR) << "fd: " << it->fd << " with mask " << it->event_mask |
| 545 << " registered with cb: " << it->cb; | 546 << " registered with cb: " << it->cb; |
| 546 } | 547 } |
| 547 LOG(ERROR) << "----------------------/Epoll Server--------------------------"; | 548 LOG(ERROR) << "----------------------/Epoll Server--------------------------"; |
| 548 } | 549 } |
| 549 | 550 |
| 550 | |
| 551 | |
| 552 //////////////////////////////////////////////////////////////////////////////// | 551 //////////////////////////////////////////////////////////////////////////////// |
| 553 //////////////////////////////////////////////////////////////////////////////// | 552 //////////////////////////////////////////////////////////////////////////////// |
| 554 | 553 |
| 555 void EpollServer::DelFD(int fd) const { | 554 void EpollServer::DelFD(int fd) const { |
| 556 struct epoll_event ee; | 555 struct epoll_event ee; |
| 557 memset(&ee, 0, sizeof(ee)); | 556 memset(&ee, 0, sizeof(ee)); |
| 558 #ifdef EPOLL_SERVER_EVENT_TRACING | 557 #ifdef EPOLL_SERVER_EVENT_TRACING |
| 559 event_recorder_.RecordFDMaskEvent(fd, 0, "DelFD"); | 558 event_recorder_.RecordFDMaskEvent(fd, 0, "DelFD"); |
| 560 #endif | 559 #endif |
| 561 if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &ee)) { | 560 if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &ee)) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 587 //////////////////////////////////////// | 586 //////////////////////////////////////// |
| 588 | 587 |
| 589 void EpollServer::ModFD(int fd, int event_mask) const { | 588 void EpollServer::ModFD(int fd, int event_mask) const { |
| 590 struct epoll_event ee; | 589 struct epoll_event ee; |
| 591 memset(&ee, 0, sizeof(ee)); | 590 memset(&ee, 0, sizeof(ee)); |
| 592 ee.events = event_mask | EPOLLERR | EPOLLHUP; | 591 ee.events = event_mask | EPOLLERR | EPOLLHUP; |
| 593 ee.data.fd = fd; | 592 ee.data.fd = fd; |
| 594 #ifdef EPOLL_SERVER_EVENT_TRACING | 593 #ifdef EPOLL_SERVER_EVENT_TRACING |
| 595 event_recorder_.RecordFDMaskEvent(fd, ee.events, "ModFD"); | 594 event_recorder_.RecordFDMaskEvent(fd, ee.events, "ModFD"); |
| 596 #endif | 595 #endif |
| 597 VLOG(3) << "modifying fd= " << fd << " " | 596 VLOG(3) << "modifying fd= " << fd << " " << EventMaskToString(ee.events); |
| 598 << EventMaskToString(ee.events); | |
| 599 if (epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &ee)) { | 597 if (epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &ee)) { |
| 600 int saved_errno = errno; | 598 int saved_errno = errno; |
| 601 char buf[kErrorBufferSize]; | 599 char buf[kErrorBufferSize]; |
| 602 LOG(FATAL) << "Epoll set modification error for fd " << fd << ": " | 600 LOG(FATAL) << "Epoll set modification error for fd " << fd << ": " |
| 603 << strerror_r(saved_errno, buf, sizeof(buf)); | 601 << strerror_r(saved_errno, buf, sizeof(buf)); |
| 604 } | 602 } |
| 605 } | 603 } |
| 606 | 604 |
| 607 //////////////////////////////////////// | 605 //////////////////////////////////////// |
| 608 | 606 |
| 609 void EpollServer::ModifyFD(int fd, int remove_event, int add_event) { | 607 void EpollServer::ModifyFD(int fd, int remove_event, int add_event) { |
| 610 FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); | 608 FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); |
| 611 if (cb_map_.end() == fd_i) { | 609 if (cb_map_.end() == fd_i) { |
| 612 VLOG(2) << "Didn't find the fd " << fd << "in internal structures"; | 610 VLOG(2) << "Didn't find the fd " << fd << "in internal structures"; |
| 613 return; | 611 return; |
| 614 } | 612 } |
| 615 | 613 |
| 616 if (fd_i->cb != NULL) { | 614 if (fd_i->cb != NULL) { |
| 617 int & event_mask = fd_i->event_mask; | 615 int& event_mask = fd_i->event_mask; |
| 618 VLOG(3) << "fd= " << fd | 616 VLOG(3) << "fd= " << fd |
| 619 << " event_mask before: " << EventMaskToString(event_mask); | 617 << " event_mask before: " << EventMaskToString(event_mask); |
| 620 event_mask &= ~remove_event; | 618 event_mask &= ~remove_event; |
| 621 event_mask |= add_event; | 619 event_mask |= add_event; |
| 622 | 620 |
| 623 VLOG(3) << " event_mask after: " << EventMaskToString(event_mask); | 621 VLOG(3) << " event_mask after: " << EventMaskToString(event_mask); |
| 624 | 622 |
| 625 ModFD(fd, event_mask); | 623 ModFD(fd, event_mask); |
| 626 | 624 |
| 627 fd_i->cb->OnModification(fd, event_mask); | 625 fd_i->cb->OnModification(fd, event_mask); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 641 // should set timeout_in_us to -1000 so we will | 639 // should set timeout_in_us to -1000 so we will |
| 642 // Wait(-1000/1000) == Wait(-1) == Wait forever. | 640 // Wait(-1000/1000) == Wait(-1) == Wait forever. |
| 643 timeout_in_us = -1000; | 641 timeout_in_us = -1000; |
| 644 } else { | 642 } else { |
| 645 // If timeout is specified, and the ready list is empty. | 643 // If timeout is specified, and the ready list is empty. |
| 646 if (timeout_in_us < 1000) { | 644 if (timeout_in_us < 1000) { |
| 647 timeout_in_us = 1000; | 645 timeout_in_us = 1000; |
| 648 } | 646 } |
| 649 } | 647 } |
| 650 const int timeout_in_ms = timeout_in_us / 1000; | 648 const int timeout_in_ms = timeout_in_us / 1000; |
| 651 int nfds = epoll_wait_impl(epoll_fd_, | 649 int nfds = epoll_wait_impl(epoll_fd_, events, events_size, timeout_in_ms); |
| 652 events, | |
| 653 events_size, | |
| 654 timeout_in_ms); | |
| 655 VLOG(3) << "nfds=" << nfds; | 650 VLOG(3) << "nfds=" << nfds; |
| 656 | 651 |
| 657 #ifdef EPOLL_SERVER_EVENT_TRACING | 652 #ifdef EPOLL_SERVER_EVENT_TRACING |
| 658 event_recorder_.RecordEpollWaitEvent(timeout_in_ms, nfds); | 653 event_recorder_.RecordEpollWaitEvent(timeout_in_ms, nfds); |
| 659 #endif | 654 #endif |
| 660 | 655 |
| 661 // If you're wondering why the NowInUsec() is recorded here, the answer is | 656 // If you're wondering why the NowInUsec() is recorded here, the answer is |
| 662 // simple: If we did it before the epoll_wait_impl, then the max error for | 657 // simple: If we did it before the epoll_wait_impl, then the max error for |
| 663 // the ApproximateNowInUs() call would be as large as the maximum length of | 658 // the ApproximateNowInUs() call would be as large as the maximum length of |
| 664 // epoll_wait, which can be arbitrarily long. Since this would make | 659 // epoll_wait, which can be arbitrarily long. Since this would make |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 if (tmp_list_.lh_first) { | 692 if (tmp_list_.lh_first) { |
| 698 tmp_list_.lh_first->entry.le_prev = &tmp_list_.lh_first; | 693 tmp_list_.lh_first->entry.le_prev = &tmp_list_.lh_first; |
| 699 EpollEvent event(0, false); | 694 EpollEvent event(0, false); |
| 700 while (tmp_list_.lh_first != NULL) { | 695 while (tmp_list_.lh_first != NULL) { |
| 701 DCHECK_GT(ready_list_size_, 0); | 696 DCHECK_GT(ready_list_size_, 0); |
| 702 CBAndEventMask* cb_and_mask = tmp_list_.lh_first; | 697 CBAndEventMask* cb_and_mask = tmp_list_.lh_first; |
| 703 RemoveFromReadyList(*cb_and_mask); | 698 RemoveFromReadyList(*cb_and_mask); |
| 704 | 699 |
| 705 event.out_ready_mask = 0; | 700 event.out_ready_mask = 0; |
| 706 event.in_events = | 701 event.in_events = |
| 707 cb_and_mask->events_asserted | cb_and_mask->events_to_fake; | 702 cb_and_mask->events_asserted | cb_and_mask->events_to_fake; |
| 708 // TODO(fenix): get rid of the two separate fields in cb_and_mask. | 703 // TODO(fenix): get rid of the two separate fields in cb_and_mask. |
| 709 cb_and_mask->events_asserted = 0; | 704 cb_and_mask->events_asserted = 0; |
| 710 cb_and_mask->events_to_fake = 0; | 705 cb_and_mask->events_to_fake = 0; |
| 711 { | 706 { |
| 712 // OnEvent() may call UnRegister, so we set in_use, here. Any | 707 // OnEvent() may call UnRegister, so we set in_use, here. Any |
| 713 // UnRegister call will now simply set the cb to NULL instead of | 708 // UnRegister call will now simply set the cb to NULL instead of |
| 714 // invalidating the cb_and_mask object (by deleting the object in the | 709 // invalidating the cb_and_mask object (by deleting the object in the |
| 715 // map to which cb_and_mask refers) | 710 // map to which cb_and_mask refers) |
| 716 TrueFalseGuard in_use_guard(&(cb_and_mask->in_use)); | 711 TrueFalseGuard in_use_guard(&(cb_and_mask->in_use)); |
| 717 cb_and_mask->cb->OnEvent(cb_and_mask->fd, &event); | 712 cb_and_mask->cb->OnEvent(cb_and_mask->fd, &event); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 732 } | 727 } |
| 733 | 728 |
| 734 void EpollServer::CallAndReregisterAlarmEvents() { | 729 void EpollServer::CallAndReregisterAlarmEvents() { |
| 735 int64 now_in_us = recorded_now_in_us_; | 730 int64 now_in_us = recorded_now_in_us_; |
| 736 DCHECK_NE(0, recorded_now_in_us_); | 731 DCHECK_NE(0, recorded_now_in_us_); |
| 737 | 732 |
| 738 TimeToAlarmCBMap::iterator erase_it; | 733 TimeToAlarmCBMap::iterator erase_it; |
| 739 | 734 |
| 740 // execute alarms. | 735 // execute alarms. |
| 741 for (TimeToAlarmCBMap::iterator i = alarm_map_.begin(); | 736 for (TimeToAlarmCBMap::iterator i = alarm_map_.begin(); |
| 742 i != alarm_map_.end(); | 737 i != alarm_map_.end();) { |
| 743 ) { | |
| 744 if (i->first > now_in_us) { | 738 if (i->first > now_in_us) { |
| 745 break; | 739 break; |
| 746 } | 740 } |
| 747 AlarmCB* cb = i->second; | 741 AlarmCB* cb = i->second; |
| 748 // Execute the OnAlarm() only if we did not register | 742 // Execute the OnAlarm() only if we did not register |
| 749 // it in this loop itself. | 743 // it in this loop itself. |
| 750 const bool added_in_this_round = | 744 const bool added_in_this_round = |
| 751 alarms_reregistered_and_should_be_skipped_.find(cb) | 745 alarms_reregistered_and_should_be_skipped_.find(cb) != |
| 752 != alarms_reregistered_and_should_be_skipped_.end(); | 746 alarms_reregistered_and_should_be_skipped_.end(); |
| 753 if (added_in_this_round) { | 747 if (added_in_this_round) { |
| 754 ++i; | 748 ++i; |
| 755 continue; | 749 continue; |
| 756 } | 750 } |
| 757 all_alarms_.erase(cb); | 751 all_alarms_.erase(cb); |
| 758 const int64 new_timeout_time_in_us = cb->OnAlarm(); | 752 const int64 new_timeout_time_in_us = cb->OnAlarm(); |
| 759 | 753 |
| 760 erase_it = i; | 754 erase_it = i; |
| 761 ++i; | 755 ++i; |
| 762 alarm_map_.erase(erase_it); | 756 alarm_map_.erase(erase_it); |
| 763 | 757 |
| 764 if (new_timeout_time_in_us > 0) { | 758 if (new_timeout_time_in_us > 0) { |
| 765 // We add to hash_set only if the new timeout is <= now_in_us. | 759 // We add to hash_set only if the new timeout is <= now_in_us. |
| 766 // if timeout is > now_in_us then we have no fear that this alarm | 760 // if timeout is > now_in_us then we have no fear that this alarm |
| 767 // can be reexecuted in this loop, and hence we do not need to | 761 // can be reexecuted in this loop, and hence we do not need to |
| 768 // worry about a recursive loop. | 762 // worry about a recursive loop. |
| 769 DVLOG(3) << "Reregistering alarm " | 763 DVLOG(3) << "Reregistering alarm " |
| 770 << " " << cb | 764 << " " << cb << " " << new_timeout_time_in_us << " " |
| 771 << " " << new_timeout_time_in_us | 765 << now_in_us; |
| 772 << " " << now_in_us; | |
| 773 if (new_timeout_time_in_us <= now_in_us) { | 766 if (new_timeout_time_in_us <= now_in_us) { |
| 774 alarms_reregistered_and_should_be_skipped_.insert(cb); | 767 alarms_reregistered_and_should_be_skipped_.insert(cb); |
| 775 } | 768 } |
| 776 RegisterAlarm(new_timeout_time_in_us, cb); | 769 RegisterAlarm(new_timeout_time_in_us, cb); |
| 777 } | 770 } |
| 778 } | 771 } |
| 779 alarms_reregistered_and_should_be_skipped_.clear(); | 772 alarms_reregistered_and_should_be_skipped_.clear(); |
| 780 } | 773 } |
| 781 | 774 |
| 782 EpollAlarm::EpollAlarm() : eps_(NULL), registered_(false) { | 775 EpollAlarm::EpollAlarm() : eps_(NULL), registered_(false) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 811 | 804 |
| 812 // If the alarm was registered, unregister it. | 805 // If the alarm was registered, unregister it. |
| 813 void EpollAlarm::UnregisterIfRegistered() { | 806 void EpollAlarm::UnregisterIfRegistered() { |
| 814 if (!registered_) { | 807 if (!registered_) { |
| 815 return; | 808 return; |
| 816 } | 809 } |
| 817 eps_->UnregisterAlarm(token_); | 810 eps_->UnregisterAlarm(token_); |
| 818 } | 811 } |
| 819 | 812 |
| 820 } // namespace net | 813 } // namespace net |
| OLD | NEW |