2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1986-2000, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
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 of the License, or
9 * (at your option) 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; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
23 * related information and legal notices. It is expected that any future
24 * projects/authors will amend these files as needed.
28 * sel.c: arrange to block on read/write file descriptors using lwp
30 * Known contributors to this file:
36 #include <sys/types.h>
48 #include "prototypes.h"
50 #if defined(_EMPTH_LWP)
58 struct lwpProc **wait;
59 struct lwpQueue delayq;
63 struct lwpSelect LwpSelect;
65 void lwpInitSelect(proc)
71 LwpSelect.nfile = _NFILE;
73 LwpSelect.nfile = getdtablesize();
75 FD_ZERO(&LwpSelect.readmask);
76 FD_ZERO(&LwpSelect.writemask);
77 LwpSelect.wait = (struct lwpProc **)
78 calloc(LwpSelect.nfile, sizeof(char *));
79 LwpSelect.delayq.head = 0;
80 LwpSelect.delayq.tail = 0;
81 LwpSelect.proc = proc;
84 void lwpSleepFd(fd, mask)
88 extern struct lwpProc *LwpCurrent;
90 lwpStatus(LwpCurrent, "sleeping on fd %d", fd);
92 if (LwpSelect.wait[fd] != 0) {
94 "multiple sleeps attempted on file descriptor %d", fd);
97 if (mask & LWP_FD_READ)
98 FD_SET(fd, &LwpSelect.readmask);
99 if (mask & LWP_FD_WRITE)
100 FD_SET(fd, &LwpSelect.writemask);
104 if (LwpSelect.maxfd == 0 && LwpSelect.delayq.head == 0) {
105 /* select process is sleeping until first waiter arrives */
106 lwpStatus(LwpCurrent, "going to resched fd %d", fd);
107 lwpReady(LwpSelect.proc);
109 lwpStatus(LwpCurrent, "going to wait on fd %d", fd);
110 if (fd > LwpSelect.maxfd)
111 LwpSelect.maxfd = fd;
112 LwpSelect.wait[fd] = LwpCurrent;
117 void lwpWakeupFd(proc)
118 struct lwpProc *proc;
123 lwpStatus(proc, "awakening; was sleeping on fd %d", proc->fd);
124 FD_CLR(proc->fd, &LwpSelect.readmask);
125 FD_CLR(proc->fd, &LwpSelect.writemask);
127 LwpSelect.wait[proc->fd] = 0;
132 void lwpSleepUntil(until)
135 extern struct lwpProc *LwpCurrent;
137 lwpStatus(LwpCurrent, "sleeping for %d sec", until - time(0));
138 LwpCurrent->runtime = until;
139 if (LwpSelect.maxfd == 0 && LwpSelect.delayq.head == 0) {
140 /* select process is sleeping until first waiter arrives */
141 lwpReady(LwpSelect.proc);
143 lwpAddTail(&LwpSelect.delayq, LwpCurrent);
149 lwpSelect(argc, argv)
153 extern struct lwpProc *LwpCurrent;
154 struct lwpProc *us = LwpCurrent;
161 struct lwpProc *proc;
163 struct lwpQueue save;
165 lwpStatus(us, "starting select loop");
172 if (LwpSelect.delayq.head)
174 /* wait for someone to lwpSleepFd or lwpSleepUntil */
176 lwpStatus(us, "no fds or sleepers, waiting");
181 if (LwpSelect.delayq.head) {
183 proc = LwpSelect.delayq.head;
184 for ( ; proc != 0; proc = proc->next) {
185 delta = proc->runtime - now;
186 if (delta < tv.tv_sec)
192 lwpStatus(us, "selecting; sleep %ld secs", (long)delta);
194 bcopy((s_char *)&LwpSelect.readmask, (s_char *)&readmask, sizeof(fd_set));
195 bcopy((s_char *)&LwpSelect.writemask, (s_char *)&writemask, sizeof(fd_set));
196 n = select(LwpSelect.maxfd + 1, &readmask, &writemask,
200 if (errno == EINTR) {
201 /* go handle the signal */
207 "select failed (bad file descriptor?)");
211 if (LwpSelect.delayq.head) {
212 /* sleeping proecss activity */
214 save.tail = save.head = 0;
215 while (NULL != (proc = lwpGetFirst(&LwpSelect.delayq))) {
216 if (now >= proc->runtime) {
217 lwpStatus(proc, "sleep done");
220 lwpAddTail(&save, proc);
223 LwpSelect.delayq = save;
226 /* file descriptor activity */
227 for(fd = 0; fd <= LwpSelect.maxfd; fd++) {
228 if (LwpSelect.wait[fd] == 0)
230 if (FD_ISSET(fd, &readmask)) {
231 lwpStatus(LwpSelect.wait[fd],
233 lwpWakeupFd(LwpSelect.wait[fd]);
236 if (FD_ISSET(fd, &writemask)) {
237 lwpStatus(LwpSelect.wait[fd],
239 lwpWakeupFd(LwpSelect.wait[fd]);
244 lwpStatus(us, "fd dispatch completed");
245 lwpReady(LwpCurrent);