2 * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
3 * Copyright 2003 Michael A. Davis <mike@datanerds.net>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 /* Avoid the windows/msvc thing. */
32 #include "../config.h"
37 #include <sys/types.h>
38 #include <sys/queue.h>
46 #define RB_AUGMENT(x) (void)(x)
50 #include "event-internal.h"
52 #define XFREE(ptr) do { if (ptr) free(ptr); } while(0)
54 extern struct event_list timequeue
;
55 extern struct event_list addqueue
;
57 extern struct event_list signalqueue
;
65 int evsigcaught
[NSIG
];
66 volatile sig_atomic_t signal_caught
= 0;
67 /* MSDN says this is required to handle SIGFPE */
68 volatile double SIGFPE_REQ
= 0.0f
;
71 static void signal_handler(int sig
);
73 void signal_process(void);
74 int signal_recalc(void);
78 RB_ENTRY(event_entry
) node
;
82 struct event
*read_event
;
83 struct event
*write_event
;
87 compare(struct event_entry
*a
, struct event_entry
*b
)
89 if (a
->sock
< b
->sock
)
91 else if (a
->sock
> b
->sock
)
99 struct win_fd_set
*readset_in
;
100 struct win_fd_set
*writeset_in
;
101 struct win_fd_set
*readset_out
;
102 struct win_fd_set
*writeset_out
;
103 struct win_fd_set
*exset_out
;
104 RB_HEAD(event_map
, event_entry
) event_root
;
106 unsigned signals_are_broken
: 1;
109 RB_PROTOTYPE(event_map
, event_entry
, node
, compare
);
110 RB_GENERATE(event_map
, event_entry
, node
, compare
);
112 void *win32_init (struct event_base
*);
113 int win32_insert (void *, struct event
*);
114 int win32_del (void *, struct event
*);
115 int win32_dispatch (struct event_base
*base
, void *, struct timeval
*);
116 void win32_dealloc (struct event_base
*, void *);
118 struct eventop win32ops
= {
128 #define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET)))
131 realloc_fd_sets(struct win32op
*op
, size_t new_size
)
135 assert(new_size
>= op
->readset_in
->fd_count
&&
136 new_size
>= op
->writeset_in
->fd_count
);
137 assert(new_size
>= 1);
139 size
= FD_SET_ALLOC_SIZE(new_size
);
140 if (!(op
->readset_in
= realloc(op
->readset_in
, size
)))
142 if (!(op
->writeset_in
= realloc(op
->writeset_in
, size
)))
144 if (!(op
->readset_out
= realloc(op
->readset_out
, size
)))
146 if (!(op
->exset_out
= realloc(op
->exset_out
, size
)))
148 if (!(op
->writeset_out
= realloc(op
->writeset_out
, size
)))
150 op
->fd_setsz
= new_size
;
155 timeval_to_ms(struct timeval
*tv
)
157 return ((tv
->tv_sec
* 1000) + (tv
->tv_usec
/ 1000));
160 static struct event_entry
*
161 get_event_entry(struct win32op
*op
, SOCKET s
, int create
)
163 struct event_entry key
, *val
;
165 val
= RB_FIND(event_map
, &op
->event_root
, &key
);
168 if (!(val
= calloc(1, sizeof(struct event_entry
)))) {
169 event_warn("%s: calloc", __func__
);
173 val
->read_pos
= val
->write_pos
= -1;
174 RB_INSERT(event_map
, &op
->event_root
, val
);
179 do_fd_set(struct win32op
*op
, struct event_entry
*ent
, int read
)
181 SOCKET s
= ent
->sock
;
182 struct win_fd_set
*set
= read
? op
->readset_in
: op
->writeset_in
;
184 if (ent
->read_pos
>= 0)
187 if (ent
->write_pos
>= 0)
190 if (set
->fd_count
== op
->fd_setsz
) {
191 if (realloc_fd_sets(op
, op
->fd_setsz
*2))
193 /* set pointer will have changed and needs reiniting! */
194 set
= read
? op
->readset_in
: op
->writeset_in
;
196 set
->fd_array
[set
->fd_count
] = s
;
198 ent
->read_pos
= set
->fd_count
;
200 ent
->write_pos
= set
->fd_count
;
201 return (set
->fd_count
++);
205 do_fd_clear(struct win32op
*op
, struct event_entry
*ent
, int read
)
208 struct win_fd_set
*set
= read
? op
->readset_in
: op
->writeset_in
;
218 if (--set
->fd_count
!= i
) {
219 struct event_entry
*ent2
;
221 s2
= set
->fd_array
[i
] = set
->fd_array
[set
->fd_count
];
222 ent2
= get_event_entry(op
, s2
, 0);
223 if (!ent
) /* This indicates a bug. */
235 win32_init(struct event_base
*_base
)
237 struct win32op
*winop
;
239 if (!(winop
= calloc(1, sizeof(struct win32op
))))
241 winop
->fd_setsz
= NEVENT
;
242 size
= FD_SET_ALLOC_SIZE(NEVENT
);
243 if (!(winop
->readset_in
= malloc(size
)))
245 if (!(winop
->writeset_in
= malloc(size
)))
247 if (!(winop
->readset_out
= malloc(size
)))
249 if (!(winop
->writeset_out
= malloc(size
)))
251 if (!(winop
->exset_out
= malloc(size
)))
253 RB_INIT(&winop
->event_root
);
254 winop
->readset_in
->fd_count
= winop
->writeset_in
->fd_count
= 0;
255 winop
->readset_out
->fd_count
= winop
->writeset_out
->fd_count
256 = winop
->exset_out
->fd_count
= 0;
258 if (evsignal_init(_base
) < 0)
259 winop
->signals_are_broken
= 1;
263 XFREE(winop
->readset_in
);
264 XFREE(winop
->writeset_in
);
265 XFREE(winop
->readset_out
);
266 XFREE(winop
->writeset_out
);
267 XFREE(winop
->exset_out
);
273 win32_insert(void *op
, struct event
*ev
)
275 struct win32op
*win32op
= op
;
276 struct event_entry
*ent
;
278 if (ev
->ev_events
& EV_SIGNAL
) {
279 if (win32op
->signals_are_broken
)
281 return (evsignal_add(ev
));
283 if (!(ev
->ev_events
& (EV_READ
|EV_WRITE
)))
285 ent
= get_event_entry(win32op
, ev
->ev_fd
, 1);
287 return (-1); /* out of memory */
289 event_debug(("%s: adding event for %d", __func__
, (int)ev
->ev_fd
));
290 if (ev
->ev_events
& EV_READ
) {
291 if (do_fd_set(win32op
, ent
, 1)<0)
293 ent
->read_event
= ev
;
295 if (ev
->ev_events
& EV_WRITE
) {
296 if (do_fd_set(win32op
, ent
, 0)<0)
298 ent
->write_event
= ev
;
304 win32_del(void *op
, struct event
*ev
)
306 struct win32op
*win32op
= op
;
307 struct event_entry
*ent
;
309 if (ev
->ev_events
& EV_SIGNAL
)
310 return (evsignal_del(ev
));
312 if (!(ent
= get_event_entry(win32op
, ev
->ev_fd
, 0)))
314 event_debug(("%s: Removing event for %d", __func__
, ev
->ev_fd
));
315 if (ev
== ent
->read_event
) {
316 do_fd_clear(win32op
, ent
, 1);
317 ent
->read_event
= NULL
;
319 if (ev
== ent
->write_event
) {
320 do_fd_clear(win32op
, ent
, 0);
321 ent
->write_event
= NULL
;
323 if (!ent
->read_event
&& !ent
->write_event
) {
324 RB_REMOVE(event_map
, &win32op
->event_root
, ent
);
332 fd_set_copy(struct win_fd_set
*out
, const struct win_fd_set
*in
)
334 out
->fd_count
= in
->fd_count
;
335 memcpy(out
->fd_array
, in
->fd_array
, in
->fd_count
* (sizeof(SOCKET
)));
339 static void dump_fd_set(struct win_fd_set *s)
343 for(i=0;i<s->fd_count;++i)
344 printf("%d ",(int)s->fd_array[i]);
350 win32_dispatch(struct event_base
*base
, void *op
,
353 struct win32op
*win32op
= op
;
358 struct event_entry
*ent
;
360 fd_set_copy(win32op
->readset_out
, win32op
->readset_in
);
361 fd_set_copy(win32op
->exset_out
, win32op
->readset_in
);
362 fd_set_copy(win32op
->writeset_out
, win32op
->writeset_in
);
365 (win32op
->readset_out
->fd_count
> win32op
->writeset_out
->fd_count
) ?
366 win32op
->readset_out
->fd_count
: win32op
->writeset_out
->fd_count
;
369 /* Windows doesn't like you to call select() with no sockets */
370 Sleep(timeval_to_ms(tv
));
371 evsignal_process(base
);
375 res
= select(fd_count
,
376 (struct fd_set
*)win32op
->readset_out
,
377 (struct fd_set
*)win32op
->writeset_out
,
378 (struct fd_set
*)win32op
->exset_out
, tv
);
380 event_debug(("%s: select returned %d", __func__
, res
));
383 evsignal_process(base
);
385 } else if (base
->sig
.evsignal_caught
) {
386 evsignal_process(base
);
389 if (win32op
->readset_out
->fd_count
) {
390 i
= rand() % win32op
->readset_out
->fd_count
;
391 for (j
=0; j
<win32op
->readset_out
->fd_count
; ++j
) {
392 if (++i
>= win32op
->readset_out
->fd_count
)
394 s
= win32op
->readset_out
->fd_array
[i
];
395 if ((ent
= get_event_entry(win32op
, s
, 0)) && ent
->read_event
)
396 event_active(ent
->read_event
, EV_READ
, 1);
399 if (win32op
->exset_out
->fd_count
) {
400 i
= rand() % win32op
->exset_out
->fd_count
;
401 for (j
=0; j
<win32op
->exset_out
->fd_count
; ++j
) {
402 if (++i
>= win32op
->exset_out
->fd_count
)
404 s
= win32op
->exset_out
->fd_array
[i
];
405 if ((ent
= get_event_entry(win32op
, s
, 0)) && ent
->read_event
)
406 event_active(ent
->read_event
, EV_READ
, 1);
409 if (win32op
->writeset_out
->fd_count
) {
410 i
= rand() % win32op
->writeset_out
->fd_count
;
411 for (j
=0; j
<win32op
->writeset_out
->fd_count
; ++j
) {
412 if (++i
>= win32op
->exset_out
->fd_count
)
414 s
= win32op
->writeset_out
->fd_array
[i
];
415 if ((ent
= get_event_entry(win32op
, s
, 0)) && ent
->write_event
)
416 event_active(ent
->write_event
, EV_WRITE
, 1);
425 win32_dealloc(struct event_base
*_base
, void *arg
)
427 struct win32op
*win32op
= arg
;
429 evsignal_dealloc(_base
);
430 if (win32op
->readset_in
)
431 free(win32op
->readset_in
);
432 if (win32op
->writeset_in
)
433 free(win32op
->writeset_in
);
434 if (win32op
->readset_out
)
435 free(win32op
->readset_out
);
436 if (win32op
->writeset_out
)
437 free(win32op
->writeset_out
);
438 if (win32op
->exset_out
)
439 free(win32op
->exset_out
);
440 /* XXXXX free the tree. */
442 memset(win32op
, 0, sizeof(win32op
));
448 signal_handler(int sig
)
459 /* Reinstall our signal handler. */
460 TAILQ_FOREACH(ev
, &signalqueue
, ev_signal_next
) {
461 if((int)signal(EVENT_SIGNAL(ev
), signal_handler
) == -1)
473 TAILQ_FOREACH(ev
, &signalqueue
, ev_signal_next
) {
474 ncalls
= evsigcaught
[EVENT_SIGNAL(ev
)];
476 if (!(ev
->ev_events
& EV_PERSIST
))
478 event_active(ev
, EV_SIGNAL
, ncalls
);
482 memset(evsigcaught
, 0, sizeof(evsigcaught
));