diff options
Diffstat (limited to 'seatd/poller.c')
| -rw-r--r-- | seatd/poller.c | 203 | 
1 files changed, 74 insertions, 129 deletions
| diff --git a/seatd/poller.c b/seatd/poller.c index 0631f4b..74d5d89 100644 --- a/seatd/poller.c +++ b/seatd/poller.c @@ -6,11 +6,13 @@  #include <stdint.h>  #include <stdlib.h>  #include <string.h> +#include <unistd.h> -#include "list.h" +#include "linked_list.h"  #include "poller.h"  struct event_source_fd { +	struct linked_list link; // poller::fds  	const struct event_source_fd_impl *impl;  	event_source_fd_func_t func; @@ -20,9 +22,11 @@ struct event_source_fd {  	struct poller *poller;  	bool killed; +	ssize_t pollfd_idx;  };  struct event_source_signal { +	struct linked_list link; // poller::signals  	const struct event_source_signal_impl *impl;  	event_source_signal_func_t func; @@ -40,38 +44,21 @@ struct poller *global_poller = NULL;  void poller_init(struct poller *poller) {  	assert(global_poller == NULL); -	list_init(&poller->fds); -	list_init(&poller->new_fds); -	list_init(&poller->signals); -	list_init(&poller->new_signals); +	linked_list_init(&poller->fds); +	linked_list_init(&poller->signals); +	poller->pollfds = NULL; +	poller->pollfds_len = 0; +	poller->fd_event_sources = 0;  	global_poller = poller;  }  int poller_finish(struct poller *poller) { -	for (size_t idx = 0; idx < poller->fds.length; idx++) { -		struct event_source_fd *bpfd = poller->fds.items[idx]; +	while (!linked_list_empty(&poller->fds)) { +		struct event_source_fd *bpfd = (struct event_source_fd *)poller->fds.next;  		free(bpfd);  	} -	list_free(&poller->fds); -	for (size_t idx = 0; idx < poller->new_fds.length; idx++) { -		struct event_source_fd *bpfd = poller->new_fds.items[idx]; -		free(bpfd); -	} -	list_free(&poller->new_fds); -	for (size_t idx = 0; idx < poller->signals.length; idx++) { -		struct event_source_signal *bps = poller->signals.items[idx]; - -		struct sigaction sa; -		sa.sa_handler = SIG_DFL; -		sigemptyset(&sa.sa_mask); -		sa.sa_flags = 0; -		sigaction(bps->signal, &sa, NULL); - -		free(bps); -	} -	list_free(&poller->signals); -	for (size_t idx = 0; idx < poller->new_signals.length; idx++) { -		struct event_source_signal *bps = poller->new_signals.items[idx]; +	while (!linked_list_empty(&poller->signals)) { +		struct event_source_signal *bps = (struct event_source_signal *)poller->signals.next;  		struct sigaction sa;  		sa.sa_handler = SIG_DFL; @@ -81,7 +68,6 @@ int poller_finish(struct poller *poller) {  		free(bps);  	} -	list_free(&poller->new_signals);  	free(poller->pollfds);  	return 0;  } @@ -115,24 +101,31 @@ static uint32_t poll_mask_to_event_mask(int poll_mask) {  }  static int regenerate_pollfds(struct poller *poller) { -	if (poller->pollfds_len != poller->fds.length) { -		struct pollfd *fds = calloc(poller->fds.length, sizeof(struct pollfd)); +	if (!poller->pollfds_dirty) { +		return 0; +	} + +	if (poller->fd_event_sources > poller->pollfds_len) { +		struct pollfd *fds = calloc(poller->fd_event_sources, sizeof(struct pollfd));  		if (fds == NULL) {  			return -1;  		}  		free(poller->pollfds);  		poller->pollfds = fds; -		poller->pollfds_len = poller->fds.length; +		poller->pollfds_len = poller->fd_event_sources;  	} -	for (size_t idx = 0; idx < poller->fds.length; idx++) { -		struct event_source_fd *bpfd = poller->fds.items[idx]; -		poller->pollfds[idx] = (struct pollfd){ +	ssize_t idx = 0; +	for (struct linked_list *elem = poller->fds.next; elem != &poller->fds; elem = elem->next) { +		struct event_source_fd *bpfd = (struct event_source_fd *)elem; +		bpfd->pollfd_idx = idx++; +		poller->pollfds[bpfd->pollfd_idx] = (struct pollfd){  			.fd = bpfd->fd,  			.events = event_mask_to_poll_mask(bpfd->mask),  		};  	} +	poller->pollfds_dirty = false;  	return 0;  } @@ -147,31 +140,19 @@ struct event_source_fd *poller_add_fd(struct poller *poller, int fd, uint32_t ma  	bpfd->data = data;  	bpfd->func = func;  	bpfd->poller = poller; -	poller->dirty = true; -	if (poller->inpoll) { -		list_add(&poller->new_fds, bpfd); -	} else { -		list_add(&poller->fds, bpfd); -		regenerate_pollfds(poller); -	} +	bpfd->pollfd_idx = -1; +	poller->fd_event_sources += 1; +	poller->pollfds_dirty = true; +	linked_list_insert(&poller->fds, &bpfd->link);  	return (struct event_source_fd *)bpfd;  }  int event_source_fd_destroy(struct event_source_fd *event_source) {  	struct event_source_fd *bpfd = (struct event_source_fd *)event_source;  	struct poller *poller = bpfd->poller; -	int idx = list_find(&poller->fds, event_source); -	if (idx == -1) { -		return -1; -	} -	poller->dirty = true; -	if (poller->inpoll) { -		bpfd->killed = true; -	} else { -		list_del(&poller->fds, idx); -		free(bpfd); -		regenerate_pollfds(poller); -	} +	poller->fd_event_sources -= 1; +	poller->pollfds_dirty = true; +	bpfd->killed = true;  	return 0;  } @@ -179,11 +160,7 @@ int event_source_fd_update(struct event_source_fd *event_source, uint32_t mask)  	struct event_source_fd *bpfd = (struct event_source_fd *)event_source;  	struct poller *poller = bpfd->poller;  	event_source->mask = mask; - -	poller->dirty = true; -	if (!poller->inpoll) { -		regenerate_pollfds(poller); -	} +	poller->pollfds_dirty = true;  	return 0;  } @@ -191,9 +168,9 @@ static void signal_handler(int sig) {  	if (global_poller == NULL) {  		return;  	} - -	for (size_t idx = 0; idx < global_poller->signals.length; idx++) { -		struct event_source_signal *bps = global_poller->signals.items[idx]; +	for (struct linked_list *elem = global_poller->signals.next; +	     elem != &global_poller->signals; elem = elem->next) { +		struct event_source_signal *bps = (struct event_source_signal *)elem;  		if (bps->signal == sig) {  			bps->raised = true;  		} @@ -208,32 +185,18 @@ struct event_source_signal *poller_add_signal(struct poller *poller, int signal,  		return NULL;  	} -	int refcnt = 0; -	for (size_t idx = 0; idx < poller->signals.length; idx++) { -		struct event_source_signal *bps = poller->signals.items[idx]; -		if (bps->signal == signal) { -			refcnt++; -		} -	} -  	bps->signal = signal;  	bps->data = data;  	bps->func = func;  	bps->poller = poller; -	if (refcnt == 0) { -		struct sigaction sa; -		sa.sa_handler = &signal_handler; -		sigemptyset(&sa.sa_mask); -		sa.sa_flags = 0; -		sigaction(signal, &sa, NULL); -	} +	struct sigaction sa; +	sa.sa_handler = &signal_handler; +	sigemptyset(&sa.sa_mask); +	sa.sa_flags = 0; +	sigaction(signal, &sa, NULL); -	if (poller->inpoll) { -		list_add(&poller->new_signals, bps); -	} else { -		list_add(&poller->signals, bps); -	} +	linked_list_insert(&poller->signals, &bps->link);  	return (struct event_source_signal *)bps;  } @@ -242,15 +205,11 @@ int event_source_signal_destroy(struct event_source_signal *event_source) {  	struct event_source_signal *bps = (struct event_source_signal *)event_source;  	struct poller *poller = bps->poller; -	int idx = list_find(&poller->signals, event_source); -	if (idx == -1) { -		return -1; -	} -  	int refcnt = 0; -	for (size_t idx = 0; idx < poller->signals.length; idx++) { -		struct event_source_signal *b = poller->signals.items[idx]; -		if (b->signal == bps->signal) { +	for (struct linked_list *elem = poller->signals.next; elem != &poller->signals; +	     elem = elem->next) { +		struct event_source_signal *b = (struct event_source_signal *)elem; +		if (b->signal == bps->signal && !b->killed) {  			refcnt++;  		}  	} @@ -263,77 +222,63 @@ int event_source_signal_destroy(struct event_source_signal *event_source) {  		sigaction(bps->signal, &sa, NULL);  	} -	if (poller->inpoll) { -		bps->killed = true; -	} else { -		list_del(&poller->signals, idx); -		free(bps); -	} +	bps->killed = true;  	return 0;  }  int poller_poll(struct poller *poller) { -	if (poll(poller->pollfds, poller->fds.length, -1) == -1 && errno != EINTR) { +	if (regenerate_pollfds(poller) == -1) {  		return -1;  	} -	poller->inpoll = true; +	if (poll(poller->pollfds, poller->fd_event_sources, -1) == -1 && errno != EINTR) { +		return -1; +	} -	for (size_t idx = 0; idx < poller->fds.length; idx++) { -		short revents = poller->pollfds[idx].revents; +	for (struct linked_list *elem = poller->fds.next; elem != &poller->fds; elem = elem->next) { +		struct event_source_fd *bpfd = (struct event_source_fd *)elem; +		if (bpfd->pollfd_idx == -1 || bpfd->killed) { +			continue; +		} +		short revents = poller->pollfds[bpfd->pollfd_idx].revents;  		if (revents == 0) {  			continue;  		} -		struct event_source_fd *bpfd = poller->fds.items[idx]; -		bpfd->func(poller->pollfds[idx].fd, poll_mask_to_event_mask(revents), bpfd->data); +		bpfd->func(poller->pollfds[bpfd->pollfd_idx].fd, poll_mask_to_event_mask(revents), +			   bpfd->data);  	} -	for (size_t idx = 0; idx < poller->signals.length; idx++) { -		struct event_source_signal *bps = poller->signals.items[idx]; -		if (!bps->raised) { +	for (struct linked_list *elem = poller->signals.next; elem != &poller->signals; +	     elem = elem->next) { +		struct event_source_signal *bps = (struct event_source_signal *)elem; +		if (!bps->raised || bps->killed) {  			continue;  		}  		bps->func(bps->signal, bps->data);  		bps->raised = false;  	} -	poller->inpoll = false; - -	for (size_t idx = 0; idx < poller->fds.length; idx++) { -		struct event_source_fd *bpfd = poller->fds.items[idx]; +	for (struct linked_list *elem = poller->fds.next; elem != &poller->fds; elem = elem->next) { +		struct event_source_fd *bpfd = (struct event_source_fd *)elem;  		if (!bpfd->killed) {  			continue;  		} -		list_del(&poller->fds, idx); +		elem = elem->prev; +		linked_list_remove(&bpfd->link);  		free(bpfd); -		idx--;  	} -	for (size_t idx = 0; idx < poller->signals.length; idx++) { -		struct event_source_signal *bps = poller->signals.items[idx]; +	for (struct linked_list *elem = poller->signals.next; elem != &poller->signals; +	     elem = elem->next) { +		struct event_source_signal *bps = (struct event_source_signal *)elem;  		if (!bps->killed) {  			continue;  		} -		list_del(&poller->signals, idx); +		elem = elem->prev; +		linked_list_remove(&bps->link);  		free(bps); -		idx--; -	} - -	if (poller->new_fds.length > 0) { -		list_concat(&poller->fds, &poller->new_fds); -		list_truncate(&poller->new_fds); -	} - -	if (poller->new_signals.length > 0) { -		list_concat(&poller->signals, &poller->new_signals); -		list_truncate(&poller->new_signals); -	} - -	if (poller->dirty) { -		regenerate_pollfds(poller); -		poller->dirty = false;  	}  	return 0; | 
