debuggers.hg

view tools/blktap2/drivers/scheduler.c @ 22848:6341fe0f4e5a

Added tag 4.1.0-rc2 for changeset 9dca60d88c63
author Keir Fraser <keir@xen.org>
date Tue Jan 25 14:06:55 2011 +0000 (2011-01-25)
parents 1c627434605e
children
line source
1 /*
2 * Copyright (c) 2008, XenSource Inc.
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 met:
7 * * 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 XenSource Inc. nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * 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 OWNER
20 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 #include <errno.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <sys/time.h>
34 #include "scheduler.h"
35 #include "tapdisk-log.h"
37 #define DBG(_f, _a...) tlog_write(TLOG_DBG, _f, ##_a)
39 #define SCHEDULER_MAX_TIMEOUT 600
40 #define SCHEDULER_POLL_FD (SCHEDULER_POLL_READ_FD | \
41 SCHEDULER_POLL_WRITE_FD | \
42 SCHEDULER_POLL_EXCEPT_FD)
44 #define MIN(a, b) ((a) <= (b) ? (a) : (b))
45 #define MAX(a, b) ((a) >= (b) ? (a) : (b))
47 #define scheduler_for_each_event(s, event, tmp) \
48 list_for_each_entry_safe(event, tmp, &(s)->events, next)
50 typedef struct event {
51 char mode;
52 event_id_t id;
54 int fd;
55 int timeout;
56 int deadline;
58 event_cb_t cb;
59 void *private;
61 struct list_head next;
62 } event_t;
64 static void
65 scheduler_prepare_events(scheduler_t *s)
66 {
67 int diff;
68 struct timeval now;
69 event_t *event, *tmp;
71 FD_ZERO(&s->read_fds);
72 FD_ZERO(&s->write_fds);
73 FD_ZERO(&s->except_fds);
75 s->max_fd = 0;
76 s->timeout = SCHEDULER_MAX_TIMEOUT;
78 gettimeofday(&now, NULL);
80 scheduler_for_each_event(s, event, tmp) {
81 if (event->mode & SCHEDULER_POLL_READ_FD) {
82 FD_SET(event->fd, &s->read_fds);
83 s->max_fd = MAX(event->fd, s->max_fd);
84 }
86 if (event->mode & SCHEDULER_POLL_WRITE_FD) {
87 FD_SET(event->fd, &s->write_fds);
88 s->max_fd = MAX(event->fd, s->max_fd);
89 }
91 if (event->mode & SCHEDULER_POLL_EXCEPT_FD) {
92 FD_SET(event->fd, &s->except_fds);
93 s->max_fd = MAX(event->fd, s->max_fd);
94 }
96 if (event->mode & SCHEDULER_POLL_TIMEOUT) {
97 diff = event->deadline - now.tv_sec;
98 if (diff > 0)
99 s->timeout = MIN(s->timeout, diff);
100 else
101 s->timeout = 0;
102 }
103 }
105 s->timeout = MIN(s->timeout, s->max_timeout);
106 }
108 static void
109 scheduler_event_callback(event_t *event, char mode)
110 {
111 if (event->mode & SCHEDULER_POLL_TIMEOUT) {
112 struct timeval now;
113 gettimeofday(&now, NULL);
114 event->deadline = now.tv_sec + event->timeout;
115 }
117 event->cb(event->id, mode, event->private);
118 }
120 static void
121 scheduler_run_events(scheduler_t *s)
122 {
123 struct timeval now;
124 event_t *event, *tmp;
126 gettimeofday(&now, NULL);
128 again:
129 s->restart = 0;
131 scheduler_for_each_event(s, event, tmp) {
132 if ((event->mode & SCHEDULER_POLL_READ_FD) &&
133 FD_ISSET(event->fd, &s->read_fds)) {
134 FD_CLR(event->fd, &s->read_fds);
135 scheduler_event_callback(event, SCHEDULER_POLL_READ_FD);
136 goto next;
137 }
139 if ((event->mode & SCHEDULER_POLL_WRITE_FD) &&
140 FD_ISSET(event->fd, &s->write_fds)) {
141 FD_CLR(event->fd, &s->write_fds);
142 scheduler_event_callback(event, SCHEDULER_POLL_WRITE_FD);
143 goto next;
144 }
146 if ((event->mode & SCHEDULER_POLL_EXCEPT_FD) &&
147 FD_ISSET(event->fd, &s->except_fds)) {
148 FD_CLR(event->fd, &s->except_fds);
149 scheduler_event_callback(event, SCHEDULER_POLL_EXCEPT_FD);
150 goto next;
151 }
153 if ((event->mode & SCHEDULER_POLL_TIMEOUT) &&
154 (event->deadline <= now.tv_sec))
155 scheduler_event_callback(event, SCHEDULER_POLL_TIMEOUT);
157 next:
158 if (s->restart)
159 goto again;
160 }
161 }
163 int
164 scheduler_register_event(scheduler_t *s, char mode, int fd,
165 int timeout, event_cb_t cb, void *private)
166 {
167 event_t *event;
168 struct timeval now;
170 if (!cb)
171 return -EINVAL;
173 if (!(mode & SCHEDULER_POLL_TIMEOUT) && !(mode & SCHEDULER_POLL_FD))
174 return -EINVAL;
176 event = calloc(1, sizeof(event_t));
177 if (!event)
178 return -ENOMEM;
180 gettimeofday(&now, NULL);
182 INIT_LIST_HEAD(&event->next);
184 event->mode = mode;
185 event->fd = fd;
186 event->timeout = timeout;
187 event->deadline = now.tv_sec + timeout;
188 event->cb = cb;
189 event->private = private;
190 event->id = s->uuid++;
192 if (!s->uuid)
193 s->uuid++;
195 list_add_tail(&event->next, &s->events);
197 return event->id;
198 }
200 void
201 scheduler_unregister_event(scheduler_t *s, event_id_t id)
202 {
203 event_t *event, *tmp;
205 if (!id)
206 return;
208 scheduler_for_each_event(s, event, tmp)
209 if (event->id == id) {
210 list_del(&event->next);
211 free(event);
212 s->restart = 1;
213 break;
214 }
215 }
217 void
218 scheduler_set_max_timeout(scheduler_t *s, int timeout)
219 {
220 if (timeout >= 0)
221 s->max_timeout = MIN(s->max_timeout, timeout);
222 }
224 int
225 scheduler_wait_for_events(scheduler_t *s)
226 {
227 int ret;
228 struct timeval tv;
230 scheduler_prepare_events(s);
232 tv.tv_sec = s->timeout;
233 tv.tv_usec = 0;
235 DBG("timeout: %d, max_timeout: %d\n",
236 s->timeout, s->max_timeout);
238 ret = select(s->max_fd + 1, &s->read_fds,
239 &s->write_fds, &s->except_fds, &tv);
241 s->restart = 0;
242 s->timeout = SCHEDULER_MAX_TIMEOUT;
243 s->max_timeout = SCHEDULER_MAX_TIMEOUT;
245 if (ret < 0)
246 return ret;
248 scheduler_run_events(s);
250 return ret;
251 }
253 void
254 scheduler_initialize(scheduler_t *s)
255 {
256 memset(s, 0, sizeof(scheduler_t));
258 s->uuid = 1;
260 FD_ZERO(&s->read_fds);
261 FD_ZERO(&s->write_fds);
262 FD_ZERO(&s->except_fds);
264 INIT_LIST_HEAD(&s->events);
265 }