2 * ircd-ratbox: A slightly useful ircd.
3 * s_bsd_devpoll.c: /dev/poll compatible network routines.
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2001 Adrian Chadd <adrian@creative.net.au>
8 * Copyright (C) 2002-2005 ircd-ratbox development team
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25 * $Id: devpoll.c 21876 2006-02-21 19:12:53Z androsyn $
32 #include <sys/devpoll.h>
39 #include "irc_string.h"
55 static void devpoll_update_events(int, short, PF
*);
58 static struct pollfd
*npollfds
;
59 static void devpoll_update_events(int, short, PF
*);
60 static void devpoll_write_update(int, int);
63 /* #define NOTYET 1 */
65 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
66 /* Private functions */
76 * Write an update to the devpoll filter.
77 * See, we end up having to do a seperate (?) remove before we do an
78 * add of a new polltype, so we have to have this function seperate from
82 devpoll_write_update(int fd
, int events
)
84 struct pollfd pollfds
[1]; /* Just to be careful */
87 /* Build the pollfd entry */
88 pollfds
[0].revents
= 0;
90 pollfds
[0].events
= events
;
92 /* Write the thing to our poll fd */
93 retval
= write(dpfd
, &pollfds
[0], sizeof(struct pollfd
));
94 if(retval
!= sizeof(struct pollfd
))
96 "devpoll_write_update: dpfd write failed %d: %s", errno
, strerror(errno
));
101 devpoll_update_events(int fd
, short filter
, PF
* handler
)
103 int update_required
= 0;
104 int cur_mask
= fdmask
[fd
];
109 case COMM_SELECT_READ
:
110 cur_handler
= fd_table
[fd
].read_handler
;
112 fdmask
[fd
] |= POLLRDNORM
;
114 fdmask
[fd
] &= ~POLLRDNORM
;
115 if(fd_table
[fd
].write_handler
)
116 fdmask
[fd
] |= POLLWRNORM
;
118 case COMM_SELECT_WRITE
:
119 cur_handler
= fd_table
[fd
].write_handler
;
121 fdmask
[fd
] |= POLLWRNORM
;
123 fdmask
[fd
] &= ~POLLWRNORM
;
124 if(fd_table
[fd
].read_handler
)
125 fdmask
[fd
] |= POLLRDNORM
;
129 ilog(L_IOERROR
, "devpoll_update_events called with unknown filter: %hd", filter
);
135 if(cur_handler
== NULL
&& handler
!= NULL
)
137 else if(cur_handler
!= NULL
&& handler
== NULL
)
139 if(cur_mask
!= fdmask
[fd
])
144 * Ok, we can call devpoll_write_update() here now to re-build the
145 * fd struct. If we end up with nothing on this fd, it won't write
150 devpoll_write_update(fd
, POLLREMOVE
);
151 devpoll_write_update(fd
, fdmask
[fd
]);
154 devpoll_write_update(fd
, POLLREMOVE
);
162 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
163 /* Public functions */
169 * This is a needed exported function which will be called to initialise
170 * the network loop code.
175 maxfd
= getdtablesize() - 2; /* This makes more sense than HARD_FDLIMIT */
176 fdmask
= MyMalloc(sizeof(fdmask
) * maxfd
+ 1);
177 npollfds
= MyMalloc(sizeof(struct pollfd
) * maxfd
+ 1);
179 dpfd
= open("/dev/poll", O_RDWR
);
183 "init_netio: Couldn't open /dev/poll - %d: %s\n",
184 errno
, strerror(errno
));
185 exit(115); /* Whee! */
192 * This is a needed exported function which will be called to register
193 * and deregister interest in a pending IO state for a given FD.
196 comm_setselect(int fd
, fdlist_t list
, unsigned int type
, PF
* handler
,
199 fde_t
*F
= &fd_table
[fd
];
201 s_assert(F
->flags
.open
);
203 /* Update the list, even though we're not using it .. */
206 if(type
& COMM_SELECT_READ
)
208 devpoll_update_events(fd
, COMM_SELECT_READ
, handler
);
209 F
->read_handler
= handler
;
210 F
->read_data
= client_data
;
212 if(type
& COMM_SELECT_WRITE
)
214 devpoll_update_events(fd
, COMM_SELECT_WRITE
, handler
);
215 F
->write_handler
= handler
;
216 F
->write_data
= client_data
;
221 * Check all connections for new connections and input data that is to be
222 * processed. Also check for connections with data queued and whether we can
229 * Called to do the new-style IO, courtesy of squid (like most of this
230 * new IO code). This routine handles the stuff we've hidden in
231 * comm_setselect and fd_table[] and calls callbacks for IO ready
236 comm_select(unsigned long delay
)
239 struct dvpoll dopoll
;
245 dopoll
.dp_timeout
= delay
;
246 dopoll
.dp_nfds
= maxfd
;
247 dopoll
.dp_fds
= npollfds
;
248 num
= ioctl(dpfd
, DP_POLL
, &dopoll
);
251 if(ignoreErrno(errno
))
261 for (i
= 0; i
< num
; i
++)
263 int fd
= dopoll
.dp_fds
[i
].fd
;
265 fde_t
*F
= &fd_table
[fd
];
266 if((dopoll
.dp_fds
[i
].
267 revents
& (POLLRDNORM
| POLLIN
| POLLHUP
|
269 && (dopoll
.dp_fds
[i
].events
& (POLLRDNORM
| POLLIN
)))
271 if((hdl
= F
->read_handler
) != NULL
)
273 F
->read_handler
= NULL
;
274 hdl(fd
, F
->read_data
);
276 * this call used to be with a NULL pointer, BUT
277 * in the devpoll case we only want to update the
278 * poll set *if* the handler changes state (active ->
279 * NULL or vice versa.)
281 devpoll_update_events(fd
,
282 COMM_SELECT_READ
, F
->read_handler
);
286 "comm_select: Unhandled read event: fdmask: %x",
290 if(F
->flags
.open
== 0)
291 continue; /* Read handler closed us..go on to do something more useful */
292 if((dopoll
.dp_fds
[i
].
293 revents
& (POLLWRNORM
| POLLOUT
| POLLHUP
|
295 && (dopoll
.dp_fds
[i
].events
& (POLLWRNORM
| POLLOUT
)))
297 if((hdl
= F
->write_handler
) != NULL
)
299 F
->write_handler
= NULL
;
300 hdl(fd
, F
->write_data
);
301 /* See above similar code in the read case */
302 devpoll_update_events(fd
,
303 COMM_SELECT_WRITE
, F
->write_handler
);
307 "comm_select: Unhandled write event: fdmask: %x",
311 if(dopoll
.dp_fds
[i
].revents
& POLLNVAL
)
313 ilog(L_IOERROR
, "revents was Invalid for %d", fd
);
319 /* XXX Get here, we broke! */