| 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> |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 events_size_); | 354 events_size_); |
| 355 recorded_now_in_us_ = 0; | 355 recorded_now_in_us_ = 0; |
| 356 return; | 356 return; |
| 357 } | 357 } |
| 358 | 358 |
| 359 // store the 'now'. If we recomputed 'now' every iteration | 359 // store the 'now'. If we recomputed 'now' every iteration |
| 360 // down below, then we might never exit that loop-- any | 360 // down below, then we might never exit that loop-- any |
| 361 // long-running alarms might install other long-running | 361 // long-running alarms might install other long-running |
| 362 // alarms, etc. By storing it here now, we ensure that | 362 // alarms, etc. By storing it here now, we ensure that |
| 363 // a more reasonable amount of work is done here. | 363 // a more reasonable amount of work is done here. |
| 364 int64 now_in_us = NowInUsec(); | 364 int64_t now_in_us = NowInUsec(); |
| 365 | 365 |
| 366 // Get the first timeout from the alarm_map where it is | 366 // Get the first timeout from the alarm_map where it is |
| 367 // stored in absolute time. | 367 // stored in absolute time. |
| 368 int64 next_alarm_time_in_us = alarm_map_.begin()->first; | 368 int64_t next_alarm_time_in_us = alarm_map_.begin()->first; |
| 369 VLOG(4) << "next_alarm_time = " << next_alarm_time_in_us | 369 VLOG(4) << "next_alarm_time = " << next_alarm_time_in_us |
| 370 << " now = " << now_in_us | 370 << " now = " << now_in_us |
| 371 << " timeout_in_us = " << timeout_in_us_; | 371 << " timeout_in_us = " << timeout_in_us_; |
| 372 | 372 |
| 373 int64 wait_time_in_us; | 373 int64_t wait_time_in_us; |
| 374 int64 alarm_timeout_in_us = next_alarm_time_in_us - now_in_us; | 374 int64_t alarm_timeout_in_us = next_alarm_time_in_us - now_in_us; |
| 375 | 375 |
| 376 // If the next alarm is sooner than the default timeout, or if there is no | 376 // If the next alarm is sooner than the default timeout, or if there is no |
| 377 // timeout (timeout_in_us_ == -1), wake up when the alarm should fire. | 377 // timeout (timeout_in_us_ == -1), wake up when the alarm should fire. |
| 378 // Otherwise use the default timeout. | 378 // Otherwise use the default timeout. |
| 379 if (alarm_timeout_in_us < timeout_in_us_ || timeout_in_us_ < 0) { | 379 if (alarm_timeout_in_us < timeout_in_us_ || timeout_in_us_ < 0) { |
| 380 wait_time_in_us = std::max(alarm_timeout_in_us, static_cast<int64>(0)); | 380 wait_time_in_us = std::max(alarm_timeout_in_us, static_cast<int64_t>(0)); |
| 381 } else { | 381 } else { |
| 382 wait_time_in_us = timeout_in_us_; | 382 wait_time_in_us = timeout_in_us_; |
| 383 } | 383 } |
| 384 | 384 |
| 385 VLOG(4) << "wait_time_in_us = " << wait_time_in_us; | 385 VLOG(4) << "wait_time_in_us = " << wait_time_in_us; |
| 386 | 386 |
| 387 // wait for events. | 387 // wait for events. |
| 388 | 388 |
| 389 WaitForEventsAndCallHandleEvents(wait_time_in_us, | 389 WaitForEventsAndCallHandleEvents(wait_time_in_us, |
| 390 events_, | 390 events_, |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 CBAndEventMask* cur = ready_list_.lh_first; | 433 CBAndEventMask* cur = ready_list_.lh_first; |
| 434 for (; cur; cur = cur->entry.le_next) { | 434 for (; cur; cur = cur->entry.le_next) { |
| 435 ++count; | 435 ++count; |
| 436 } | 436 } |
| 437 for (cur = tmp_list_.lh_first; cur; cur = cur->entry.le_next) { | 437 for (cur = tmp_list_.lh_first; cur; cur = cur->entry.le_next) { |
| 438 ++count; | 438 ++count; |
| 439 } | 439 } |
| 440 CHECK_EQ(ready_list_size_, count) << "Ready list size does not match count"; | 440 CHECK_EQ(ready_list_size_, count) << "Ready list size does not match count"; |
| 441 } | 441 } |
| 442 | 442 |
| 443 void EpollServer::RegisterAlarm(int64 timeout_time_in_us, AlarmCB* ac) { | 443 void EpollServer::RegisterAlarm(int64_t timeout_time_in_us, AlarmCB* ac) { |
| 444 CHECK(ac); | 444 CHECK(ac); |
| 445 if (ContainsKey(all_alarms_, ac)) { | 445 if (ContainsKey(all_alarms_, ac)) { |
| 446 LOG(FATAL) << "Alarm already exists " << ac; | 446 LOG(FATAL) << "Alarm already exists " << ac; |
| 447 } | 447 } |
| 448 VLOG(4) << "RegisteringAlarm at : " << timeout_time_in_us; | 448 VLOG(4) << "RegisteringAlarm at : " << timeout_time_in_us; |
| 449 | 449 |
| 450 TimeToAlarmCBMap::iterator alarm_iter = | 450 TimeToAlarmCBMap::iterator alarm_iter = |
| 451 alarm_map_.insert(std::make_pair(timeout_time_in_us, ac)); | 451 alarm_map_.insert(std::make_pair(timeout_time_in_us, ac)); |
| 452 | 452 |
| 453 all_alarms_.insert(ac); | 453 all_alarms_.insert(ac); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 469 // Omit the internal FD (read_fd_) | 469 // Omit the internal FD (read_fd_) |
| 470 return cb_map_.size() - 1; | 470 return cb_map_.size() - 1; |
| 471 } | 471 } |
| 472 | 472 |
| 473 void EpollServer::Wake() { | 473 void EpollServer::Wake() { |
| 474 char data = 'd'; // 'd' is for data. It's good enough for me. | 474 char data = 'd'; // 'd' is for data. It's good enough for me. |
| 475 int rv = write(write_fd_, &data, 1); | 475 int rv = write(write_fd_, &data, 1); |
| 476 DCHECK_EQ(rv, 1); | 476 DCHECK_EQ(rv, 1); |
| 477 } | 477 } |
| 478 | 478 |
| 479 int64 EpollServer::NowInUsec() const { | 479 int64_t EpollServer::NowInUsec() const { |
| 480 return (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds(); | 480 return (base::Time::Now() - base::Time::UnixEpoch()).InMicroseconds(); |
| 481 } | 481 } |
| 482 | 482 |
| 483 int64 EpollServer::ApproximateNowInUsec() const { | 483 int64_t EpollServer::ApproximateNowInUsec() const { |
| 484 if (recorded_now_in_us_ != 0) { | 484 if (recorded_now_in_us_ != 0) { |
| 485 return recorded_now_in_us_; | 485 return recorded_now_in_us_; |
| 486 } | 486 } |
| 487 return this->NowInUsec(); | 487 return this->NowInUsec(); |
| 488 } | 488 } |
| 489 | 489 |
| 490 std::string EpollServer::EventMaskToString(int event_mask) { | 490 std::string EpollServer::EventMaskToString(int event_mask) { |
| 491 std::string s; | 491 std::string s; |
| 492 if (event_mask & EPOLLIN) s += "EPOLLIN "; | 492 if (event_mask & EPOLLIN) s += "EPOLLIN "; |
| 493 if (event_mask & EPOLLPRI) s += "EPOLLPRI "; | 493 if (event_mask & EPOLLPRI) s += "EPOLLPRI "; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 event_mask |= add_event; | 605 event_mask |= add_event; |
| 606 | 606 |
| 607 VLOG(3) << " event_mask after: " << EventMaskToString(event_mask); | 607 VLOG(3) << " event_mask after: " << EventMaskToString(event_mask); |
| 608 | 608 |
| 609 ModFD(fd, event_mask); | 609 ModFD(fd, event_mask); |
| 610 | 610 |
| 611 fd_i->cb->OnModification(fd, event_mask); | 611 fd_i->cb->OnModification(fd, event_mask); |
| 612 } | 612 } |
| 613 } | 613 } |
| 614 | 614 |
| 615 void EpollServer::WaitForEventsAndCallHandleEvents(int64 timeout_in_us, | 615 void EpollServer::WaitForEventsAndCallHandleEvents(int64_t timeout_in_us, |
| 616 struct epoll_event events[], | 616 struct epoll_event events[], |
| 617 int events_size) { | 617 int events_size) { |
| 618 if (timeout_in_us == 0 || ready_list_.lh_first != NULL) { | 618 if (timeout_in_us == 0 || ready_list_.lh_first != NULL) { |
| 619 // If ready list is not empty, then don't sleep at all. | 619 // If ready list is not empty, then don't sleep at all. |
| 620 timeout_in_us = 0; | 620 timeout_in_us = 0; |
| 621 } else if (timeout_in_us < 0) { | 621 } else if (timeout_in_us < 0) { |
| 622 LOG(INFO) << "Negative epoll timeout: " << timeout_in_us | 622 LOG(INFO) << "Negative epoll timeout: " << timeout_in_us |
| 623 << "us; epoll will wait forever for events."; | 623 << "us; epoll will wait forever for events."; |
| 624 // If timeout_in_us is < 0 we are supposed to Wait forever. This means we | 624 // If timeout_in_us is < 0 we are supposed to Wait forever. This means we |
| 625 // should set timeout_in_us to -1000 so we will | 625 // should set timeout_in_us to -1000 so we will |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 709 } else if (event.out_ready_mask != 0) { | 709 } else if (event.out_ready_mask != 0) { |
| 710 cb_and_mask->events_to_fake = event.out_ready_mask; | 710 cb_and_mask->events_to_fake = event.out_ready_mask; |
| 711 AddToReadyList(cb_and_mask); | 711 AddToReadyList(cb_and_mask); |
| 712 } | 712 } |
| 713 } | 713 } |
| 714 } | 714 } |
| 715 DCHECK(tmp_list_.lh_first == NULL); | 715 DCHECK(tmp_list_.lh_first == NULL); |
| 716 } | 716 } |
| 717 | 717 |
| 718 void EpollServer::CallAndReregisterAlarmEvents() { | 718 void EpollServer::CallAndReregisterAlarmEvents() { |
| 719 int64 now_in_us = recorded_now_in_us_; | 719 int64_t now_in_us = recorded_now_in_us_; |
| 720 DCHECK_NE(0, recorded_now_in_us_); | 720 DCHECK_NE(0, recorded_now_in_us_); |
| 721 | 721 |
| 722 TimeToAlarmCBMap::iterator erase_it; | 722 TimeToAlarmCBMap::iterator erase_it; |
| 723 | 723 |
| 724 // execute alarms. | 724 // execute alarms. |
| 725 for (TimeToAlarmCBMap::iterator i = alarm_map_.begin(); | 725 for (TimeToAlarmCBMap::iterator i = alarm_map_.begin(); |
| 726 i != alarm_map_.end(); | 726 i != alarm_map_.end(); |
| 727 ) { | 727 ) { |
| 728 if (i->first > now_in_us) { | 728 if (i->first > now_in_us) { |
| 729 break; | 729 break; |
| 730 } | 730 } |
| 731 AlarmCB* cb = i->second; | 731 AlarmCB* cb = i->second; |
| 732 // Execute the OnAlarm() only if we did not register | 732 // Execute the OnAlarm() only if we did not register |
| 733 // it in this loop itself. | 733 // it in this loop itself. |
| 734 const bool added_in_this_round = | 734 const bool added_in_this_round = |
| 735 alarms_reregistered_and_should_be_skipped_.find(cb) | 735 alarms_reregistered_and_should_be_skipped_.find(cb) |
| 736 != alarms_reregistered_and_should_be_skipped_.end(); | 736 != alarms_reregistered_and_should_be_skipped_.end(); |
| 737 if (added_in_this_round) { | 737 if (added_in_this_round) { |
| 738 ++i; | 738 ++i; |
| 739 continue; | 739 continue; |
| 740 } | 740 } |
| 741 all_alarms_.erase(cb); | 741 all_alarms_.erase(cb); |
| 742 const int64 new_timeout_time_in_us = cb->OnAlarm(); | 742 const int64_t new_timeout_time_in_us = cb->OnAlarm(); |
| 743 | 743 |
| 744 erase_it = i; | 744 erase_it = i; |
| 745 ++i; | 745 ++i; |
| 746 alarm_map_.erase(erase_it); | 746 alarm_map_.erase(erase_it); |
| 747 | 747 |
| 748 if (new_timeout_time_in_us > 0) { | 748 if (new_timeout_time_in_us > 0) { |
| 749 // We add to hash_set only if the new timeout is <= now_in_us. | 749 // We add to hash_set only if the new timeout is <= now_in_us. |
| 750 // if timeout is > now_in_us then we have no fear that this alarm | 750 // if timeout is > now_in_us then we have no fear that this alarm |
| 751 // can be reexecuted in this loop, and hence we do not need to | 751 // can be reexecuted in this loop, and hence we do not need to |
| 752 // worry about a recursive loop. | 752 // worry about a recursive loop. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 763 alarms_reregistered_and_should_be_skipped_.clear(); | 763 alarms_reregistered_and_should_be_skipped_.clear(); |
| 764 } | 764 } |
| 765 | 765 |
| 766 EpollAlarm::EpollAlarm() : eps_(NULL), registered_(false) { | 766 EpollAlarm::EpollAlarm() : eps_(NULL), registered_(false) { |
| 767 } | 767 } |
| 768 | 768 |
| 769 EpollAlarm::~EpollAlarm() { | 769 EpollAlarm::~EpollAlarm() { |
| 770 UnregisterIfRegistered(); | 770 UnregisterIfRegistered(); |
| 771 } | 771 } |
| 772 | 772 |
| 773 int64 EpollAlarm::OnAlarm() { | 773 int64_t EpollAlarm::OnAlarm() { |
| 774 registered_ = false; | 774 registered_ = false; |
| 775 return 0; | 775 return 0; |
| 776 } | 776 } |
| 777 | 777 |
| 778 void EpollAlarm::OnRegistration(const EpollServer::AlarmRegToken& token, | 778 void EpollAlarm::OnRegistration(const EpollServer::AlarmRegToken& token, |
| 779 EpollServer* eps) { | 779 EpollServer* eps) { |
| 780 DCHECK_EQ(false, registered_); | 780 DCHECK_EQ(false, registered_); |
| 781 | 781 |
| 782 token_ = token; | 782 token_ = token; |
| 783 eps_ = eps; | 783 eps_ = eps; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 795 | 795 |
| 796 // If the alarm was registered, unregister it. | 796 // If the alarm was registered, unregister it. |
| 797 void EpollAlarm::UnregisterIfRegistered() { | 797 void EpollAlarm::UnregisterIfRegistered() { |
| 798 if (!registered_) { | 798 if (!registered_) { |
| 799 return; | 799 return; |
| 800 } | 800 } |
| 801 eps_->UnregisterAlarm(token_); | 801 eps_->UnregisterAlarm(token_); |
| 802 } | 802 } |
| 803 | 803 |
| 804 } // namespace net | 804 } // namespace net |
| OLD | NEW |