2
Copyright (C) 2003-2004 Douglas Thain and the University of Wisconsin
3
Copyright (C) 2005- The University of Notre Dame
4
This software is distributed under the GNU General Public License.
5
See the file COPYING for details.
9
#include "pfs_process.h"
10
#include "pfs_critical.h"
21
#include <sys/select.h>
26
This code has a race condition that is unavoidable.
27
We want to select on a number of file descriptors,
28
but be woken up if a sigchild comes in. Sadly, Linux
29
has no atomic pselect. To combat this, we put an
30
upper bound on the select sleep time, and check an
31
integer shortly before selecting. Not much else
35
#define POLL_TIME_MAX 1
37
#define POLL_TABLE_MAX 4096
38
#define SLEEP_TABLE_MAX 4096
47
struct timeval stoptime;
51
static struct poll_entry poll_table[POLL_TABLE_MAX];
52
static struct sleep_entry sleep_table[SLEEP_TABLE_MAX];
54
static int poll_table_size = 0;
55
static int sleep_table_size = 0;
56
static int poll_abort_now = 0;
58
extern void install_handler( int sig, void (*handler)(int sig));
59
extern void handle_sigchld( int sig );
69
for(i=0;i<POLL_TABLE_MAX;i++) {
70
poll_table[i].pid = -1;
72
for(i=0;i<SLEEP_TABLE_MAX;i++) {
73
sleep_table[i].pid = -1;
77
void pfs_poll_clear( int pid )
80
for(i=0;i<poll_table_size;i++) {
81
if(poll_table[i].pid==pid) poll_table[i].pid = -1;
83
for(i=0;i<sleep_table_size;i++) {
84
if(sleep_table[i].pid==pid) sleep_table[i].pid = -1;
90
struct timeval curtime;
91
struct timeval stoptime;
92
struct timeval sleeptime;
93
fd_set rfds, wfds, efds;
94
struct sleep_entry *s;
105
gettimeofday(&curtime,0);
107
stoptime.tv_sec += POLL_TIME_MAX;
109
for(i=0;i<poll_table_size;i++) {
112
maxfd = MAX(p->fd+1,maxfd);
113
if(p->flags&PFS_POLL_READ) FD_SET(p->fd,&rfds);
114
if(p->flags&PFS_POLL_WRITE) FD_SET(p->fd,&wfds);
115
if(p->flags&PFS_POLL_EXCEPT) FD_SET(p->fd,&efds);
118
for(i=0;i<sleep_table_size;i++) {
121
if(timercmp(&stoptime,&s->stoptime,>)) {
122
stoptime = s->stoptime;
127
sleeptime.tv_sec = stoptime.tv_sec - curtime.tv_sec;
128
sleeptime.tv_usec = stoptime.tv_usec - curtime.tv_usec;
130
while(sleeptime.tv_usec<0) {
131
sleeptime.tv_usec += 1000000;
132
sleeptime.tv_sec -= 1;
137
if(!poll_abort_now && sleeptime.tv_sec>0) usleep(1);
139
if(sleeptime.tv_sec<0 || poll_abort_now) {
140
sleeptime.tv_sec = 0;
141
sleeptime.tv_usec = 0;
144
result = select(maxfd,&rfds,&wfds,&efds,&sleeptime);
149
for(i=0;i<poll_table_size;i++) {
153
(p->flags&PFS_POLL_READ && FD_ISSET(p->fd,&rfds)) ||
154
(p->flags&PFS_POLL_WRITE && FD_ISSET(p->fd,&wfds)) ||
155
(p->flags&PFS_POLL_EXCEPT && FD_ISSET(p->fd,&efds))
158
debug(D_POLL,"waking pid %d because of fd %d",pid,p->fd);
160
pfs_process_wake(pid);
164
} else if(result==0) {
165
// select timed out, which should never happen, except
166
// that it does when the jvm linked with hdfs sets up its
167
// signal handlers to avoid sigchld. In that case, re-install
168
install_handler(SIGCHLD,handle_sigchld);
170
gettimeofday(&curtime,0);
172
for(i=0;i<sleep_table_size;i++) {
175
if(timercmp(&curtime,&s->stoptime,>)) {
177
debug(D_POLL,"waking pid %d because time expired",pid);
179
pfs_process_wake(pid);
183
} else if(errno==EBADF) {
184
debug(D_POLL,"select returned EBADF, which really shouldn't happen.");
185
debug(D_POLL,"waking up all processes to clean up and try again.");
190
debug(D_POLL,"waking pid %d",pid);
192
pfs_process_wake(pid);
198
void pfs_poll_wakeon( int fd, int flags )
200
struct poll_entry *p;
203
debug(D_POLL,"wake on fd %d flags %s",fd,pfs_poll_string(flags));
205
for(i=0;i<POLL_TABLE_MAX;i++) {
209
p->pid = pfs_process_getpid();
211
if(i>=poll_table_size) poll_table_size=i+1;
216
fatal("ran out of poll table space!");
219
void pfs_poll_wakein( struct timeval tv )
221
struct sleep_entry *s;
224
debug(D_POLL,"wake in time %d.%06d",tv.tv_sec,tv.tv_usec);
226
for(i=0;i<SLEEP_TABLE_MAX;i++) {
229
s->pid = pfs_process_getpid();
230
gettimeofday(&s->stoptime,0);
231
s->stoptime.tv_sec += tv.tv_sec;
232
s->stoptime.tv_usec += tv.tv_usec;
233
while(s->stoptime.tv_usec>1000000) {
234
s->stoptime.tv_sec++;
235
s->stoptime.tv_usec-=1000000;
237
if(i>=sleep_table_size) sleep_table_size=i+1;
242
fatal("ran out of sleep table space!");
245
char * pfs_poll_string( int flags )
248
if(flags&PFS_POLL_READ) {
253
if(flags&PFS_POLL_WRITE) {
258
if(flags&PFS_POLL_EXCEPT) {