Merge tag 'for-linus-5.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw...
[linux-block.git] / tools / thermal / lib / mainloop.c
CommitLineData
3b7c5e8a
DL
1// SPDX-License-Identifier: LGPL-2.1+
2// Copyright (C) 2022, Linaro Ltd - Daniel Lezcano <daniel.lezcano@linaro.org>
3#include <stdlib.h>
4#include <errno.h>
5#include <unistd.h>
6#include <signal.h>
7#include <sys/epoll.h>
8#include "mainloop.h"
9#include "log.h"
10
11static int epfd = -1;
12static unsigned short nrhandler;
13static sig_atomic_t exit_mainloop;
14
15struct mainloop_data {
16 mainloop_callback_t cb;
17 void *data;
18 int fd;
19};
20
21static struct mainloop_data **mds;
22
23#define MAX_EVENTS 10
24
25int mainloop(unsigned int timeout)
26{
27 int i, nfds;
28 struct epoll_event events[MAX_EVENTS];
29 struct mainloop_data *md;
30
31 if (epfd < 0)
32 return -1;
33
34 for (;;) {
35
36 nfds = epoll_wait(epfd, events, MAX_EVENTS, timeout);
37
38 if (exit_mainloop || !nfds)
39 return 0;
40
41 if (nfds < 0) {
42 if (errno == EINTR)
43 continue;
44 return -1;
45 }
46
47 for (i = 0; i < nfds; i++) {
48 md = events[i].data.ptr;
49
50 if (md->cb(md->fd, md->data) > 0)
51 return 0;
52 }
53 }
54}
55
56int mainloop_add(int fd, mainloop_callback_t cb, void *data)
57{
58 struct epoll_event ev = {
59 .events = EPOLLIN,
60 };
61
62 struct mainloop_data *md;
63
64 if (fd >= nrhandler) {
65 mds = realloc(mds, sizeof(*mds) * (fd + 1));
66 if (!mds)
67 return -1;
68 nrhandler = fd + 1;
69 }
70
71 md = malloc(sizeof(*md));
72 if (!md)
73 return -1;
74
75 md->data = data;
76 md->cb = cb;
77 md->fd = fd;
78
79 mds[fd] = md;
80 ev.data.ptr = md;
81
82 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
83 free(md);
84 return -1;
85 }
86
87 return 0;
88}
89
90int mainloop_del(int fd)
91{
92 if (fd >= nrhandler)
93 return -1;
94
95 if (epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL) < 0)
96 return -1;
97
98 free(mds[fd]);
99
100 return 0;
101}
102
103int mainloop_init(void)
104{
105 epfd = epoll_create(2);
106 if (epfd < 0)
107 return -1;
108
109 return 0;
110}
111
112void mainloop_exit(void)
113{
114 exit_mainloop = 1;
115}
116
117void mainloop_fini(void)
118{
119 close(epfd);
120}