105 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			105 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: LGPL-2.1+
 | |
| // Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
 | |
| #include <stdlib.h>
 | |
| #include <errno.h>
 | |
| #include <unistd.h>
 | |
| #include <signal.h>
 | |
| #include <sys/epoll.h>
 | |
| #include "mainloop.h"
 | |
| #include "log.h"
 | |
| 
 | |
| static int epfd = -1;
 | |
| static sig_atomic_t exit_mainloop;
 | |
| 
 | |
| struct mainloop_data {
 | |
| 	mainloop_callback_t cb;
 | |
| 	void *data;
 | |
| 	int fd;
 | |
| };
 | |
| 
 | |
| #define MAX_EVENTS 10
 | |
| 
 | |
| int mainloop(unsigned int timeout)
 | |
| {
 | |
| 	int i, nfds;
 | |
| 	struct epoll_event events[MAX_EVENTS];
 | |
| 	struct mainloop_data *md;
 | |
| 
 | |
| 	if (epfd < 0)
 | |
| 		return -1;
 | |
| 
 | |
| 	for (;;) {
 | |
| 
 | |
| 		nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
 | |
| 
 | |
| 		if (exit_mainloop || !nfds)
 | |
| 			return 0;
 | |
| 
 | |
| 		if (nfds < 0) {
 | |
| 			if (errno == EINTR)
 | |
| 				continue;
 | |
| 			return -1;
 | |
| 		}
 | |
| 
 | |
| 		for (i = 0; i < nfds; i++) {
 | |
| 			md = events[i].data.ptr;
 | |
| 
 | |
| 			if (md->cb(md->fd, md->data) > 0)
 | |
| 				return 0;
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int mainloop_add(int fd, mainloop_callback_t cb, void *data)
 | |
| {
 | |
| 	struct epoll_event ev = {
 | |
| 		.events = EPOLLIN,
 | |
| 	};
 | |
| 
 | |
| 	struct mainloop_data *md;
 | |
| 
 | |
| 	md = malloc(sizeof(*md));
 | |
| 	if (!md)
 | |
| 		return -1;
 | |
| 
 | |
| 	md->data = data;
 | |
| 	md->cb = cb;
 | |
| 	md->fd = fd;
 | |
| 
 | |
| 	ev.data.ptr = md;
 | |
| 
 | |
| 	if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
 | |
| 		free(md);
 | |
| 		return -1;
 | |
| 	}
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int mainloop_del(int fd)
 | |
| {
 | |
| 	if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) < 0)
 | |
| 		return -1;
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int mainloop_init(void)
 | |
| {
 | |
| 	epfd = epoll_create(2);
 | |
| 	if (epfd < 0)
 | |
| 		return -1;
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| void mainloop_exit(void)
 | |
| {
 | |
| 	exit_mainloop = 1;
 | |
| }
 | |
| 
 | |
| void mainloop_fini(void)
 | |
| {
 | |
| 	close(epfd);
 | |
| }
 |