Merge branch 'master' into lua-scripting
[screen-lua.git] / src / sched.c
blob7a181d83b60f54e242dd81175eb1d4f61e7ff841
1 /* Copyright (c) 1993-2002
2 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3 * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4 * Copyright (c) 1987 Oliver Laumann
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program (see the file COPYING); if not, write to the
18 * Free Software Foundation, Inc.,
19 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 ****************************************************************
24 #include <sys/types.h>
25 #if !defined(sun) && !defined(B43) && !defined(ISC) && !defined(pyr) && !defined(_CX_UX)
26 # include <time.h>
27 #endif
28 #include <sys/time.h>
30 #include "config.h"
31 #include "screen.h"
32 #include "extern.h"
34 static struct event *evs;
35 static struct event *tevs;
36 static struct event *nextev;
37 static int calctimeout;
39 static struct event *calctimo __P((void));
40 #if (defined(sgi) && defined(SVR4)) || defined(__osf__) || defined(M_UNIX)
41 static int sgihack __P((void));
42 #endif
44 void
45 evenq(ev)
46 struct event *ev;
48 struct event *evp, **evpp;
49 debug3("New event fd %d type %d queued %d\n", ev->fd, ev->type, ev->queued);
50 if (ev->queued)
51 return;
52 evpp = &evs;
53 if (ev->type == EV_TIMEOUT)
55 calctimeout = 1;
56 evpp = &tevs;
58 for (; (evp = *evpp); evpp = &evp->next)
59 if (ev->pri > evp->pri)
60 break;
61 ev->next = evp;
62 *evpp = ev;
63 ev->queued = 1;
66 void
67 evdeq(ev)
68 struct event *ev;
70 struct event *evp, **evpp;
71 debug3("Deq event fd %d type %d queued %d\n", ev->fd, ev->type, ev->queued);
72 if (!ev->queued)
73 return;
74 evpp = &evs;
75 if (ev->type == EV_TIMEOUT)
77 calctimeout = 1;
78 evpp = &tevs;
80 for (; (evp = *evpp); evpp = &evp->next)
81 if (evp == ev)
82 break;
83 ASSERT(evp);
84 *evpp = ev->next;
85 ev->queued = 0;
86 if (ev == nextev)
87 nextev = nextev->next;
90 static struct event *
91 calctimo()
93 struct event *ev, *min;
94 long mins;
96 if ((min = tevs) == 0)
97 return 0;
98 mins = min->timeout.tv_sec;
99 for (ev = tevs->next; ev; ev = ev->next)
101 ASSERT(ev->type == EV_TIMEOUT);
102 if (mins < ev->timeout.tv_sec)
103 continue;
104 if (mins > ev->timeout.tv_sec || min->timeout.tv_usec > ev->timeout.tv_usec)
106 min = ev;
107 mins = ev->timeout.tv_sec;
110 return min;
113 void
114 sched()
116 struct event *ev;
117 fd_set r, w, *set;
118 struct event *timeoutev = 0;
119 struct timeval timeout;
120 int nsel;
122 for (;;)
124 if (calctimeout)
125 timeoutev = calctimo();
126 if (timeoutev)
128 gettimeofday(&timeout, NULL);
129 /* tp - timeout */
130 timeout.tv_sec = timeoutev->timeout.tv_sec - timeout.tv_sec;
131 timeout.tv_usec = timeoutev->timeout.tv_usec - timeout.tv_usec;
132 if (timeout.tv_usec < 0)
134 timeout.tv_usec += 1000000;
135 timeout.tv_sec--;
137 if (timeout.tv_sec < 0)
139 timeout.tv_usec = 0;
140 timeout.tv_sec = 0;
143 #ifdef DEBUG
144 debug("waiting for events");
145 if (timeoutev)
146 debug2(" timeout %d secs %d usecs", timeout.tv_sec, timeout.tv_usec);
147 debug(":\n");
148 for (ev = evs; ev; ev = ev->next)
149 debug3(" - fd %d type %d pri %d\n", ev->fd, ev->type, ev->pri);
150 if (tevs)
151 debug("timed events:\n");
152 for (ev = tevs; ev; ev = ev->next)
153 debug3(" - pri %d sec %d usec %d\n", ev->pri, ev->timeout.tv_sec, ev->timeout.tv_usec);
154 #endif
156 FD_ZERO(&r);
157 FD_ZERO(&w);
158 for (ev = evs; ev; ev = ev->next)
160 if (ev->condpos && *ev->condpos <= (ev->condneg ? *ev->condneg : 0))
162 debug2(" - cond ev fd %d type %d failed\n", ev->fd, ev->type);
163 continue;
165 if (ev->type == EV_READ)
166 FD_SET(ev->fd, &r);
167 else if (ev->type == EV_WRITE)
168 FD_SET(ev->fd, &w);
171 #ifdef DEBUG
172 debug("readfds:");
173 for (nsel = 0; nsel < FD_SETSIZE; nsel++)
174 if (FD_ISSET(nsel, &r))
175 debug1(" %d", nsel);
176 debug("\n");
177 debug("writefds:");
178 for (nsel = 0; nsel < FD_SETSIZE; nsel++)
179 if (FD_ISSET(nsel, &w))
180 debug1(" %d", nsel);
181 debug("\n");
182 #endif
184 nsel = select(FD_SETSIZE, &r, &w, (fd_set *)0, timeoutev ? &timeout : (struct timeval *) 0);
185 if (nsel < 0)
187 if (errno != EINTR)
189 #if defined(sgi) && defined(SVR4)
190 if (errno == EIO && sgihack())
191 continue;
192 #endif
193 #if defined(__osf__) || defined(M_UNIX)
194 /* OSF/1 3.x, SCO bug: EBADF */
195 /* OSF/1 4.x bug: EIO */
196 if ((errno == EIO || errno == EBADF) && sgihack())
197 continue;
198 #endif
199 Panic(errno, "select");
201 nsel = 0;
203 else if (nsel == 0) /* timeout */
205 debug("TIMEOUT!\n");
206 ASSERT(timeoutev);
207 evdeq(timeoutev);
208 timeoutev->handler(timeoutev, timeoutev->data);
210 #ifdef SELECT_BROKEN
212 * Sequents select emulation counts a descriptor which is
213 * readable and writeable only as one hit. Waaaaa.
215 if (nsel)
216 nsel = 2 * FD_SETSIZE;
217 #endif
219 for (ev = evs; ev; ev = nextev)
221 nextev = ev->next;
222 if (ev->type != EV_ALWAYS)
224 set = ev->type == EV_READ ? &r : &w;
225 if (nsel == 0 || !FD_ISSET(ev->fd, set))
226 continue;
227 nsel--;
229 if (ev->condpos && *ev->condpos <= (ev->condneg ? *ev->condneg : 0))
230 continue;
231 debug2(" + hit ev fd %d type %d!\n", ev->fd, ev->type);
232 ev->handler(ev, ev->data);
237 void
238 SetTimeout(ev, timo)
239 struct event *ev;
240 int timo;
242 ASSERT(ev->type == EV_TIMEOUT);
243 debug2("event %x new timeout %d ms\n", ev, timo);
244 gettimeofday(&ev->timeout, NULL);
245 ev->timeout.tv_sec += timo / 1000;
246 ev->timeout.tv_usec += (timo % 1000) * 1000;
247 if (ev->timeout.tv_usec > 1000000)
249 ev->timeout.tv_usec -= 1000000;
250 ev->timeout.tv_sec++;
252 if (ev->queued)
253 calctimeout = 1;
257 #if (defined(sgi) && defined(SVR4)) || defined(__osf__) || defined(M_UNIX)
259 extern struct display *display, *displays;
260 static int sgihack()
262 fd_set r, w;
263 struct timeval tv;
265 debug("IRIX5.2 workaround: searching for bad display\n");
266 for (display = displays; display; )
268 FD_ZERO(&r);
269 FD_ZERO(&w);
270 FD_SET(D_userfd, &r);
271 FD_SET(D_userfd, &w);
272 tv.tv_sec = tv.tv_usec = 0;
273 if (select(FD_SETSIZE, &r, &w, (fd_set *)0, &tv) == -1)
275 if (errno == EINTR)
276 continue;
277 Hangup(); /* goodbye display */
278 return 1;
280 display = display->d_next;
282 return 0;
285 #endif