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 &section)
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