tools/thermal: Add util library
[linux-2.6-microblaze.git] / tools / thermal / lib / mainloop.c
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
11 static int epfd = -1;
12 static unsigned short nrhandler;
13 static sig_atomic_t exit_mainloop;
14
15 struct mainloop_data {
16         mainloop_callback_t cb;
17         void *data;
18         int fd;
19 };
20
21 static struct mainloop_data **mds;
22
23 #define MAX_EVENTS 10
24
25 int 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
56 int 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
90 int 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
103 int mainloop_init(void)
104 {
105         epfd = epoll_create(2);
106         if (epfd < 0)
107                 return -1;
108
109         return 0;
110 }
111
112 void mainloop_exit(void)
113 {
114         exit_mainloop = 1;
115 }
116
117 void mainloop_fini(void)
118 {
119         close(epfd);
120 }