1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/tools/flip_server/epoll_server.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <stdlib.h> // for abort 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <errno.h> // for errno and strerror_r 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <algorithm> 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <iostream> 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <utility> 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <vector> 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/timer.h" 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Design notes: An efficient implementation of ready list has the following 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// desirable properties: 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// A. O(1) insertion into/removal from the list in any location. 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// B. Once the callback is found by hash lookup using the fd, the lookup of 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// corresponding entry in the list is O(1). 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// C. Safe insertion into/removal from the list during list iteration. (The 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ready list's purpose is to enable completely event driven I/O model. 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Thus, all the interesting bits happen in the callback. It is critical 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// to not place any restriction on the API during list iteration. 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The current implementation achieves these goals with the following design: 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - The ready list is constructed as a doubly linked list to enable O(1) 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// insertion/removal (see man 3 queue). 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - The forward and backward links are directly embedded inside the 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// CBAndEventMask struct. This enables O(1) lookup in the list for a given 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// callback. (Techincally, we could've used std::list of hash_set::iterator, 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and keep a list::iterator in CBAndEventMask to achieve the same effect. 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// However, iterators have two problems: no way to portably invalidate them, 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and no way to tell whether an iterator is singular or not. The only way to 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// overcome these issues is to keep bools in both places, but that throws off 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// memory alignment (up to 7 wasted bytes for each bool). The extra level of 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// indirection will also likely be less cache friendly. Direct manipulation 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// of link pointers makes it easier to retrieve the CBAndEventMask from the 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// list, easier to check whether an CBAndEventMask is in the list, uses less 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// memory (save 32 bytes/fd), and does not affect cache usage (we need to 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// read in the struct to use the callback anyway).) 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - Embed the fd directly into CBAndEventMask and switch to using hash_set. 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This removes the need to store hash_map::iterator in the list just so that 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// we can get both the fd and the callback. 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - The ready list is "one shot": each entry is removed before OnEvent is 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// called. This removes the mutation-while-iterating problem. 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// - Use two lists to keep track of callbacks. The ready_list_ is the one used 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// for registration. Before iteration, the ready_list_ is swapped into the 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// tmp_list_. Once iteration is done, tmp_list_ will be empty, and 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ready_list_ will have all the new ready fds. 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The size we use for buffers passed to strerror_r 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const int kErrorBufferSize = 256; 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Clears the pipe and returns. Used for waking the epoll server up. 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ReadPipeCallback : public EpollCallbackInterface { 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void OnEvent(int fd, EpollEvent* event) { 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(event->in_events == EPOLLIN); 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int data; 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int data_read = 1; 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Read until the pipe is empty. 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (data_read > 0) { 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott data_read = read(fd, &data, sizeof(data)); 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void OnShutdown(EpollServer *eps, int fd) {} 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void OnRegistration(EpollServer*, int, int) {} 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void OnModification(int, int) {} // COV_NF_LINE 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void OnUnregistration(int, bool) {} // COV_NF_LINE 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEpollServer::EpollServer() 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : epoll_fd_(epoll_create(1024)), 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott timeout_in_us_(0), 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott recorded_now_in_us_(0), 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ready_list_size_(0), 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott wake_cb_(new ReadPipeCallback), 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_fd_(-1), 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_fd_(-1), 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott in_wait_for_events_and_execute_callbacks_(false), 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott in_shutdown_(false) { 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // ensure that the epoll_fd_ is valid. 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECK_NE(epoll_fd_, -1); 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LIST_INIT(&ready_list_); 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LIST_INIT(&tmp_list_); 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int pipe_fds[2]; 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (pipe(pipe_fds) < 0) { 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Unfortunately, it is impossible to test any such initialization in 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // a constructor (as virtual methods do not yet work). 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This -could- be solved by moving initialization to an outside 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // call... 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int saved_errno = errno; 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char buf[kErrorBufferSize]; 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "Error " << saved_errno 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " in pipe(): " << strerror_r(saved_errno, buf, sizeof(buf)); 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott read_fd_ = pipe_fds[0]; 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott write_fd_ = pipe_fds[1]; 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RegisterFD(read_fd_, wake_cb_.get(), EPOLLIN); 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::CleanupFDToCBMap() { 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FDToCBMap::iterator cb_iter = cb_map_.begin(); 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (cb_iter != cb_map_.end()) { 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int fd = cb_iter->fd; 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CB* cb = cb_iter->cb; 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb_iter->in_use = true; 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cb) { 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb->OnShutdown(this, fd); 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb_map_.erase(cb_iter); 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb_iter = cb_map_.begin(); 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::CleanupTimeToAlarmCBMap() { 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TimeToAlarmCBMap::iterator erase_it; 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Call OnShutdown() on alarms. Note that the structure of the loop 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // is similar to the structure of loop in the function HandleAlarms() 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (TimeToAlarmCBMap::iterator i = alarm_map_.begin(); 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i != alarm_map_.end(); 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ) { 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note that OnShutdown() can call UnregisterAlarm() on 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // other iterators. OnShutdown() should not call UnregisterAlarm() 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // on self because by definition the iterator is not valid any more. 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i->second->OnShutdown(this); 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott erase_it = i; 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++i; 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott alarm_map_.erase(erase_it); 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEpollServer::~EpollServer() { 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(in_shutdown_, false); 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott in_shutdown_ = true; 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef EPOLL_SERVER_EVENT_TRACING 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(INFO) << "\n" << event_recorder_; 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Shutting down epoll server "; 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CleanupFDToCBMap(); 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LIST_INIT(&ready_list_); 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LIST_INIT(&tmp_list_); 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CleanupTimeToAlarmCBMap(); 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott close(read_fd_); 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott close(write_fd_); 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott close(epoll_fd_); 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Whether a CBAandEventMask is on the ready list is determined by a non-NULL 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// le_prev pointer (le_next being NULL indicates end of list). 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline void EpollServer::AddToReadyList(CBAndEventMask* cb_and_mask) { 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cb_and_mask->entry.le_prev == NULL) { 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LIST_INSERT_HEAD(&ready_list_, cb_and_mask, entry); 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++ready_list_size_; 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline void EpollServer::RemoveFromReadyList( 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const CBAndEventMask& cb_and_mask) { 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cb_and_mask.entry.le_prev != NULL) { 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LIST_REMOVE(&cb_and_mask, entry); 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Clean up all the ready list states. Don't bother with the other fields 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // as they are initialized when the CBAandEventMask is added to the ready 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // list. This saves a few cycles in the inner loop. 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb_and_mask.entry.le_prev = NULL; 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott --ready_list_size_; 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ready_list_size_ == 0) { 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(ready_list_.lh_first == NULL); 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(tmp_list_.lh_first == NULL); 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::RegisterFD(int fd, CB* cb, int event_mask) { 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECK(cb); 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(3) << "RegisterFD fd=" << fd << " event_mask=" << event_mask; 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cb_map_.end() != fd_i) { 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // do we just abort, or do we just unregister the other guy? 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // for now, lets just unregister the other guy. 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // unregister any callback that may already be registered for this FD. 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CB* other_cb = fd_i->cb; 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (other_cb) { 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Must remove from the ready list before erasing. 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RemoveFromReadyList(*fd_i); 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott other_cb->OnUnregistration(fd, true); 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ModFD(fd, event_mask); 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // already unregistered, so just recycle the node. 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddFD(fd, event_mask); 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd_i->cb = cb; 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd_i->event_mask = event_mask; 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd_i->events_to_fake = 0; 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddFD(fd, event_mask); 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb_map_.insert(CBAndEventMask(cb, event_mask, fd)); 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // set the FD to be non-blocking. 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetNonblocking(fd); 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb->OnRegistration(this, fd, event_mask); 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 22472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint EpollServer::GetFlags(int fd) { 22572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return fcntl(fd, F_GETFL, 0); 22672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 22772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::SetNonblocking(int fd) { 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int flags = GetFlags(fd); 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (flags == -1) { 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int saved_errno = errno; 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char buf[kErrorBufferSize]; 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "Error " << saved_errno 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " doing fcntl(" << fd << ", F_GETFL, 0): " 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << strerror_r(saved_errno, buf, sizeof(buf)); 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!(flags & O_NONBLOCK)) { 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int saved_flags = flags; 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott flags = SetFlags(fd, flags | O_NONBLOCK); 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (flags == -1) { 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // bad. 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int saved_errno = errno; 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char buf[kErrorBufferSize]; 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "Error " << saved_errno 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " doing fcntl(" << fd << ", F_SETFL, " << saved_flags << "): " 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << strerror_r(saved_errno, buf, sizeof(buf)); 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 25172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint EpollServer::epoll_wait_impl(int epfd, 25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen struct epoll_event* events, 25372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int max_events, 25472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int timeout_in_ms) { 25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return epoll_wait(epfd, events, max_events, timeout_in_ms); 25672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::RegisterFDForWrite(int fd, CB* cb) { 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RegisterFD(fd, cb, EPOLLOUT); 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::RegisterFDForReadWrite(int fd, CB* cb) { 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RegisterFD(fd, cb, EPOLLIN | EPOLLOUT); 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::RegisterFDForRead(int fd, CB* cb) { 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RegisterFD(fd, cb, EPOLLIN); 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::UnregisterFD(int fd) { 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cb_map_.end() == fd_i || fd_i->cb == NULL) { 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Doesn't exist in server, or has gone through UnregisterFD once and still 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // inside the callchain of OnEvent. 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef EPOLL_SERVER_EVENT_TRACING 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_recorder_.RecordUnregistration(fd); 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CB* cb = fd_i->cb; 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Since the links are embedded within the struct, we must remove it from the 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // list before erasing it from the hash_set. 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RemoveFromReadyList(*fd_i); 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DelFD(fd); 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb->OnUnregistration(fd, false); 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // fd_i->cb is NULL if that fd is unregistered inside the callchain of 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // OnEvent. Since the EpollServer needs a valid CBAndEventMask after OnEvent 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // returns in order to add it to the ready list, we cannot have UnregisterFD 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // erase the entry if it is in use. Thus, a NULL fd_i->cb is used as a 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // condition that tells the EpollServer that this entry is unused at a later 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // point. 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!fd_i->in_use) { 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb_map_.erase(fd_i); 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Remove all trace of the registration, and just keep the node alive long 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // enough so the code that calls OnEvent doesn't have to worry about 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // figuring out whether the CBAndEventMask is valid or not. 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd_i->cb = NULL; 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd_i->event_mask = 0; 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd_i->events_to_fake = 0; 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::ModifyCallback(int fd, int event_mask) { 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ModifyFD(fd, ~0, event_mask); 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::StopRead(int fd) { 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ModifyFD(fd, EPOLLIN, 0); 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::StartRead(int fd) { 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ModifyFD(fd, 0, EPOLLIN); 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::StopWrite(int fd) { 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ModifyFD(fd, EPOLLOUT, 0); 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::StartWrite(int fd) { 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ModifyFD(fd, 0, EPOLLOUT); 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::HandleEvent(int fd, int event_mask) { 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef EPOLL_SERVER_EVENT_TRACING 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_recorder_.RecordEpollEvent(fd, event_mask); 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fd_i == cb_map_.end() || fd_i->cb == NULL) { 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Ignore the event. 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This could occur if epoll() returns a set of events, and 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // while processing event A (earlier) we removed the callback 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // for event B (and are now processing event B). 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd_i->events_asserted = event_mask; 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CBAndEventMask* cb_and_mask = const_cast<CBAndEventMask*>(&*fd_i); 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddToReadyList(cb_and_mask); 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass TrueFalseGuard { 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit TrueFalseGuard(bool* guarded_bool) : guarded_bool_(guarded_bool) { 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(guarded_bool_ != NULL); 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(*guarded_bool_ == false); 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *guarded_bool_ = true; 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~TrueFalseGuard() { 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *guarded_bool_ = false; 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool* guarded_bool_; 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::WaitForEventsAndExecuteCallbacks() { 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (in_wait_for_events_and_execute_callbacks_) { 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(DFATAL) << 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "Attempting to call WaitForEventsAndExecuteCallbacks" 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " when an ancestor to the current function is already" 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott " WaitForEventsAndExecuteCallbacks!"; 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The line below is actually tested, but in coverage mode, 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // we never see it. 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; // COV_NF_LINE 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TrueFalseGuard recursion_guard(&in_wait_for_events_and_execute_callbacks_); 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (alarm_map_.empty()) { 367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // no alarms, this is business as usual. 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WaitForEventsAndCallHandleEvents(timeout_in_us_, 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_, 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_size_); 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott recorded_now_in_us_ = 0; 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // store the 'now'. If we recomputed 'now' every iteration 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // down below, then we might never exit that loop-- any 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // long-running alarms might install other long-running 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // alarms, etc. By storing it here now, we ensure that 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // a more reasonable amount of work is done here. 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64 now_in_us = NowInUsec(); 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Get the first timeout from the alarm_map where it is 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // stored in absolute time. 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64 next_alarm_time_in_us = alarm_map_.begin()->first; 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(4) << "next_alarm_time = " << next_alarm_time_in_us 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " now = " << now_in_us 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " timeout_in_us = " << timeout_in_us_; 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64 wait_time_in_us; 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64 alarm_timeout_in_us = next_alarm_time_in_us - now_in_us; 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the next alarm is sooner than the default timeout, or if there is no 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // timeout (timeout_in_us_ == -1), wake up when the alarm should fire. 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Otherwise use the default timeout. 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (alarm_timeout_in_us < timeout_in_us_ || timeout_in_us_ < 0) { 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott wait_time_in_us = std::max(alarm_timeout_in_us, static_cast<int64>(0)); 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott wait_time_in_us = timeout_in_us_; 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(4) << "wait_time_in_us = " << wait_time_in_us; 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // wait for events. 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott WaitForEventsAndCallHandleEvents(wait_time_in_us, 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_, 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_size_); 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CallAndReregisterAlarmEvents(); 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott recorded_now_in_us_ = 0; 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::SetFDReady(int fd, int events_to_fake) { 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cb_map_.end() != fd_i && fd_i->cb != NULL) { 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // This const_cast is necessary for LIST_HEAD_INSERT to work. Declaring 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // entry mutable is insufficient because LIST_HEAD_INSERT assigns the 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // forward pointer of the list head to the current cb_and_mask, and the 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // compiler complains that it can't assign a const T* to a T*. 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CBAndEventMask* cb_and_mask = const_cast<CBAndEventMask*>(&*fd_i); 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note that there is no clearly correct behavior here when 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // cb_and_mask->events_to_fake != 0 and this function is called. 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Of the two operations: 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // cb_and_mask->events_to_fake = events_to_fake 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // cb_and_mask->events_to_fake |= events_to_fake 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the first was picked because it discourages users from calling 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // SetFDReady repeatedly to build up the correct event set as it is more 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // efficient to call SetFDReady once with the correct, final mask. 428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb_and_mask->events_to_fake = events_to_fake; 429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddToReadyList(cb_and_mask); 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::SetFDNotReady(int fd) { 434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cb_map_.end() != fd_i) { 436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RemoveFromReadyList(*fd_i); 437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool EpollServer::IsFDReady(int fd) const { 441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FDToCBMap::const_iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); 442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (cb_map_.end() != fd_i && 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd_i->cb != NULL && 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd_i->entry.le_prev != NULL); 445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::VerifyReadyList() const { 448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int count = 0; 449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CBAndEventMask* cur = ready_list_.lh_first; 450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (; cur; cur = cur->entry.le_next) { 451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++count; 452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (cur = tmp_list_.lh_first; cur; cur = cur->entry.le_next) { 454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++count; 455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECK_EQ(ready_list_size_, count) << "Ready list size does not match count"; 457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::RegisterAlarm(int64 timeout_time_in_us, AlarmCB* ac) { 460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CHECK(ac); 461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ContainsAlarm(ac)) { 462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "Alarm already exists " << ac; 463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(4) << "RegisteringAlarm at : " << timeout_time_in_us; 465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TimeToAlarmCBMap::iterator alarm_iter = 467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott alarm_map_.insert(std::make_pair(timeout_time_in_us, ac)); 468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott all_alarms_.insert(ac); 470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Pass the iterator to the EpollAlarmCallbackInterface. 471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ac->OnRegistration(alarm_iter, this); 472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Unregister a specific alarm callback: iterator_token must be a 475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// valid iterator. The caller must ensure the validity of the iterator. 476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::UnregisterAlarm(const AlarmRegToken& iterator_token) { 477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AlarmCB* cb = iterator_token->second; 478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott alarm_map_.erase(iterator_token); 479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott all_alarms_.erase(cb); 480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb->OnUnregistration(); 481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint EpollServer::NumFDsRegistered() const { 484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(cb_map_.size() >= 1); 485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Omit the internal FD (read_fd_) 486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return cb_map_.size() - 1; 487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::Wake() { 490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char data = 'd'; // 'd' is for data. It's good enough for me. 491201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch int rv = write(write_fd_, &data, 1); 492201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK(rv == 1); 493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint64 EpollServer::NowInUsec() const { 496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return base::Time::Now().ToInternalValue(); 497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 49972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint64 EpollServer::ApproximateNowInUsec() const { 50072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (recorded_now_in_us_ != 0) { 50172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return recorded_now_in_us_; 50272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 50372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return this->NowInUsec(); 50472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 50572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstd::string EpollServer::EventMaskToString(int event_mask) { 507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string s; 508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_mask & EPOLLIN) s += "EPOLLIN "; 509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_mask & EPOLLPRI) s += "EPOLLPRI "; 510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_mask & EPOLLOUT) s += "EPOLLOUT "; 511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_mask & EPOLLRDNORM) s += "EPOLLRDNORM "; 512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_mask & EPOLLRDBAND) s += "EPOLLRDBAND "; 513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_mask & EPOLLWRNORM) s += "EPOLLWRNORM "; 514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_mask & EPOLLWRBAND) s += "EPOLLWRBAND "; 515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_mask & EPOLLMSG) s += "EPOLLMSG "; 516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_mask & EPOLLERR) s += "EPOLLERR "; 517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_mask & EPOLLHUP) s += "EPOLLHUP "; 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_mask & EPOLLONESHOT) s += "EPOLLONESHOT "; 519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_mask & EPOLLET) s += "EPOLLET "; 520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return s; 521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::LogStateOnCrash() { 524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "----------------------Epoll Server---------------------------"; 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Epoll server " << this << " polling on fd " << epoll_fd_; 526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "timeout_in_us_: " << timeout_in_us_; 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Log sessions with alarms. 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << alarm_map_.size() << " alarms registered."; 530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (TimeToAlarmCBMap::iterator it = alarm_map_.begin(); 531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott it != alarm_map_.end(); 532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++it) { 533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const bool skipped = 534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott alarms_reregistered_and_should_be_skipped_.find(it->second) 535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott != alarms_reregistered_and_should_be_skipped_.end(); 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Alarm " << it->second << " registered at time " << it->first 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " and should be skipped = " << skipped; 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << cb_map_.size() << " fd callbacks registered."; 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (FDToCBMap::iterator it = cb_map_.begin(); 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott it != cb_map_.end(); 543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++it) { 544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "fd: " << it->fd << " with mask " << it->event_mask 545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " registered with cb: " << it->cb; 546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "----------------------/Epoll Server--------------------------"; 548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////////////////////////////////////////////// 554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::DelFD(int fd) const { 556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct epoll_event ee; 557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memset(&ee, 0, sizeof(ee)); 558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef EPOLL_SERVER_EVENT_TRACING 559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_recorder_.RecordFDMaskEvent(fd, 0, "DelFD"); 560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, &ee)) { 562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int saved_errno = errno; 563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char buf[kErrorBufferSize]; 564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "Epoll set removal error for fd " << fd << ": " 565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << strerror_r(saved_errno, buf, sizeof(buf)); 566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////// 570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::AddFD(int fd, int event_mask) const { 572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct epoll_event ee; 573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memset(&ee, 0, sizeof(ee)); 574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ee.events = event_mask | EPOLLERR | EPOLLHUP; 575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ee.data.fd = fd; 576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef EPOLL_SERVER_EVENT_TRACING 577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_recorder_.RecordFDMaskEvent(fd, ee.events, "AddFD"); 578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &ee)) { 580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int saved_errno = errno; 581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char buf[kErrorBufferSize]; 582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "Epoll set insertion error for fd " << fd << ": " 583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << strerror_r(saved_errno, buf, sizeof(buf)); 584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////// 588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::ModFD(int fd, int event_mask) const { 590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct epoll_event ee; 591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memset(&ee, 0, sizeof(ee)); 592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ee.events = event_mask | EPOLLERR | EPOLLHUP; 593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ee.data.fd = fd; 594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef EPOLL_SERVER_EVENT_TRACING 595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_recorder_.RecordFDMaskEvent(fd, ee.events, "ModFD"); 596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(3) << "modifying fd= " << fd << " " 598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << EventMaskToString(ee.events); 599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, fd, &ee)) { 600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int saved_errno = errno; 601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char buf[kErrorBufferSize]; 602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "Epoll set modification error for fd " << fd << ": " 603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << strerror_r(saved_errno, buf, sizeof(buf)); 604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//////////////////////////////////////// 608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::ModifyFD(int fd, int remove_event, int add_event) { 610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FDToCBMap::iterator fd_i = cb_map_.find(CBAndEventMask(NULL, 0, fd)); 611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cb_map_.end() == fd_i) { 612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(2) << "Didn't find the fd " << fd << "in internal structures"; 613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (fd_i->cb != NULL) { 617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int & event_mask = fd_i->event_mask; 618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(3) << "fd= " << fd 619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " event_mask before: " << EventMaskToString(event_mask); 620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_mask &= ~remove_event; 621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_mask |= add_event; 622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(3) << " event_mask after: " << EventMaskToString(event_mask); 624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ModFD(fd, event_mask); 626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fd_i->cb->OnModification(fd, event_mask); 628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::WaitForEventsAndCallHandleEvents(int64 timeout_in_us, 632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct epoll_event events[], 633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int events_size) { 634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (timeout_in_us == 0 || ready_list_.lh_first != NULL) { 635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If ready list is not empty, then don't sleep at all. 636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott timeout_in_us = 0; 637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (timeout_in_us < 0) { 638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(INFO) << "Negative epoll timeout: " << timeout_in_us 639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "us; epoll will wait forever for events."; 640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If timeout_in_us is < 0 we are supposed to Wait forever. This means we 641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // should set timeout_in_us to -1000 so we will 642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Wait(-1000/1000) == Wait(-1) == Wait forever. 643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott timeout_in_us = -1000; 644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If timeout is specified, and the ready list is empty. 646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (timeout_in_us < 1000) { 647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott timeout_in_us = 1000; 648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const int timeout_in_ms = timeout_in_us / 1000; 651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int nfds = epoll_wait_impl(epoll_fd_, 652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events, 653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott events_size, 654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott timeout_in_ms); 655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott VLOG(3) << "nfds=" << nfds; 656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef EPOLL_SERVER_EVENT_TRACING 658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_recorder_.RecordEpollWaitEvent(timeout_in_ms, nfds); 659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If you're wondering why the NowInUsec() is recorded here, the answer is 662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // simple: If we did it before the epoll_wait_impl, then the max error for 663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the ApproximateNowInUs() call would be as large as the maximum length of 664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // epoll_wait, which can be arbitrarily long. Since this would make 665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // ApproximateNowInUs() worthless, we instead record the time -after- we've 666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // done epoll_wait, which guarantees that the maximum error is the amount of 667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // time it takes to process all the events generated by epoll_wait. 668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott recorded_now_in_us_ = NowInUsec(); 669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (nfds > 0) { 670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (int i = 0; i < nfds; ++i) { 671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int event_mask = events[i].events; 672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int fd = events[i].data.fd; 673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HandleEvent(fd, event_mask); 674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (nfds < 0) { 676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Catch interrupted syscall and just ignore it and move on. 677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (errno != EINTR && errno != 0) { 678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int saved_errno = errno; 679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char buf[kErrorBufferSize]; 680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(FATAL) << "Error " << saved_errno << " in epoll_wait: " 681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << strerror_r(saved_errno, buf, sizeof(buf)); 682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Now run through the ready list. 686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (ready_list_.lh_first) { 687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CallReadyListCallbacks(); 688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::CallReadyListCallbacks() { 692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Check pre-conditions. 693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(tmp_list_.lh_first == NULL); 694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Swap out the ready_list_ into the tmp_list_ before traversing the list to 695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // enable SetFDReady() to just push new items into the ready_list_. 696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::swap(ready_list_.lh_first, tmp_list_.lh_first); 697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (tmp_list_.lh_first) { 698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott tmp_list_.lh_first->entry.le_prev = &tmp_list_.lh_first; 699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EpollEvent event(0, false); 700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (tmp_list_.lh_first != NULL) { 701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GT(ready_list_size_, 0); 702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CBAndEventMask* cb_and_mask = tmp_list_.lh_first; 703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RemoveFromReadyList(*cb_and_mask); 704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event.out_ready_mask = 0; 706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event.in_events = 707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb_and_mask->events_asserted | cb_and_mask->events_to_fake; 708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(fenix): get rid of the two separate fields in cb_and_mask. 709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb_and_mask->events_asserted = 0; 710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb_and_mask->events_to_fake = 0; 711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott { 712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // OnEvent() may call UnRegister, so we set in_use, here. Any 713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // UnRegister call will now simply set the cb to NULL instead of 714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // invalidating the cb_and_mask object (by deleting the object in the 715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // map to which cb_and_mask refers) 716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TrueFalseGuard in_use_guard(&(cb_and_mask->in_use)); 717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb_and_mask->cb->OnEvent(cb_and_mask->fd, &event); 718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Since OnEvent may have called UnregisterFD, we must check here that 721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // the callback is still valid. If it isn't, then UnregisterFD *was* 722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // called, and we should now get rid of the object. 723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cb_and_mask->cb == NULL) { 724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb_map_.erase(*cb_and_mask); 725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (event.out_ready_mask != 0) { 726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cb_and_mask->events_to_fake = event.out_ready_mask; 727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AddToReadyList(cb_and_mask); 728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(tmp_list_.lh_first == NULL); 732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst int EpollServer::kMinimumEffectiveAlarmQuantum = 1000; 735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Alarms may be up to kMinimumEffectiveAlarmQuantum -1 us late. 737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline int64 EpollServer::DoRoundingOnNow(int64 now_in_us) const { 738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott now_in_us /= kMinimumEffectiveAlarmQuantum; 739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott now_in_us *= kMinimumEffectiveAlarmQuantum; 740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott now_in_us += (2 * kMinimumEffectiveAlarmQuantum - 1); 741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return now_in_us; 742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollServer::CallAndReregisterAlarmEvents() { 745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64 now_in_us = recorded_now_in_us_; 746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(0, recorded_now_in_us_); 747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott now_in_us = DoRoundingOnNow(now_in_us); 748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TimeToAlarmCBMap::iterator erase_it; 750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // execute alarms. 752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (TimeToAlarmCBMap::iterator i = alarm_map_.begin(); 753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott i != alarm_map_.end(); 754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ) { 755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i->first > now_in_us) { 756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AlarmCB* cb = i->second; 759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Execute the OnAlarm() only if we did not register 760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // it in this loop itself. 761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const bool added_in_this_round = 762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott alarms_reregistered_and_should_be_skipped_.find(cb) 763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott != alarms_reregistered_and_should_be_skipped_.end(); 764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (added_in_this_round) { 765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++i; 766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott all_alarms_.erase(cb); 769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const int64 new_timeout_time_in_us = cb->OnAlarm(); 770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott erase_it = i; 772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ++i; 773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott alarm_map_.erase(erase_it); 774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (new_timeout_time_in_us > 0) { 776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We add to hash_set only if the new timeout is <= now_in_us. 777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // if timeout is > now_in_us then we have no fear that this alarm 778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // can be reexecuted in this loop, and hence we do not need to 779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // worry about a recursive loop. 780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DVLOG(3) << "Reregistering alarm " 781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " " << cb 782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " " << new_timeout_time_in_us 783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " " << now_in_us; 784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (new_timeout_time_in_us <= now_in_us) { 785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott alarms_reregistered_and_should_be_skipped_.insert(cb); 786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott RegisterAlarm(new_timeout_time_in_us, cb); 788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott alarms_reregistered_and_should_be_skipped_.clear(); 791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEpollAlarm::EpollAlarm() : eps_(NULL), registered_(false) { 794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottEpollAlarm::~EpollAlarm() { 797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UnregisterIfRegistered(); 798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint64 EpollAlarm::OnAlarm() { 801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott registered_ = false; 802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollAlarm::OnRegistration(const EpollServer::AlarmRegToken& token, 806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EpollServer* eps) { 807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(false, registered_); 808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott token_ = token; 810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott eps_ = eps; 811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott registered_ = true; 812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollAlarm::OnUnregistration() { 815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott registered_ = false; 816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollAlarm::OnShutdown(EpollServer* eps) { 819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott registered_ = false; 820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott eps_ = NULL; 821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// If the alarm was registered, unregister it. 824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid EpollAlarm::UnregisterIfRegistered() { 825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!registered_) { 826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott eps_->UnregisterAlarm(token_); 829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 833