| 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 #ifndef NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_ | 5 #ifndef NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_ |
| 6 #define NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_ | 6 #define NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_ |
| 7 | 7 |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <sys/queue.h> | 9 #include <sys/queue.h> |
| 10 #include <map> | 10 #include <map> |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 #include <sys/epoll.h> | 39 #include <sys/epoll.h> |
| 40 | 40 |
| 41 namespace net { | 41 namespace net { |
| 42 | 42 |
| 43 class EpollServer; | 43 class EpollServer; |
| 44 class EpollAlarmCallbackInterface; | 44 class EpollAlarmCallbackInterface; |
| 45 class ReadPipeCallback; | 45 class ReadPipeCallback; |
| 46 | 46 |
| 47 struct EpollEvent { | 47 struct EpollEvent { |
| 48 EpollEvent(int events, bool is_epoll_wait) | 48 EpollEvent(int events, bool is_epoll_wait) |
| 49 : in_events(events), | 49 : in_events(events), out_ready_mask(0) {} |
| 50 out_ready_mask(0) { | |
| 51 } | |
| 52 | 50 |
| 53 int in_events; // incoming events | 51 int in_events; // incoming events |
| 54 int out_ready_mask; // the new event mask for ready list (0 means don't | 52 int out_ready_mask; // the new event mask for ready list (0 means don't |
| 55 // get on the ready list). This field is always | 53 // get on the ready list). This field is always |
| 56 // initialized to 0 when the event is passed to | 54 // initialized to 0 when the event is passed to |
| 57 // OnEvent. | 55 // OnEvent. |
| 58 }; | 56 }; |
| 59 | 57 |
| 60 // Callbacks which go into EpollServers are expected to derive from this class. | 58 // Callbacks which go into EpollServers are expected to derive from this class. |
| 61 class EpollCallbackInterface { | 59 class EpollCallbackInterface { |
| 62 public: | 60 public: |
| 63 // Summary: | 61 // Summary: |
| 64 // Called when the callback is registered into a EpollServer. | 62 // Called when the callback is registered into a EpollServer. |
| 65 // Args: | 63 // Args: |
| 66 // eps - the poll server into which this callback was registered | 64 // eps - the poll server into which this callback was registered |
| 67 // fd - the file descriptor which was registered | 65 // fd - the file descriptor which was registered |
| (...skipping 446 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 514 : cb(NULL), | 512 : cb(NULL), |
| 515 fd(-1), | 513 fd(-1), |
| 516 event_mask(0), | 514 event_mask(0), |
| 517 events_asserted(0), | 515 events_asserted(0), |
| 518 events_to_fake(0), | 516 events_to_fake(0), |
| 519 in_use(false) { | 517 in_use(false) { |
| 520 entry.le_next = NULL; | 518 entry.le_next = NULL; |
| 521 entry.le_prev = NULL; | 519 entry.le_prev = NULL; |
| 522 } | 520 } |
| 523 | 521 |
| 524 CBAndEventMask(EpollCallbackInterface* cb, | 522 CBAndEventMask(EpollCallbackInterface* cb, int event_mask, int fd) |
| 525 int event_mask, | 523 : cb(cb), |
| 526 int fd) | 524 fd(fd), |
| 527 : cb(cb), fd(fd), event_mask(event_mask), events_asserted(0), | 525 event_mask(event_mask), |
| 528 events_to_fake(0), in_use(false) { | 526 events_asserted(0), |
| 527 events_to_fake(0), |
| 528 in_use(false) { |
| 529 entry.le_next = NULL; | 529 entry.le_next = NULL; |
| 530 entry.le_prev = NULL; | 530 entry.le_prev = NULL; |
| 531 } | 531 } |
| 532 | 532 |
| 533 // Required operator for hash_set. Normally operator== should be a free | 533 // Required operator for hash_set. Normally operator== should be a free |
| 534 // standing function. However, since CBAndEventMask is a protected type and | 534 // standing function. However, since CBAndEventMask is a protected type and |
| 535 // it will never be a base class, it makes no difference. | 535 // it will never be a base class, it makes no difference. |
| 536 bool operator==(const CBAndEventMask& cb_and_mask) const { | 536 bool operator==(const CBAndEventMask& cb_and_mask) const { |
| 537 return fd == cb_and_mask.fd; | 537 return fd == cb_and_mask.fd; |
| 538 } | 538 } |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 630 // Waits for events, and calls HandleEvents() for each | 630 // Waits for events, and calls HandleEvents() for each |
| 631 // fd, event pair discovered to possibly have an event. | 631 // fd, event pair discovered to possibly have an event. |
| 632 // Note that a callback (B) may get a spurious event if | 632 // Note that a callback (B) may get a spurious event if |
| 633 // another callback (A) has closed a file-descriptor N, and | 633 // another callback (A) has closed a file-descriptor N, and |
| 634 // the callback (B) has a newly opened file-descriptor, which | 634 // the callback (B) has a newly opened file-descriptor, which |
| 635 // also happens to be N. | 635 // also happens to be N. |
| 636 virtual void WaitForEventsAndCallHandleEvents(int64 timeout_in_us, | 636 virtual void WaitForEventsAndCallHandleEvents(int64 timeout_in_us, |
| 637 struct epoll_event events[], | 637 struct epoll_event events[], |
| 638 int events_size); | 638 int events_size); |
| 639 | 639 |
| 640 | |
| 641 | |
| 642 // Summary: | 640 // Summary: |
| 643 // An internal function for implementing the ready list. It adds a fd's | 641 // An internal function for implementing the ready list. It adds a fd's |
| 644 // CBAndEventMask to the ready list. If the fd is already on the ready | 642 // CBAndEventMask to the ready list. If the fd is already on the ready |
| 645 // list, it is a no-op. | 643 // list, it is a no-op. |
| 646 void AddToReadyList(CBAndEventMask* cb_and_mask); | 644 void AddToReadyList(CBAndEventMask* cb_and_mask); |
| 647 | 645 |
| 648 // Summary: | 646 // Summary: |
| 649 // An internal function for implementing the ready list. It remove a fd's | 647 // An internal function for implementing the ready list. It remove a fd's |
| 650 // CBAndEventMask from the ready list. If the fd is not on the ready list, | 648 // CBAndEventMask from the ready list. If the fd is not on the ready list, |
| 651 // it is a no-op. | 649 // it is a no-op. |
| 652 void RemoveFromReadyList(const CBAndEventMask& cb_and_mask); | 650 void RemoveFromReadyList(const CBAndEventMask& cb_and_mask); |
| 653 | 651 |
| 654 // Summary: | 652 // Summary: |
| 655 // Calls any pending alarms that should go off and reregisters them if they | 653 // Calls any pending alarms that should go off and reregisters them if they |
| 656 // were recurring. | 654 // were recurring. |
| 657 virtual void CallAndReregisterAlarmEvents(); | 655 virtual void CallAndReregisterAlarmEvents(); |
| 658 | 656 |
| 659 // The file-descriptor created for epolling | 657 // The file-descriptor created for epolling |
| 660 int epoll_fd_; | 658 int epoll_fd_; |
| 661 | 659 |
| 662 // The mapping of file-descriptor to CBAndEventMasks | 660 // The mapping of file-descriptor to CBAndEventMasks |
| 663 FDToCBMap cb_map_; | 661 FDToCBMap cb_map_; |
| 664 | 662 |
| 665 // Custom hash function to be used by hash_set. | 663 // Custom hash function to be used by hash_set. |
| 666 struct AlarmCBHash { | 664 struct AlarmCBHash { |
| 667 size_t operator()(AlarmCB*const& p) const { | 665 size_t operator()(AlarmCB* const& p) const { |
| 668 return reinterpret_cast<size_t>(p); | 666 return reinterpret_cast<size_t>(p); |
| 669 } | 667 } |
| 670 }; | 668 }; |
| 671 | 669 |
| 672 | |
| 673 // TOOD(sushantj): Having this hash_set is avoidable. We currently have it | 670 // TOOD(sushantj): Having this hash_set is avoidable. We currently have it |
| 674 // only so that we can enforce stringent checks that a caller can not register | 671 // only so that we can enforce stringent checks that a caller can not register |
| 675 // the same alarm twice. One option is to have an implementation in which | 672 // the same alarm twice. One option is to have an implementation in which |
| 676 // this hash_set is used only in the debug mode. | 673 // this hash_set is used only in the debug mode. |
| 677 typedef base::hash_set<AlarmCB*, AlarmCBHash> AlarmCBMap; | 674 typedef base::hash_set<AlarmCB*, AlarmCBHash> AlarmCBMap; |
| 678 AlarmCBMap all_alarms_; | 675 AlarmCBMap all_alarms_; |
| 679 | 676 |
| 680 TimeToAlarmCBMap alarm_map_; | 677 TimeToAlarmCBMap alarm_map_; |
| 681 | 678 |
| 682 // The amount of time in microseconds that we'll wait before returning | 679 // The amount of time in microseconds that we'll wait before returning |
| (...skipping 24 matching lines...) Expand all Loading... |
| 707 int ready_list_size_; | 704 int ready_list_size_; |
| 708 // TODO(alyssar): make this into something that scales up. | 705 // TODO(alyssar): make this into something that scales up. |
| 709 static const int events_size_ = 256; | 706 static const int events_size_ = 256; |
| 710 struct epoll_event events_[256]; | 707 struct epoll_event events_[256]; |
| 711 | 708 |
| 712 #ifdef EPOLL_SERVER_EVENT_TRACING | 709 #ifdef EPOLL_SERVER_EVENT_TRACING |
| 713 struct EventRecorder { | 710 struct EventRecorder { |
| 714 public: | 711 public: |
| 715 EventRecorder() : num_records_(0), record_threshold_(10000) {} | 712 EventRecorder() : num_records_(0), record_threshold_(10000) {} |
| 716 | 713 |
| 717 ~EventRecorder() { | 714 ~EventRecorder() { Clear(); } |
| 718 Clear(); | |
| 719 } | |
| 720 | 715 |
| 721 // When a number of events equals the record threshold, | 716 // When a number of events equals the record threshold, |
| 722 // the collected data summary for all FDs will be written | 717 // the collected data summary for all FDs will be written |
| 723 // to LOG(INFO). Note that this does not include the | 718 // to LOG(INFO). Note that this does not include the |
| 724 // individual events (if you'reinterested in those, you'll | 719 // individual events (if you'reinterested in those, you'll |
| 725 // have to get at them programmatically). | 720 // have to get at them programmatically). |
| 726 // After any such flushing to LOG(INFO) all events will | 721 // After any such flushing to LOG(INFO) all events will |
| 727 // be cleared. | 722 // be cleared. |
| 728 // Note that the definition of an 'event' is a bit 'hazy', | 723 // Note that the definition of an 'event' is a bit 'hazy', |
| 729 // as it includes the 'Unregistration' event, and perhaps | 724 // as it includes the 'Unregistration' event, and perhaps |
| 730 // others. | 725 // others. |
| 731 void set_record_threshold(int64 new_threshold) { | 726 void set_record_threshold(int64 new_threshold) { |
| 732 record_threshold_ = new_threshold; | 727 record_threshold_ = new_threshold; |
| 733 } | 728 } |
| 734 | 729 |
| 735 void Clear() { | 730 void Clear() { |
| 736 for (int i = 0; i < debug_events_.size(); ++i) { | 731 for (int i = 0; i < debug_events_.size(); ++i) { |
| 737 delete debug_events_[i]; | 732 delete debug_events_[i]; |
| 738 } | 733 } |
| 739 debug_events_.clear(); | 734 debug_events_.clear(); |
| 740 unregistered_fds_.clear(); | 735 unregistered_fds_.clear(); |
| 741 event_counts_.clear(); | 736 event_counts_.clear(); |
| 742 } | 737 } |
| 743 | 738 |
| 744 void MaybeRecordAndClear() { | 739 void MaybeRecordAndClear() { |
| 745 ++num_records_; | 740 ++num_records_; |
| 746 if ((num_records_ > record_threshold_) && | 741 if ((num_records_ > record_threshold_) && (record_threshold_ > 0)) { |
| 747 (record_threshold_ > 0)) { | |
| 748 LOG(INFO) << "\n" << *this; | 742 LOG(INFO) << "\n" << *this; |
| 749 num_records_ = 0; | 743 num_records_ = 0; |
| 750 Clear(); | 744 Clear(); |
| 751 } | 745 } |
| 752 } | 746 } |
| 753 | 747 |
| 754 void RecordFDMaskEvent(int fd, int mask, const char* function) { | 748 void RecordFDMaskEvent(int fd, int mask, const char* function) { |
| 755 FDMaskOutput* fdmo = new FDMaskOutput(fd, mask, function); | 749 FDMaskOutput* fdmo = new FDMaskOutput(fd, mask, function); |
| 756 debug_events_.push_back(fdmo); | 750 debug_events_.push_back(fdmo); |
| 757 MaybeRecordAndClear(); | 751 MaybeRecordAndClear(); |
| 758 } | 752 } |
| 759 | 753 |
| 760 void RecordEpollWaitEvent(int timeout_in_ms, | 754 void RecordEpollWaitEvent(int timeout_in_ms, int num_events_generated) { |
| 761 int num_events_generated) { | 755 EpollWaitOutput* ewo = |
| 762 EpollWaitOutput* ewo = new EpollWaitOutput(timeout_in_ms, | 756 new EpollWaitOutput(timeout_in_ms, num_events_generated); |
| 763 num_events_generated); | |
| 764 debug_events_.push_back(ewo); | 757 debug_events_.push_back(ewo); |
| 765 MaybeRecordAndClear(); | 758 MaybeRecordAndClear(); |
| 766 } | 759 } |
| 767 | 760 |
| 768 void RecordEpollEvent(int fd, int event_mask) { | 761 void RecordEpollEvent(int fd, int event_mask) { |
| 769 Events& events_for_fd = event_counts_[fd]; | 762 Events& events_for_fd = event_counts_[fd]; |
| 770 events_for_fd.AssignFromMask(event_mask); | 763 events_for_fd.AssignFromMask(event_mask); |
| 771 MaybeRecordAndClear(); | 764 MaybeRecordAndClear(); |
| 772 } | 765 } |
| 773 | 766 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 803 friend ostream& operator<<(ostream& os, const DebugOutput& debug_output) { | 796 friend ostream& operator<<(ostream& os, const DebugOutput& debug_output) { |
| 804 debug_output.OutputToStream(os); | 797 debug_output.OutputToStream(os); |
| 805 return os; | 798 return os; |
| 806 } | 799 } |
| 807 virtual void OutputToStream(ostream* os) const = 0; | 800 virtual void OutputToStream(ostream* os) const = 0; |
| 808 virtual ~DebugOutput() {} | 801 virtual ~DebugOutput() {} |
| 809 }; | 802 }; |
| 810 | 803 |
| 811 class FDMaskOutput : public DebugOutput { | 804 class FDMaskOutput : public DebugOutput { |
| 812 public: | 805 public: |
| 813 FDMaskOutput(int fd, int mask, const char* function) : | 806 FDMaskOutput(int fd, int mask, const char* function) |
| 814 fd_(fd), mask_(mask), function_(function) {} | 807 : fd_(fd), mask_(mask), function_(function) {} |
| 815 virtual void OutputToStream(ostream* os) const { | 808 virtual void OutputToStream(ostream* os) const { |
| 816 (*os) << "func: " << function_ | 809 (*os) << "func: " << function_ << "\tfd: " << fd_; |
| 817 << "\tfd: " << fd_; | |
| 818 if (mask_ != 0) { | 810 if (mask_ != 0) { |
| 819 (*os) << "\tmask: " << EventMaskToString(mask_); | 811 (*os) << "\tmask: " << EventMaskToString(mask_); |
| 820 } | 812 } |
| 821 } | 813 } |
| 822 int fd_; | 814 int fd_; |
| 823 int mask_; | 815 int mask_; |
| 824 const char* function_; | 816 const char* function_; |
| 825 }; | 817 }; |
| 826 | 818 |
| 827 class EpollWaitOutput : public DebugOutput { | 819 class EpollWaitOutput : public DebugOutput { |
| 828 public: | 820 public: |
| 829 EpollWaitOutput(int timeout_in_ms, | 821 EpollWaitOutput(int timeout_in_ms, int num_events_generated) |
| 830 int num_events_generated) : | 822 : timeout_in_ms_(timeout_in_ms), |
| 831 timeout_in_ms_(timeout_in_ms), | 823 num_events_generated_(num_events_generated) {} |
| 832 num_events_generated_(num_events_generated) {} | |
| 833 virtual void OutputToStream(ostream* os) const { | 824 virtual void OutputToStream(ostream* os) const { |
| 834 (*os) << "timeout_in_ms: " << timeout_in_ms_ | 825 (*os) << "timeout_in_ms: " << timeout_in_ms_ |
| 835 << "\tnum_events_generated: " << num_events_generated_; | 826 << "\tnum_events_generated: " << num_events_generated_; |
| 836 } | 827 } |
| 828 |
| 837 protected: | 829 protected: |
| 838 int timeout_in_ms_; | 830 int timeout_in_ms_; |
| 839 int num_events_generated_; | 831 int num_events_generated_; |
| 840 }; | 832 }; |
| 841 | 833 |
| 842 struct Events { | 834 struct Events { |
| 843 Events() : | 835 Events() |
| 844 epoll_in(0), | 836 : epoll_in(0), |
| 845 epoll_pri(0), | 837 epoll_pri(0), |
| 846 epoll_out(0), | 838 epoll_out(0), |
| 847 epoll_rdnorm(0), | 839 epoll_rdnorm(0), |
| 848 epoll_rdband(0), | 840 epoll_rdband(0), |
| 849 epoll_wrnorm(0), | 841 epoll_wrnorm(0), |
| 850 epoll_wrband(0), | 842 epoll_wrband(0), |
| 851 epoll_msg(0), | 843 epoll_msg(0), |
| 852 epoll_err(0), | 844 epoll_err(0), |
| 853 epoll_hup(0), | 845 epoll_hup(0), |
| 854 epoll_oneshot(0), | 846 epoll_oneshot(0), |
| 855 epoll_et(0) {} | 847 epoll_et(0) {} |
| 856 | 848 |
| 857 void AssignFromMask(int event_mask) { | 849 void AssignFromMask(int event_mask) { |
| 858 if (event_mask & EPOLLIN) ++epoll_in; | 850 if (event_mask & EPOLLIN) |
| 859 if (event_mask & EPOLLPRI) ++epoll_pri; | 851 ++epoll_in; |
| 860 if (event_mask & EPOLLOUT) ++epoll_out; | 852 if (event_mask & EPOLLPRI) |
| 861 if (event_mask & EPOLLRDNORM) ++epoll_rdnorm; | 853 ++epoll_pri; |
| 862 if (event_mask & EPOLLRDBAND) ++epoll_rdband; | 854 if (event_mask & EPOLLOUT) |
| 863 if (event_mask & EPOLLWRNORM) ++epoll_wrnorm; | 855 ++epoll_out; |
| 864 if (event_mask & EPOLLWRBAND) ++epoll_wrband; | 856 if (event_mask & EPOLLRDNORM) |
| 865 if (event_mask & EPOLLMSG) ++epoll_msg; | 857 ++epoll_rdnorm; |
| 866 if (event_mask & EPOLLERR) ++epoll_err; | 858 if (event_mask & EPOLLRDBAND) |
| 867 if (event_mask & EPOLLHUP) ++epoll_hup; | 859 ++epoll_rdband; |
| 868 if (event_mask & EPOLLONESHOT) ++epoll_oneshot; | 860 if (event_mask & EPOLLWRNORM) |
| 869 if (event_mask & EPOLLET) ++epoll_et; | 861 ++epoll_wrnorm; |
| 862 if (event_mask & EPOLLWRBAND) |
| 863 ++epoll_wrband; |
| 864 if (event_mask & EPOLLMSG) |
| 865 ++epoll_msg; |
| 866 if (event_mask & EPOLLERR) |
| 867 ++epoll_err; |
| 868 if (event_mask & EPOLLHUP) |
| 869 ++epoll_hup; |
| 870 if (event_mask & EPOLLONESHOT) |
| 871 ++epoll_oneshot; |
| 872 if (event_mask & EPOLLET) |
| 873 ++epoll_et; |
| 870 }; | 874 }; |
| 871 | 875 |
| 872 friend ostream& operator<<(ostream& os, const Events& ev) { | 876 friend ostream& operator<<(ostream& os, const Events& ev) { |
| 873 if (ev.epoll_in) { | 877 if (ev.epoll_in) { |
| 874 os << "\t EPOLLIN: " << ev.epoll_in << "\n"; | 878 os << "\t EPOLLIN: " << ev.epoll_in << "\n"; |
| 875 } | 879 } |
| 876 if (ev.epoll_pri) { | 880 if (ev.epoll_pri) { |
| 877 os << "\t EPOLLPRI: " << ev.epoll_pri << "\n"; | 881 os << "\t EPOLLPRI: " << ev.epoll_pri << "\n"; |
| 878 } | 882 } |
| 879 if (ev.epoll_out) { | 883 if (ev.epoll_out) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 924 }; | 928 }; |
| 925 | 929 |
| 926 std::vector<DebugOutput*> debug_events_; | 930 std::vector<DebugOutput*> debug_events_; |
| 927 std::vector<Events> unregistered_fds_; | 931 std::vector<Events> unregistered_fds_; |
| 928 typedef base::hash_map<int, Events> EventCountsMap; | 932 typedef base::hash_map<int, Events> EventCountsMap; |
| 929 EventCountsMap event_counts_; | 933 EventCountsMap event_counts_; |
| 930 int64 num_records_; | 934 int64 num_records_; |
| 931 int64 record_threshold_; | 935 int64 record_threshold_; |
| 932 }; | 936 }; |
| 933 | 937 |
| 934 void ClearEventRecords() { | 938 void ClearEventRecords() { event_recorder_.Clear(); } |
| 935 event_recorder_.Clear(); | 939 void WriteEventRecords(ostream* os) const { (*os) << event_recorder_; } |
| 936 } | |
| 937 void WriteEventRecords(ostream* os) const { | |
| 938 (*os) << event_recorder_; | |
| 939 } | |
| 940 | 940 |
| 941 mutable EventRecorder event_recorder_; | 941 mutable EventRecorder event_recorder_; |
| 942 | 942 |
| 943 #endif | 943 #endif |
| 944 | 944 |
| 945 private: | 945 private: |
| 946 // Helper functions used in the destructor. | 946 // Helper functions used in the destructor. |
| 947 void CleanupFDToCBMap(); | 947 void CleanupFDToCBMap(); |
| 948 void CleanupTimeToAlarmCBMap(); | 948 void CleanupTimeToAlarmCBMap(); |
| 949 | 949 |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1044 | 1044 |
| 1045 private: | 1045 private: |
| 1046 EpollServer::AlarmRegToken token_; | 1046 EpollServer::AlarmRegToken token_; |
| 1047 EpollServer* eps_; | 1047 EpollServer* eps_; |
| 1048 bool registered_; | 1048 bool registered_; |
| 1049 }; | 1049 }; |
| 1050 | 1050 |
| 1051 } // namespace net | 1051 } // namespace net |
| 1052 | 1052 |
| 1053 #endif // NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_ | 1053 #endif // NET_TOOLS_EPOLL_SERVER_EPOLL_SERVER_H_ |
| OLD | NEW |