pollevent.cc revision 408
15359Sgblack@eecs.umich.edu/* 25359Sgblack@eecs.umich.edu * Copyright (c) 2003 The Regents of The University of Michigan 35359Sgblack@eecs.umich.edu * All rights reserved. 45359Sgblack@eecs.umich.edu * 55359Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 65359Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 75359Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 85359Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 95359Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 105359Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 115359Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 125359Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 135359Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 145359Sgblack@eecs.umich.edu * this software without specific prior written permission. 155359Sgblack@eecs.umich.edu * 165359Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175359Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185359Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195359Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205359Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215359Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225359Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235359Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245359Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255359Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265359Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275359Sgblack@eecs.umich.edu */ 285359Sgblack@eecs.umich.edu 295359Sgblack@eecs.umich.edu#include <sys/ioctl.h> 304561Sgblack@eecs.umich.edu#include <sys/types.h> 314561Sgblack@eecs.umich.edu 324561Sgblack@eecs.umich.edu#include <fcntl.h> 334561Sgblack@eecs.umich.edu#include <signal.h> 344561Sgblack@eecs.umich.edu#include <unistd.h> 354561Sgblack@eecs.umich.edu 364561Sgblack@eecs.umich.edu#include "sim/async.hh" 374561Sgblack@eecs.umich.edu#include "sim/host.hh" 384561Sgblack@eecs.umich.edu#include "base/misc.hh" 394561Sgblack@eecs.umich.edu#include "base/pollevent.hh" 404561Sgblack@eecs.umich.edu#include "sim/universe.hh" 414561Sgblack@eecs.umich.edu#include "sim/serialize.hh" 424561Sgblack@eecs.umich.edu 434561Sgblack@eecs.umich.eduusing namespace std; 444561Sgblack@eecs.umich.edu 454561Sgblack@eecs.umich.eduPollQueue pollQueue; 464561Sgblack@eecs.umich.edu 474561Sgblack@eecs.umich.edu///////////////////////////////////////////////////// 484561Sgblack@eecs.umich.edu// 494561Sgblack@eecs.umich.eduPollEvent::PollEvent(int _fd, int _events) 504561Sgblack@eecs.umich.edu : queue(NULL), enabled(true) 514561Sgblack@eecs.umich.edu{ 524561Sgblack@eecs.umich.edu pfd.fd = _fd; 534561Sgblack@eecs.umich.edu pfd.events = _events; 544561Sgblack@eecs.umich.edu} 554561Sgblack@eecs.umich.edu 564561Sgblack@eecs.umich.eduPollEvent::~PollEvent() 574561Sgblack@eecs.umich.edu{ 584561Sgblack@eecs.umich.edu if (queue) 594561Sgblack@eecs.umich.edu queue->remove(this); 604561Sgblack@eecs.umich.edu} 614561Sgblack@eecs.umich.edu 624561Sgblack@eecs.umich.eduvoid 634561Sgblack@eecs.umich.eduPollEvent::disable() 644561Sgblack@eecs.umich.edu{ 654561Sgblack@eecs.umich.edu if (!enabled) return; 664561Sgblack@eecs.umich.edu enabled = false; 674561Sgblack@eecs.umich.edu 684561Sgblack@eecs.umich.edu if (queue) 694561Sgblack@eecs.umich.edu queue->copy(); 704561Sgblack@eecs.umich.edu} 714561Sgblack@eecs.umich.edu 724561Sgblack@eecs.umich.eduvoid 734561Sgblack@eecs.umich.eduPollEvent::enable() 744561Sgblack@eecs.umich.edu{ 754561Sgblack@eecs.umich.edu if (enabled) return; 764561Sgblack@eecs.umich.edu enabled = true; 774561Sgblack@eecs.umich.edu 784561Sgblack@eecs.umich.edu if (queue) 794561Sgblack@eecs.umich.edu queue->copy(); 804561Sgblack@eecs.umich.edu} 814561Sgblack@eecs.umich.edu 824561Sgblack@eecs.umich.eduvoid 834561Sgblack@eecs.umich.eduPollEvent::serialize(ostream &os) 844561Sgblack@eecs.umich.edu{ 854561Sgblack@eecs.umich.edu SERIALIZE_SCALAR(pfd.fd); 864561Sgblack@eecs.umich.edu SERIALIZE_SCALAR(pfd.events); 874561Sgblack@eecs.umich.edu SERIALIZE_SCALAR(enabled); 884561Sgblack@eecs.umich.edu} 894561Sgblack@eecs.umich.edu 904601Sgblack@eecs.umich.eduvoid 914601Sgblack@eecs.umich.eduPollEvent::unserialize(Checkpoint *cp, const std::string §ion) 924601Sgblack@eecs.umich.edu{ 934601Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(pfd.fd); 944601Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(pfd.events); 954601Sgblack@eecs.umich.edu UNSERIALIZE_SCALAR(enabled); 964601Sgblack@eecs.umich.edu} 974601Sgblack@eecs.umich.edu 984601Sgblack@eecs.umich.edu///////////////////////////////////////////////////// 994601Sgblack@eecs.umich.edu// 1004601Sgblack@eecs.umich.eduPollQueue::PollQueue() 1014601Sgblack@eecs.umich.edu : poll_fds(NULL), max_size(0), num_fds(0) 1024601Sgblack@eecs.umich.edu{ } 1034601Sgblack@eecs.umich.edu 1044601Sgblack@eecs.umich.eduPollQueue::~PollQueue() 1054601Sgblack@eecs.umich.edu{ 1064601Sgblack@eecs.umich.edu removeHandler(); 1074601Sgblack@eecs.umich.edu for (int i = 0; i < num_fds; i++) 1084601Sgblack@eecs.umich.edu setupAsyncIO(poll_fds[0].fd, false); 1094601Sgblack@eecs.umich.edu 1104601Sgblack@eecs.umich.edu delete [] poll_fds; 1114601Sgblack@eecs.umich.edu} 1124601Sgblack@eecs.umich.edu 1134601Sgblack@eecs.umich.eduvoid 1144601Sgblack@eecs.umich.eduPollQueue::copy() 1154601Sgblack@eecs.umich.edu{ 1164601Sgblack@eecs.umich.edu eventvec_t::iterator i = events.begin(); 1174601Sgblack@eecs.umich.edu eventvec_t::iterator end = events.end(); 1184601Sgblack@eecs.umich.edu 1194601Sgblack@eecs.umich.edu num_fds = 0; 1204601Sgblack@eecs.umich.edu 1214601Sgblack@eecs.umich.edu while (i < end) { 1224601Sgblack@eecs.umich.edu if ((*i)->enabled) 1234601Sgblack@eecs.umich.edu poll_fds[num_fds++] = (*i)->pfd; 1246345Sgblack@eecs.umich.edu ++i; 1256345Sgblack@eecs.umich.edu } 1266345Sgblack@eecs.umich.edu} 1275912Sgblack@eecs.umich.edu 1285912Sgblack@eecs.umich.eduvoid 1294601Sgblack@eecs.umich.eduPollQueue::remove(PollEvent *event) 1304601Sgblack@eecs.umich.edu{ 1314601Sgblack@eecs.umich.edu eventvec_t::iterator i = events.begin(); 1326345Sgblack@eecs.umich.edu eventvec_t::iterator end = events.end(); 1336345Sgblack@eecs.umich.edu 1346345Sgblack@eecs.umich.edu while (i < end) { 1355912Sgblack@eecs.umich.edu if (*i == event) { 1365912Sgblack@eecs.umich.edu events.erase(i); 1374601Sgblack@eecs.umich.edu copy(); 1384601Sgblack@eecs.umich.edu event->queue = NULL; 1394601Sgblack@eecs.umich.edu return; 1404601Sgblack@eecs.umich.edu } 1414601Sgblack@eecs.umich.edu 1424601Sgblack@eecs.umich.edu ++i; 1434601Sgblack@eecs.umich.edu } 1444587Sgblack@eecs.umich.edu 1454587Sgblack@eecs.umich.edu panic("Event does not exist. Cannot remove."); 1464587Sgblack@eecs.umich.edu} 1474587Sgblack@eecs.umich.edu 1484587Sgblack@eecs.umich.eduvoid 1494587Sgblack@eecs.umich.eduPollQueue::schedule(PollEvent *event) 1504587Sgblack@eecs.umich.edu{ 1514587Sgblack@eecs.umich.edu if (event->queue) 1524587Sgblack@eecs.umich.edu panic("Event already scheduled!"); 1534587Sgblack@eecs.umich.edu 1544587Sgblack@eecs.umich.edu event->queue = this; 1554587Sgblack@eecs.umich.edu events.push_back(event); 1565912Sgblack@eecs.umich.edu setupAsyncIO(event->pfd.fd, true); 1574720Sgblack@eecs.umich.edu 1585920Sgblack@eecs.umich.edu // if we ran out of space in the fd array, double the capacity 1594587Sgblack@eecs.umich.edu // if this is the first time that we've scheduled an event, create 1605920Sgblack@eecs.umich.edu // the array with an initial size of 16 1615920Sgblack@eecs.umich.edu if (++num_fds > max_size) { 1625920Sgblack@eecs.umich.edu if (max_size > 0) { 1634587Sgblack@eecs.umich.edu delete [] poll_fds; 1644587Sgblack@eecs.umich.edu max_size *= 2; 1654587Sgblack@eecs.umich.edu } else { 1664587Sgblack@eecs.umich.edu max_size = 16; 1674587Sgblack@eecs.umich.edu setupHandler(); 1684587Sgblack@eecs.umich.edu } 1694587Sgblack@eecs.umich.edu 1704587Sgblack@eecs.umich.edu poll_fds = new pollfd[max_size]; 1714587Sgblack@eecs.umich.edu } 1724587Sgblack@eecs.umich.edu 1734587Sgblack@eecs.umich.edu copy(); 1744587Sgblack@eecs.umich.edu} 1754587Sgblack@eecs.umich.edu 1764587Sgblack@eecs.umich.eduvoid 1774587Sgblack@eecs.umich.eduPollQueue::service() 1784587Sgblack@eecs.umich.edu{ 1794587Sgblack@eecs.umich.edu int ret = poll(poll_fds, num_fds, 0); 1804587Sgblack@eecs.umich.edu 1814587Sgblack@eecs.umich.edu if (ret <= 0) 1824587Sgblack@eecs.umich.edu return; 1834587Sgblack@eecs.umich.edu 1844587Sgblack@eecs.umich.edu for (int i = 0; i < num_fds; i++) { 1855912Sgblack@eecs.umich.edu int revents = poll_fds[i].revents; 1864587Sgblack@eecs.umich.edu if (revents) { 1874587Sgblack@eecs.umich.edu events[i]->process(revents); 1884587Sgblack@eecs.umich.edu if (--ret <= 0) 1894587Sgblack@eecs.umich.edu break; 1904587Sgblack@eecs.umich.edu } 1914587Sgblack@eecs.umich.edu } 1924587Sgblack@eecs.umich.edu} 1934587Sgblack@eecs.umich.edu 1944587Sgblack@eecs.umich.edustruct sigaction PollQueue::oldio; 1954587Sgblack@eecs.umich.edustruct sigaction PollQueue::oldalrm; 1964587Sgblack@eecs.umich.edubool PollQueue::handler = false; 1974587Sgblack@eecs.umich.edu 1984587Sgblack@eecs.umich.eduvoid 1994587Sgblack@eecs.umich.eduPollQueue::setupAsyncIO(int fd, bool set) 2004587Sgblack@eecs.umich.edu{ 2015727Sgblack@eecs.umich.edu int flags = fcntl(fd, F_GETFL); 2025002Sgblack@eecs.umich.edu if (flags == -1) 2034587Sgblack@eecs.umich.edu panic("Could not set up async IO"); 2044587Sgblack@eecs.umich.edu 2054587Sgblack@eecs.umich.edu if (set) 2064587Sgblack@eecs.umich.edu flags |= FASYNC; 2074587Sgblack@eecs.umich.edu else 2084587Sgblack@eecs.umich.edu flags &= ~(FASYNC); 2094587Sgblack@eecs.umich.edu 2104587Sgblack@eecs.umich.edu if (fcntl(fd, F_SETFL, flags) == -1) 2114587Sgblack@eecs.umich.edu panic("Could not set up async IO"); 2124587Sgblack@eecs.umich.edu 2134587Sgblack@eecs.umich.edu if (set) { 2144587Sgblack@eecs.umich.edu if (fcntl(fd, F_SETOWN, getpid()) == -1) 2154587Sgblack@eecs.umich.edu panic("Could not set up async IO"); 2164587Sgblack@eecs.umich.edu } 2174587Sgblack@eecs.umich.edu} 2184587Sgblack@eecs.umich.edu 2194587Sgblack@eecs.umich.eduvoid 2204587Sgblack@eecs.umich.eduPollQueue::setupHandler() 2214587Sgblack@eecs.umich.edu{ 2224587Sgblack@eecs.umich.edu struct sigaction act; 2234587Sgblack@eecs.umich.edu 2244587Sgblack@eecs.umich.edu act.sa_handler = handleIO; 2254587Sgblack@eecs.umich.edu sigemptyset(&act.sa_mask); 2264587Sgblack@eecs.umich.edu act.sa_flags = SA_RESTART; 2274587Sgblack@eecs.umich.edu 2284587Sgblack@eecs.umich.edu if (sigaction(SIGIO, &act, &oldio) == -1) 2294587Sgblack@eecs.umich.edu panic("could not do sigaction"); 2304587Sgblack@eecs.umich.edu 2314587Sgblack@eecs.umich.edu act.sa_handler = handleALRM; 2325912Sgblack@eecs.umich.edu sigemptyset(&act.sa_mask); 2334767Sgblack@eecs.umich.edu act.sa_flags = SA_RESTART; 2344720Sgblack@eecs.umich.edu 2355892Sgblack@eecs.umich.edu if (sigaction(SIGALRM, &act, &oldalrm) == -1) 2364767Sgblack@eecs.umich.edu panic("could not do sigaction"); 2374720Sgblack@eecs.umich.edu 2384587Sgblack@eecs.umich.edu alarm(1); 2394587Sgblack@eecs.umich.edu 2404587Sgblack@eecs.umich.edu handler = true; 2414587Sgblack@eecs.umich.edu} 2424587Sgblack@eecs.umich.edu 2434587Sgblack@eecs.umich.eduvoid 2444587Sgblack@eecs.umich.eduPollQueue::removeHandler() 2454587Sgblack@eecs.umich.edu{ 2464587Sgblack@eecs.umich.edu if (sigaction(SIGIO, &oldio, NULL) == -1) 2474587Sgblack@eecs.umich.edu panic("could not remove handler"); 2484587Sgblack@eecs.umich.edu 2494587Sgblack@eecs.umich.edu if (sigaction(SIGIO, &oldalrm, NULL) == -1) 2504587Sgblack@eecs.umich.edu panic("could not remove handler"); 2514587Sgblack@eecs.umich.edu} 2524587Sgblack@eecs.umich.edu 2534587Sgblack@eecs.umich.eduvoid 2544587Sgblack@eecs.umich.eduPollQueue::handleIO(int sig) 2554587Sgblack@eecs.umich.edu{ 2564587Sgblack@eecs.umich.edu if (sig != SIGIO) 2574587Sgblack@eecs.umich.edu panic("Wrong Handler"); 2584587Sgblack@eecs.umich.edu 2594587Sgblack@eecs.umich.edu async_event = true; 2605912Sgblack@eecs.umich.edu async_io = true; 2614587Sgblack@eecs.umich.edu} 2624587Sgblack@eecs.umich.edu 2634587Sgblack@eecs.umich.eduvoid 2644587Sgblack@eecs.umich.eduPollQueue::handleALRM(int sig) 2654587Sgblack@eecs.umich.edu{ 2664587Sgblack@eecs.umich.edu if (sig != SIGALRM) 2675892Sgblack@eecs.umich.edu panic("Wrong Handler"); 2685892Sgblack@eecs.umich.edu 2694587Sgblack@eecs.umich.edu async_event = true; 2705892Sgblack@eecs.umich.edu async_alarm = true; 2715892Sgblack@eecs.umich.edu alarm(1); 2725892Sgblack@eecs.umich.edu} 2735892Sgblack@eecs.umich.edu 2744587Sgblack@eecs.umich.edu