summaryrefslogtreecommitdiff
path: root/core/event.c
diff options
context:
space:
mode:
authorUnbit <info@unbit.it>2013-03-13 14:33:38 +0100
committerUnbit <info@unbit.it>2013-03-13 14:33:38 +0100
commit88555e2c2073265f09b87f0cafe04e988d87198a (patch)
tree62f9fa65149ff317c9b307731aed1924f25b5a43 /core/event.c
parentec2bfcd3029b78b2441a111df8d9d0df4f30cd8c (diff)
downloaduwsgi-88555e2c2073265f09b87f0cafe04e988d87198a.tar.gz
improved poll() support
Diffstat (limited to 'core/event.c')
-rw-r--r--core/event.c109
1 files changed, 99 insertions, 10 deletions
diff --git a/core/event.c b/core/event.c
index 9fb90f28..6bb94732 100644
--- a/core/event.c
+++ b/core/event.c
@@ -12,7 +12,8 @@ struct uwsgi_poll_event {
int max_events;
struct pollfd *poll;
};
-struct uwsgi_poll_event *uwsgi_poll_event_queue[2048];
+
+struct uwsgi_poll_event **uwsgi_poll_event_queue;
static int uwsgi_poll_fd_is_registered(struct uwsgi_poll_event *upe, int fd) {
int i;
@@ -33,7 +34,28 @@ static int uwsgi_poll_fd_add(struct uwsgi_poll_event *upe, int fd, int event) {
return 0;
}
+static int uwsgi_poll_fd_del(struct uwsgi_poll_event *upe, int fd) {
+ int i;
+ for(i=0;i<upe->nevents;i++) {
+ if (upe->poll[i].fd == fd) {
+ if (i < upe->nevents-1) {
+ memcpy(&upe->poll[i], &upe->poll[i+1], sizeof(struct uwsgi_poll_event) * (upe->nevents - (i+1)));
+ }
+ upe->nevents--;
+ return 0;
+ }
+ }
+ return -1;
+}
+
static void uwsgi_poll_queue_rebuild(struct uwsgi_poll_event *upe) {
+ // we need to check if some file descriptor is no more valid
+ int i;
+ for(i=0;i<upe->nevents;i++) {
+ if (!uwsgi_valid_fd(upe->poll[i].fd)) {
+ uwsgi_poll_fd_del(upe, upe->poll[i].fd);
+ }
+ }
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
@@ -53,31 +75,53 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
}
int event_queue_init() {
+ if (!uwsgi_poll_event_queue) {
+ uwsgi_poll_event_queue = uwsgi_calloc(sizeof(struct uwsgi_poll_event *) * uwsgi.max_fd);
+ }
int eq = uwsgi_poll_event_queue_max;
uwsgi_poll_event_queue[eq] = uwsgi_calloc(sizeof(struct uwsgi_poll_event));
uwsgi_poll_event_queue_max++;
uwsgi_poll_event_queue[eq]->poll = uwsgi_malloc(sizeof(struct pollfd) * uwsgi.max_fd);
+ uwsgi_poll_event_queue[eq]->max_events = uwsgi.max_fd;
return eq;
}
void *event_queue_alloc(int nevents) {
- return uwsgi_malloc(sizeof(struct pollfd) * nevents);
+ return uwsgi_calloc(sizeof(struct pollfd) * nevents);
}
int event_queue_interesting_fd_is_read(void *events, int id) {
- return -1;
+ struct pollfd *pevents = (struct pollfd *)events;
+ struct pollfd *upoll = &pevents[id];
+ if (upoll->revents & POLLIN) {
+ return 1;
+ }
+ return 0;
}
int event_queue_fd_write_to_readwrite(int eq, int fd) {
+ struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
+ int i;
+ for(i=0;i<upe->nevents;i++) {
+ if (upe->poll[i].fd == fd) {
+ upe->poll[i].events = POLLIN|POLLOUT;
+ return 0;
+ }
+ }
return -1;
}
int event_queue_fd_read_to_readwrite(int eq, int fd) {
- return -1;
+ return event_queue_fd_write_to_readwrite(eq, fd);
}
int event_queue_interesting_fd_is_write(void *events, int id) {
- return -1;
+ struct pollfd *pevents = (struct pollfd *)events;
+ struct pollfd *upoll = &pevents[id];
+ if (upoll->revents & POLLOUT) {
+ return 1;
+ }
+ return 0;
}
int event_queue_add_fd_read(int eq, int fd) {
@@ -86,24 +130,69 @@ int event_queue_add_fd_read(int eq, int fd) {
return uwsgi_poll_fd_add(upe, fd, POLLIN);
}
int event_queue_add_fd_write(int eq, int fd) {
- return -1;
+ struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
+ if (uwsgi_poll_fd_is_registered(upe, fd)) return 0;
+ return uwsgi_poll_fd_add(upe, fd, POLLOUT);
}
int event_queue_del_fd(int eq, int fd, int event) {
- return -1;
+ struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
+ return uwsgi_poll_fd_del(upe, fd);
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
- return -1;
+ struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
+ uwsgi_poll_queue_rebuild(upe);
+ int ret = poll(upe->poll, upe->nevents, timeout * 1000);
+ int cnt = 0;
+ if (ret > 0) {
+ int i;
+ for(i=0;i<upe->nevents;i++) {
+ // it is safe to check for only POLLIN and POLLOUT events
+ if (upe->poll[i].revents & POLLIN || upe->poll[i].revents & POLLOUT) {
+ struct pollfd *pevents = (struct pollfd *)events;
+ struct pollfd *upoll = &pevents[cnt];
+ upoll->fd = upe->poll[i].fd;
+ upoll->revents = upe->poll[i].revents;
+ upoll->events = upe->poll[i].events;
+ cnt++;
+ }
+ }
+ }
+ if (ret <= 0) return ret;
+ return cnt;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
- return -1;
+ struct pollfd *pevents = (struct pollfd *)events;
+ struct pollfd *upoll = &pevents[id];
+ if (upoll->revents & POLLERR || upoll->revents & POLLHUP || upoll->revents & POLLNVAL) {
+ return 1;
+ }
+ return 0;
}
int event_queue_interesting_fd(void *events, int id) {
- return -1;
+ struct pollfd *pevents = (struct pollfd *)events;
+ struct pollfd *upoll = &pevents[id];
+ return upoll->fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
+ struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
+ int i;
+ for(i=0;i<upe->nevents;i++) {
+ if (upe->poll[i].fd == fd) {
+ upe->poll[i].events = POLLIN;
+ return 0;
+ }
+ }
return -1;
}
int event_queue_fd_read_to_write(int eq, int fd) {
+ struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
+ int i;
+ for(i=0;i<upe->nevents;i++) {
+ if (upe->poll[i].fd == fd) {
+ upe->poll[i].events = POLLOUT;
+ return 0;
+ }
+ }
return -1;
}
#endif