This source file includes following definitions.
- hashsocket
- eqsocket
- evmap_io_initmap
- evmap_io_clear
- evmap_io_initmap
- evmap_io_clear
- evmap_make_space
- evmap_signal_initmap
- evmap_signal_clear
- evmap_io_init
- evmap_io_add
- evmap_io_del
- evmap_io_active
- evmap_signal_init
- evmap_signal_add
- evmap_signal_del
- evmap_signal_active
- evmap_io_get_fdinfo
- event_changelist_init
- event_change_get_fdinfo
- event_changelist_check
- event_changelist_remove_all
- event_changelist_freemem
- event_changelist_grow
- event_changelist_get_or_construct
- event_changelist_add
- event_changelist_del
- evmap_check_integrity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 #include "event2/event-config.h"
27
28 #ifdef WIN32
29 #include <winsock2.h>
30 #define WIN32_LEAN_AND_MEAN
31 #include <windows.h>
32 #undef WIN32_LEAN_AND_MEAN
33 #endif
34 #include <sys/types.h>
35 #if !defined(WIN32) && defined(_EVENT_HAVE_SYS_TIME_H)
36 #include <sys/time.h>
37 #endif
38 #include <sys/queue.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #ifndef WIN32
42 #include <unistd.h>
43 #endif
44 #include <errno.h>
45 #include <signal.h>
46 #include <string.h>
47 #include <time.h>
48
49 #include "event-internal.h"
50 #include "evmap-internal.h"
51 #include "mm-internal.h"
52 #include "changelist-internal.h"
53
54
55
56
57 struct evmap_io {
58 struct event_list events;
59 ev_uint16_t nread;
60 ev_uint16_t nwrite;
61 };
62
63
64
65 struct evmap_signal {
66 struct event_list events;
67 };
68
69
70
71
72
73
74
75
76 #ifdef EVMAP_USE_HT
77 struct event_map_entry {
78 HT_ENTRY(event_map_entry) map_node;
79 evutil_socket_t fd;
80 union {
81
82 struct evmap_io evmap_io;
83 } ent;
84 };
85
86
87
88 static inline unsigned
89 hashsocket(struct event_map_entry *e)
90 {
91
92
93
94 unsigned h = (unsigned) e->fd;
95 h += (h >> 2) | (h << 30);
96 return h;
97 }
98
99
100
101 static inline int
102 eqsocket(struct event_map_entry *e1, struct event_map_entry *e2)
103 {
104 return e1->fd == e2->fd;
105 }
106
107 HT_PROTOTYPE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket)
108 HT_GENERATE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket,
109 0.5, mm_malloc, mm_realloc, mm_free)
110
111 #define GET_IO_SLOT(x, map, slot, type) \
112 do { \
113 struct event_map_entry _key, *_ent; \
114 _key.fd = slot; \
115 _ent = HT_FIND(event_io_map, map, &_key); \
116 (x) = _ent ? &_ent->ent.type : NULL; \
117 } while (0);
118
119 #define GET_IO_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \
120 do { \
121 struct event_map_entry _key, *_ent; \
122 _key.fd = slot; \
123 _HT_FIND_OR_INSERT(event_io_map, map_node, hashsocket, map, \
124 event_map_entry, &_key, ptr, \
125 { \
126 _ent = *ptr; \
127 }, \
128 { \
129 _ent = mm_calloc(1,sizeof(struct event_map_entry)+fdinfo_len); \
130 if (EVUTIL_UNLIKELY(_ent == NULL)) \
131 return (-1); \
132 _ent->fd = slot; \
133 (ctor)(&_ent->ent.type); \
134 _HT_FOI_INSERT(map_node, map, &_key, _ent, ptr) \
135 }); \
136 (x) = &_ent->ent.type; \
137 } while (0)
138
139 void evmap_io_initmap(struct event_io_map *ctx)
140 {
141 HT_INIT(event_io_map, ctx);
142 }
143
144 void evmap_io_clear(struct event_io_map *ctx)
145 {
146 struct event_map_entry **ent, **next, *this;
147 for (ent = HT_START(event_io_map, ctx); ent; ent = next) {
148 this = *ent;
149 next = HT_NEXT_RMV(event_io_map, ctx, ent);
150 mm_free(this);
151 }
152 HT_CLEAR(event_io_map, ctx);
153 }
154 #endif
155
156
157
158
159 #define GET_SIGNAL_SLOT(x, map, slot, type) \
160 (x) = (struct type *)((map)->entries[slot])
161
162
163
164
165
166 #define GET_SIGNAL_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \
167 do { \
168 if ((map)->entries[slot] == NULL) { \
169 (map)->entries[slot] = \
170 mm_calloc(1,sizeof(struct type)+fdinfo_len); \
171 if (EVUTIL_UNLIKELY((map)->entries[slot] == NULL)) \
172 return (-1); \
173 (ctor)((struct type *)(map)->entries[slot]); \
174 } \
175 (x) = (struct type *)((map)->entries[slot]); \
176 } while (0)
177
178
179
180 #ifndef EVMAP_USE_HT
181 #define GET_IO_SLOT(x,map,slot,type) GET_SIGNAL_SLOT(x,map,slot,type)
182 #define GET_IO_SLOT_AND_CTOR(x,map,slot,type,ctor,fdinfo_len) \
183 GET_SIGNAL_SLOT_AND_CTOR(x,map,slot,type,ctor,fdinfo_len)
184 #define FDINFO_OFFSET sizeof(struct evmap_io)
185 void
186 evmap_io_initmap(struct event_io_map* ctx)
187 {
188 evmap_signal_initmap(ctx);
189 }
190 void
191 evmap_io_clear(struct event_io_map* ctx)
192 {
193 evmap_signal_clear(ctx);
194 }
195 #endif
196
197
198
199
200
201 static int
202 evmap_make_space(struct event_signal_map *map, int slot, int msize)
203 {
204 if (map->nentries <= slot) {
205 int nentries = map->nentries ? map->nentries : 32;
206 void **tmp;
207
208 while (nentries <= slot)
209 nentries <<= 1;
210
211 tmp = (void **)mm_realloc(map->entries, nentries * msize);
212 if (tmp == NULL)
213 return (-1);
214
215 memset(&tmp[map->nentries], 0,
216 (nentries - map->nentries) * msize);
217
218 map->nentries = nentries;
219 map->entries = tmp;
220 }
221
222 return (0);
223 }
224
225 void
226 evmap_signal_initmap(struct event_signal_map *ctx)
227 {
228 ctx->nentries = 0;
229 ctx->entries = NULL;
230 }
231
232 void
233 evmap_signal_clear(struct event_signal_map *ctx)
234 {
235 if (ctx->entries != NULL) {
236 int i;
237 for (i = 0; i < ctx->nentries; ++i) {
238 if (ctx->entries[i] != NULL)
239 mm_free(ctx->entries[i]);
240 }
241 mm_free(ctx->entries);
242 ctx->entries = NULL;
243 }
244 ctx->nentries = 0;
245 }
246
247
248
249
250
251 static void
252 evmap_io_init(struct evmap_io *entry)
253 {
254 TAILQ_INIT(&entry->events);
255 entry->nread = 0;
256 entry->nwrite = 0;
257 }
258
259
260
261
262 int
263 evmap_io_add(struct event_base *base, evutil_socket_t fd, struct event *ev)
264 {
265 const struct eventop *evsel = base->evsel;
266 struct event_io_map *io = &base->io;
267 struct evmap_io *ctx = NULL;
268 int nread, nwrite, retval = 0;
269 short res = 0, old = 0;
270 struct event *old_ev;
271
272 EVUTIL_ASSERT(fd == ev->ev_fd);
273
274 if (fd < 0)
275 return 0;
276
277 #ifndef EVMAP_USE_HT
278 if (fd >= io->nentries) {
279 if (evmap_make_space(io, fd, sizeof(struct evmap_io *)) == -1)
280 return (-1);
281 }
282 #endif
283 GET_IO_SLOT_AND_CTOR(ctx, io, fd, evmap_io, evmap_io_init,
284 evsel->fdinfo_len);
285
286 nread = ctx->nread;
287 nwrite = ctx->nwrite;
288
289 if (nread)
290 old |= EV_READ;
291 if (nwrite)
292 old |= EV_WRITE;
293
294 if (ev->ev_events & EV_READ) {
295 if (++nread == 1)
296 res |= EV_READ;
297 }
298 if (ev->ev_events & EV_WRITE) {
299 if (++nwrite == 1)
300 res |= EV_WRITE;
301 }
302 if (EVUTIL_UNLIKELY(nread > 0xffff || nwrite > 0xffff)) {
303 event_warnx("Too many events reading or writing on fd %d",
304 (int)fd);
305 return -1;
306 }
307 if (EVENT_DEBUG_MODE_IS_ON() &&
308 (old_ev = TAILQ_FIRST(&ctx->events)) &&
309 (old_ev->ev_events&EV_ET) != (ev->ev_events&EV_ET)) {
310 event_warnx("Tried to mix edge-triggered and non-edge-triggered"
311 " events on fd %d", (int)fd);
312 return -1;
313 }
314
315 if (res) {
316 void *extra = ((char*)ctx) + sizeof(struct evmap_io);
317
318
319
320 if (evsel->add(base, ev->ev_fd,
321 old, (ev->ev_events & EV_ET) | res, extra) == -1)
322 return (-1);
323 retval = 1;
324 }
325
326 ctx->nread = (ev_uint16_t) nread;
327 ctx->nwrite = (ev_uint16_t) nwrite;
328 TAILQ_INSERT_TAIL(&ctx->events, ev, ev_io_next);
329
330 return (retval);
331 }
332
333
334
335 int
336 evmap_io_del(struct event_base *base, evutil_socket_t fd, struct event *ev)
337 {
338 const struct eventop *evsel = base->evsel;
339 struct event_io_map *io = &base->io;
340 struct evmap_io *ctx;
341 int nread, nwrite, retval = 0;
342 short res = 0, old = 0;
343
344 if (fd < 0)
345 return 0;
346
347 EVUTIL_ASSERT(fd == ev->ev_fd);
348
349 #ifndef EVMAP_USE_HT
350 if (fd >= io->nentries)
351 return (-1);
352 #endif
353
354 GET_IO_SLOT(ctx, io, fd, evmap_io);
355
356 nread = ctx->nread;
357 nwrite = ctx->nwrite;
358
359 if (nread)
360 old |= EV_READ;
361 if (nwrite)
362 old |= EV_WRITE;
363
364 if (ev->ev_events & EV_READ) {
365 if (--nread == 0)
366 res |= EV_READ;
367 EVUTIL_ASSERT(nread >= 0);
368 }
369 if (ev->ev_events & EV_WRITE) {
370 if (--nwrite == 0)
371 res |= EV_WRITE;
372 EVUTIL_ASSERT(nwrite >= 0);
373 }
374
375 if (res) {
376 void *extra = ((char*)ctx) + sizeof(struct evmap_io);
377 if (evsel->del(base, ev->ev_fd, old, res, extra) == -1)
378 return (-1);
379 retval = 1;
380 }
381
382 ctx->nread = nread;
383 ctx->nwrite = nwrite;
384 TAILQ_REMOVE(&ctx->events, ev, ev_io_next);
385
386 return (retval);
387 }
388
389 void
390 evmap_io_active(struct event_base *base, evutil_socket_t fd, short events)
391 {
392 struct event_io_map *io = &base->io;
393 struct evmap_io *ctx;
394 struct event *ev;
395
396 #ifndef EVMAP_USE_HT
397 EVUTIL_ASSERT(fd < io->nentries);
398 #endif
399 GET_IO_SLOT(ctx, io, fd, evmap_io);
400
401 EVUTIL_ASSERT(ctx);
402 TAILQ_FOREACH(ev, &ctx->events, ev_io_next) {
403 if (ev->ev_events & events)
404 event_active_nolock(ev, ev->ev_events & events, 1);
405 }
406 }
407
408
409
410 static void
411 evmap_signal_init(struct evmap_signal *entry)
412 {
413 TAILQ_INIT(&entry->events);
414 }
415
416
417 int
418 evmap_signal_add(struct event_base *base, int sig, struct event *ev)
419 {
420 const struct eventop *evsel = base->evsigsel;
421 struct event_signal_map *map = &base->sigmap;
422 struct evmap_signal *ctx = NULL;
423
424 if (sig >= map->nentries) {
425 if (evmap_make_space(
426 map, sig, sizeof(struct evmap_signal *)) == -1)
427 return (-1);
428 }
429 GET_SIGNAL_SLOT_AND_CTOR(ctx, map, sig, evmap_signal, evmap_signal_init,
430 base->evsigsel->fdinfo_len);
431
432 if (TAILQ_EMPTY(&ctx->events)) {
433 if (evsel->add(base, ev->ev_fd, 0, EV_SIGNAL, NULL)
434 == -1)
435 return (-1);
436 }
437
438 TAILQ_INSERT_TAIL(&ctx->events, ev, ev_signal_next);
439
440 return (1);
441 }
442
443 int
444 evmap_signal_del(struct event_base *base, int sig, struct event *ev)
445 {
446 const struct eventop *evsel = base->evsigsel;
447 struct event_signal_map *map = &base->sigmap;
448 struct evmap_signal *ctx;
449
450 if (sig >= map->nentries)
451 return (-1);
452
453 GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal);
454
455 if (TAILQ_FIRST(&ctx->events) == TAILQ_LAST(&ctx->events, event_list)) {
456 if (evsel->del(base, ev->ev_fd, 0, EV_SIGNAL, NULL) == -1)
457 return (-1);
458 }
459
460 TAILQ_REMOVE(&ctx->events, ev, ev_signal_next);
461
462 return (1);
463 }
464
465 void
466 evmap_signal_active(struct event_base *base, evutil_socket_t sig, int ncalls)
467 {
468 struct event_signal_map *map = &base->sigmap;
469 struct evmap_signal *ctx;
470 struct event *ev;
471
472 EVUTIL_ASSERT(sig < map->nentries);
473 GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal);
474
475 TAILQ_FOREACH(ev, &ctx->events, ev_signal_next)
476 event_active_nolock(ev, EV_SIGNAL, ncalls);
477 }
478
479 void *
480 evmap_io_get_fdinfo(struct event_io_map *map, evutil_socket_t fd)
481 {
482 struct evmap_io *ctx;
483 GET_IO_SLOT(ctx, map, fd, evmap_io);
484 if (ctx)
485 return ((char*)ctx) + sizeof(struct evmap_io);
486 else
487 return NULL;
488 }
489
490
491
492
493 struct event_changelist_fdinfo {
494 int idxplus1;
495
496 };
497
498 void
499 event_changelist_init(struct event_changelist *changelist)
500 {
501 changelist->changes = NULL;
502 changelist->changes_size = 0;
503 changelist->n_changes = 0;
504 }
505
506
507 static inline struct event_changelist_fdinfo *
508 event_change_get_fdinfo(struct event_base *base,
509 const struct event_change *change)
510 {
511 char *ptr;
512 if (change->read_change & EV_CHANGE_SIGNAL) {
513 struct evmap_signal *ctx;
514 GET_SIGNAL_SLOT(ctx, &base->sigmap, change->fd, evmap_signal);
515 ptr = ((char*)ctx) + sizeof(struct evmap_signal);
516 } else {
517 struct evmap_io *ctx;
518 GET_IO_SLOT(ctx, &base->io, change->fd, evmap_io);
519 ptr = ((char*)ctx) + sizeof(struct evmap_io);
520 }
521 return (void*)ptr;
522 }
523
524 #ifdef DEBUG_CHANGELIST
525
526 static void
527 event_changelist_check(struct event_base *base)
528 {
529 int i;
530 struct event_changelist *changelist = &base->changelist;
531
532 EVUTIL_ASSERT(changelist->changes_size >= changelist->n_changes);
533 for (i = 0; i < changelist->n_changes; ++i) {
534 struct event_change *c = &changelist->changes[i];
535 struct event_changelist_fdinfo *f;
536 EVUTIL_ASSERT(c->fd >= 0);
537 f = event_change_get_fdinfo(base, c);
538 EVUTIL_ASSERT(f);
539 EVUTIL_ASSERT(f->idxplus1 == i + 1);
540 }
541
542 for (i = 0; i < base->io.nentries; ++i) {
543 struct evmap_io *io = base->io.entries[i];
544 struct event_changelist_fdinfo *f;
545 if (!io)
546 continue;
547 f = (void*)
548 ( ((char*)io) + sizeof(struct evmap_io) );
549 if (f->idxplus1) {
550 struct event_change *c = &changelist->changes[f->idxplus1 - 1];
551 EVUTIL_ASSERT(c->fd == i);
552 }
553 }
554 }
555 #else
556 #define event_changelist_check(base) ((void)0)
557 #endif
558
559 void
560 event_changelist_remove_all(struct event_changelist *changelist,
561 struct event_base *base)
562 {
563 int i;
564
565 event_changelist_check(base);
566
567 for (i = 0; i < changelist->n_changes; ++i) {
568 struct event_change *ch = &changelist->changes[i];
569 struct event_changelist_fdinfo *fdinfo =
570 event_change_get_fdinfo(base, ch);
571 EVUTIL_ASSERT(fdinfo->idxplus1 == i + 1);
572 fdinfo->idxplus1 = 0;
573 }
574
575 changelist->n_changes = 0;
576
577 event_changelist_check(base);
578 }
579
580 void
581 event_changelist_freemem(struct event_changelist *changelist)
582 {
583 if (changelist->changes)
584 mm_free(changelist->changes);
585 event_changelist_init(changelist);
586 }
587
588
589 static int
590 event_changelist_grow(struct event_changelist *changelist)
591 {
592 int new_size;
593 struct event_change *new_changes;
594 if (changelist->changes_size < 64)
595 new_size = 64;
596 else
597 new_size = changelist->changes_size * 2;
598
599 new_changes = mm_realloc(changelist->changes,
600 new_size * sizeof(struct event_change));
601
602 if (EVUTIL_UNLIKELY(new_changes == NULL))
603 return (-1);
604
605 changelist->changes = new_changes;
606 changelist->changes_size = new_size;
607
608 return (0);
609 }
610
611
612
613
614
615 static struct event_change *
616 event_changelist_get_or_construct(struct event_changelist *changelist,
617 evutil_socket_t fd,
618 short old_events,
619 struct event_changelist_fdinfo *fdinfo)
620 {
621 struct event_change *change;
622
623 if (fdinfo->idxplus1 == 0) {
624 int idx;
625 EVUTIL_ASSERT(changelist->n_changes <= changelist->changes_size);
626
627 if (changelist->n_changes == changelist->changes_size) {
628 if (event_changelist_grow(changelist) < 0)
629 return NULL;
630 }
631
632 idx = changelist->n_changes++;
633 change = &changelist->changes[idx];
634 fdinfo->idxplus1 = idx + 1;
635
636 memset(change, 0, sizeof(struct event_change));
637 change->fd = fd;
638 change->old_events = old_events;
639 } else {
640 change = &changelist->changes[fdinfo->idxplus1 - 1];
641 EVUTIL_ASSERT(change->fd == fd);
642 }
643 return change;
644 }
645
646 int
647 event_changelist_add(struct event_base *base, evutil_socket_t fd, short old, short events,
648 void *p)
649 {
650 struct event_changelist *changelist = &base->changelist;
651 struct event_changelist_fdinfo *fdinfo = p;
652 struct event_change *change;
653
654 event_changelist_check(base);
655
656 change = event_changelist_get_or_construct(changelist, fd, old, fdinfo);
657 if (!change)
658 return -1;
659
660
661
662
663
664 if (events & (EV_READ|EV_SIGNAL)) {
665 change->read_change = EV_CHANGE_ADD |
666 (events & (EV_ET|EV_PERSIST|EV_SIGNAL));
667 }
668 if (events & EV_WRITE) {
669 change->write_change = EV_CHANGE_ADD |
670 (events & (EV_ET|EV_PERSIST|EV_SIGNAL));
671 }
672
673 event_changelist_check(base);
674 return (0);
675 }
676
677 int
678 event_changelist_del(struct event_base *base, evutil_socket_t fd, short old, short events,
679 void *p)
680 {
681 struct event_changelist *changelist = &base->changelist;
682 struct event_changelist_fdinfo *fdinfo = p;
683 struct event_change *change;
684
685 event_changelist_check(base);
686 change = event_changelist_get_or_construct(changelist, fd, old, fdinfo);
687 event_changelist_check(base);
688 if (!change)
689 return -1;
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709 if (events & (EV_READ|EV_SIGNAL)) {
710 if (!(change->old_events & (EV_READ | EV_SIGNAL)) &&
711 (change->read_change & EV_CHANGE_ADD))
712 change->read_change = 0;
713 else
714 change->read_change = EV_CHANGE_DEL;
715 }
716 if (events & EV_WRITE) {
717 if (!(change->old_events & EV_WRITE) &&
718 (change->write_change & EV_CHANGE_ADD))
719 change->write_change = 0;
720 else
721 change->write_change = EV_CHANGE_DEL;
722 }
723
724 event_changelist_check(base);
725 return (0);
726 }
727
728 void
729 evmap_check_integrity(struct event_base *base)
730 {
731 #define EVLIST_X_SIGFOUND 0x1000
732 #define EVLIST_X_IOFOUND 0x2000
733
734 evutil_socket_t i;
735 struct event *ev;
736 struct event_io_map *io = &base->io;
737 struct event_signal_map *sigmap = &base->sigmap;
738 #ifdef EVMAP_USE_HT
739 struct event_map_entry **mapent;
740 #endif
741 int nsignals, ntimers, nio;
742 nsignals = ntimers = nio = 0;
743
744 TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
745 EVUTIL_ASSERT(ev->ev_flags & EVLIST_INSERTED);
746 EVUTIL_ASSERT(ev->ev_flags & EVLIST_INIT);
747 ev->ev_flags &= ~(EVLIST_X_SIGFOUND|EVLIST_X_IOFOUND);
748 }
749
750 #ifdef EVMAP_USE_HT
751 HT_FOREACH(mapent, event_io_map, io) {
752 struct evmap_io *ctx = &(*mapent)->ent.evmap_io;
753 i = (*mapent)->fd;
754 #else
755 for (i = 0; i < io->nentries; ++i) {
756 struct evmap_io *ctx = io->entries[i];
757
758 if (!ctx)
759 continue;
760 #endif
761
762 TAILQ_FOREACH(ev, &ctx->events, ev_io_next) {
763 EVUTIL_ASSERT(!(ev->ev_flags & EVLIST_X_IOFOUND));
764 EVUTIL_ASSERT(ev->ev_fd == i);
765 ev->ev_flags |= EVLIST_X_IOFOUND;
766 nio++;
767 }
768 }
769
770 for (i = 0; i < sigmap->nentries; ++i) {
771 struct evmap_signal *ctx = sigmap->entries[i];
772 if (!ctx)
773 continue;
774
775 TAILQ_FOREACH(ev, &ctx->events, ev_signal_next) {
776 EVUTIL_ASSERT(!(ev->ev_flags & EVLIST_X_SIGFOUND));
777 EVUTIL_ASSERT(ev->ev_fd == i);
778 ev->ev_flags |= EVLIST_X_SIGFOUND;
779 nsignals++;
780 }
781 }
782
783 TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
784 if (ev->ev_events & (EV_READ|EV_WRITE)) {
785 EVUTIL_ASSERT(ev->ev_flags & EVLIST_X_IOFOUND);
786 --nio;
787 }
788 if (ev->ev_events & EV_SIGNAL) {
789 EVUTIL_ASSERT(ev->ev_flags & EVLIST_X_SIGFOUND);
790 --nsignals;
791 }
792 }
793
794 EVUTIL_ASSERT(nio == 0);
795 EVUTIL_ASSERT(nsignals == 0);
796
797
798
799 }