2 * Empire - A multi-player, client/server Internet based war game.
3 * Copyright (C) 1994-2006, Dave Pare, Jeff Bailey, Thomas Ruschak,
4 * Ken Stevens, Steve McClure
5 * Copyright (C) 1991-3 Stephen Crane
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * See the "LEGAL", "LICENSE", "CREDITS" and "README" files for all the
24 * related information and legal notices. It is expected that any future
25 * projects/authors will amend these files as needed.
29 * sel.c: arrange to block on read/write file descriptors using lwp
31 * Known contributors to this file:
39 #include <sys/types.h>
53 struct lwpProc **wait;
54 struct lwpQueue delayq;
58 struct lwpSelect LwpSelect;
61 lwpInitSelect(struct lwpProc *proc)
65 FD_ZERO(&LwpSelect.readmask);
66 FD_ZERO(&LwpSelect.writemask);
67 LwpSelect.wait = calloc(FD_SETSIZE, sizeof(struct lwpProc *));
68 LwpSelect.delayq.head = 0;
69 LwpSelect.delayq.tail = 0;
70 LwpSelect.proc = proc;
74 lwpSleepFd(int fd, int mask)
76 lwpStatus(LwpCurrent, "sleeping on fd %d for %d", fd, mask);
78 if (CANT_HAPPEN(fd > FD_SETSIZE))
80 if (LwpSelect.wait[fd] != 0) {
82 "multiple sleeps attempted on file descriptor %d", fd);
85 if (mask & LWP_FD_READ)
86 FD_SET(fd, &LwpSelect.readmask);
87 if (mask & LWP_FD_WRITE)
88 FD_SET(fd, &LwpSelect.writemask);
92 if (LwpSelect.maxfd == 0 && LwpSelect.delayq.head == 0) {
93 /* select process is sleeping until first waiter arrives */
94 lwpStatus(LwpCurrent, "going to resched fd %d", fd);
95 lwpReady(LwpSelect.proc);
97 lwpStatus(LwpCurrent, "going to wait on fd %d", fd);
98 if (fd > LwpSelect.maxfd)
100 LwpSelect.wait[fd] = LwpCurrent;
106 lwpWakeupFd(struct lwpProc *proc)
111 lwpStatus(proc, "awakening; was sleeping on fd %d", proc->fd);
112 FD_CLR(proc->fd, &LwpSelect.readmask);
113 FD_CLR(proc->fd, &LwpSelect.writemask);
115 LwpSelect.wait[proc->fd] = 0;
121 lwpSleepUntil(long int until)
123 lwpStatus(LwpCurrent, "sleeping for %ld sec", until - time(0));
124 LwpCurrent->runtime = until;
125 if (LwpSelect.maxfd == 0 && LwpSelect.delayq.head == 0) {
126 /* select process is sleeping until first waiter arrives */
127 lwpReady(LwpSelect.proc);
129 lwpAddTail(&LwpSelect.delayq, LwpCurrent);
137 struct lwpProc *us = LwpCurrent;
144 struct lwpProc *proc;
146 struct lwpQueue save;
148 lwpStatus(us, "starting select loop");
155 if (LwpSelect.delayq.head)
157 /* wait for someone to lwpSleepFd or lwpSleepUntil */
159 lwpStatus(us, "no fds or sleepers, waiting");
164 if (LwpSelect.delayq.head) {
166 proc = LwpSelect.delayq.head;
167 for (; proc != 0; proc = proc->next) {
168 delta = proc->runtime - now;
169 if (delta < tv.tv_sec)
175 lwpStatus(us, "selecting; sleep %ld secs", tv.tv_sec);
177 memcpy(&readmask, &LwpSelect.readmask, sizeof(fd_set));
178 memcpy(&writemask, &LwpSelect.writemask, sizeof(fd_set));
179 n = select(LwpSelect.maxfd + 1, &readmask, &writemask,
183 if (errno == EINTR) {
184 /* go handle the signal */
189 lwpStatus(us, "select failed (bad file descriptor?)");
193 if (LwpSelect.delayq.head) {
194 /* sleeping proecss activity */
196 save.tail = save.head = 0;
197 while (NULL != (proc = lwpGetFirst(&LwpSelect.delayq))) {
198 if (now >= proc->runtime) {
199 lwpStatus(proc, "sleep done");
202 lwpAddTail(&save, proc);
205 LwpSelect.delayq = save;
208 /* file descriptor activity */
209 for (fd = 0; fd <= LwpSelect.maxfd; fd++) {
210 if (LwpSelect.wait[fd] == 0)
212 if (FD_ISSET(fd, &readmask)) {
213 lwpStatus(LwpSelect.wait[fd], "input ready");
214 lwpWakeupFd(LwpSelect.wait[fd]);
217 if (FD_ISSET(fd, &writemask)) {
218 lwpStatus(LwpSelect.wait[fd], "output ready");
219 lwpWakeupFd(LwpSelect.wait[fd]);
224 lwpStatus(us, "fd dispatch completed");
225 lwpReady(LwpCurrent);