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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
|
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
//#include "pen.h"
#include "diag.h"
#include "event.h"
#include "memory.h"
#ifdef HAVE_POLL
#include <poll.h>
static struct pollfd *poll_ufds;
static int poll_nfds, poll_count, poll_nfds_max;
static int pindex;
/* Making a sparse pollfd table, using fd as the index seems most efficient. */
/* Need to make sure to grow the table as necessary. */
static void poll_event_ctl(int fd, int events)
{
int pollevents = 0;
DEBUG(2, "poll_event_ctl(fd=%d, events=%d)", fd, events);
if (fd >= poll_nfds_max) {
int i, new_max = fd+10000;
DEBUG(2, "expanding poll_ufds to %d entries", new_max);
poll_ufds = pen_realloc(poll_ufds, new_max * sizeof *poll_ufds);
for (i = poll_nfds_max; i < new_max; i++) {
poll_ufds[i].fd = -1;
poll_ufds[i].events = 0;
}
poll_nfds_max = new_max;
}
if (events & EVENT_READ) pollevents |= POLLIN;
if (events & EVENT_WRITE) pollevents |= POLLOUT;
poll_ufds[fd].fd = fd;
poll_ufds[fd].events = pollevents;
if (fd >= poll_nfds) poll_nfds = fd+1;
}
static void poll_event_add(int fd, int events)
{
DEBUG(2, "poll_event_add(fd=%d, events=%d)", fd, events);
poll_event_ctl(fd, events);
}
static void poll_event_arm(int fd, int events)
{
DEBUG(2, "poll_event_arm(fd=%d, events=%d)", fd, events);
poll_event_ctl(fd, events);
}
static void poll_event_delete(int fd)
{
DEBUG(2, "poll_event_delete(fd=%d)", fd);
poll_ufds[fd].fd = -1; /* ignore events */
poll_ufds[fd].events = 0;
}
static void poll_event_wait(void)
{
DEBUG(2, "poll_event_wait()");
pindex = -1;
poll_count = poll(poll_ufds, poll_nfds, 1000*timeout);
DEBUG(2, "poll returns %d", poll_count);
if (poll_count < 0 && errno != EINTR) {
error("Error on poll: %s", strerror(errno));
}
}
static int poll_event_fd(int *revents)
{
int events = 0;
DEBUG(2, "poll_event_fd(revents=%p)", revents);
for (pindex++; pindex < poll_nfds; pindex++) {
DEBUG(3, "\tpoll_ufds[%d] = {fd=%d, revents=%d}", pindex, poll_ufds[pindex].fd, poll_ufds[pindex].revents);
if (poll_ufds[pindex].revents & POLLIN) events |= EVENT_READ;
if (poll_ufds[pindex].revents & POLLOUT) events |= EVENT_WRITE;
if (events) {
*revents = events;
return poll_ufds[pindex].fd;
}
}
return -1;
}
void poll_init(void)
{
DEBUG(2, "poll_init()");
poll_nfds = poll_nfds_max = 0;
poll_ufds = NULL;
event_add = poll_event_add;
event_arm = poll_event_arm;
event_delete = poll_event_delete;
event_wait = poll_event_wait;
event_fd = poll_event_fd;
}
#else
void poll_init(void)
{
debug("You don't have poll");
exit(EXIT_FAILURE);
}
#endif
|