Deleted Added
sdiff udiff text old ( 9990:12a0efdde000 ) new ( 10360:919c02740209 )
full compact
1/*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Nathan Binkert
29 */
30
31#include <sys/ioctl.h>
32#include <sys/types.h>
33#if defined(__sun__) || defined(__SUNPRO_CC)
34#include <sys/file.h>
35#endif
36
37#include <fcntl.h>
38#include <unistd.h>
39
40#include <csignal>
41
42#include "base/misc.hh"
43#include "base/pollevent.hh"
44#include "base/types.hh"
45#include "sim/async.hh"
46#include "sim/core.hh"
47#include "sim/serialize.hh"
48
49using namespace std;
50
51PollQueue pollQueue;
52
53/////////////////////////////////////////////////////
54//
55PollEvent::PollEvent(int _fd, int _events)
56 : queue(NULL), enabled(true)
57{
58 pfd.fd = _fd;
59 pfd.events = _events;
60 pfd.revents = 0;
61}
62
63PollEvent::~PollEvent()
64{
65 if (queue)
66 queue->remove(this);
67}
68
69void
70PollEvent::disable()
71{
72 if (!enabled) return;
73 enabled = false;
74
75 if (queue)
76 queue->copy();
77}
78
79void
80PollEvent::enable()
81{
82 if (enabled) return;
83 enabled = true;
84
85 if (queue)
86 queue->copy();
87}
88
89void
90PollEvent::serialize(ostream &os)
91{
92 SERIALIZE_SCALAR(pfd.fd);
93 SERIALIZE_SCALAR(pfd.events);
94 SERIALIZE_SCALAR(enabled);
95}
96
97void
98PollEvent::unserialize(Checkpoint *cp, const std::string &section)
99{
100 UNSERIALIZE_SCALAR(pfd.fd);
101 UNSERIALIZE_SCALAR(pfd.events);
102 UNSERIALIZE_SCALAR(enabled);
103}
104
105/////////////////////////////////////////////////////
106//
107PollQueue::PollQueue()
108 : poll_fds(NULL), max_size(0), num_fds(0)
109{ }
110
111PollQueue::~PollQueue()
112{
113 for (int i = 0; i < num_fds; i++)
114 setupAsyncIO(poll_fds[0].fd, false);
115
116 delete [] poll_fds;
117}
118
119void
120PollQueue::copy()
121{
122 eventvec_t::iterator i = events.begin();
123 eventvec_t::iterator end = events.end();
124
125 num_fds = 0;
126
127 while (i < end) {
128 if ((*i)->enabled)
129 poll_fds[num_fds++] = (*i)->pfd;
130 ++i;
131 }
132}
133
134void
135PollQueue::remove(PollEvent *event)
136{
137 eventvec_t::iterator i = events.begin();
138 eventvec_t::iterator end = events.end();
139
140 while (i < end) {
141 if (*i == event) {
142 events.erase(i);
143 copy();
144 event->queue = NULL;
145 return;
146 }
147
148 ++i;
149 }
150
151 panic("Event does not exist. Cannot remove.");
152}
153
154void
155PollQueue::schedule(PollEvent *event)
156{
157 if (event->queue)
158 panic("Event already scheduled!");
159
160 event->queue = this;
161 events.push_back(event);
162 setupAsyncIO(event->pfd.fd, true);
163
164 // if we ran out of space in the fd array, double the capacity
165 // if this is the first time that we've scheduled an event, create
166 // the array with an initial size of 16
167 if (++num_fds > max_size) {
168 if (max_size > 0) {
169 delete [] poll_fds;
170 max_size *= 2;
171 } else {
172 max_size = 16;
173 }
174
175 poll_fds = new pollfd[max_size];
176 }
177
178 copy();
179}
180
181void
182PollQueue::service()
183{
184 int ret = poll(poll_fds, num_fds, 0);
185
186 if (ret <= 0)
187 return;
188
189 for (int i = 0; i < num_fds; i++) {
190 int revents = poll_fds[i].revents;
191 if (revents) {
192 events[i]->process(revents);
193 if (--ret <= 0)
194 break;
195 }
196 }
197}
198
199void
200PollQueue::setupAsyncIO(int fd, bool set)
201{
202 int flags = fcntl(fd, F_GETFL);
203 if (flags == -1)
204 panic("Could not set up async IO");
205
206 if (set)
207 flags |= FASYNC;
208 else
209 flags &= ~(FASYNC);
210
211 if (set) {
212 if (fcntl(fd, F_SETOWN, getpid()) == -1)
213 panic("Could not set up async IO");
214 }
215
216 if (fcntl(fd, F_SETFL, flags) == -1)
217 panic("Could not set up async IO");
218
219 // The file descriptor might already have events pending. We won't
220 // see them if they occurred before we set the FASYNC
221 // flag. Simulate a SIGIO to ensure that the FD will be polled in
222 // next iteration of the simulation loop. We could just poll it,
223 // but this is much simpler.
224 if (set) {
225 async_event = true;
226 async_io = true;
227 }
228}