2 * Copyright (C) 2016-2019 "IoT.bzh"
3 * Author José Bollo <jose.bollo@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
26 #include <sys/syscall.h>
30 #include <sys/eventfd.h>
32 #include <systemd/sd-event.h>
38 /** Description of handled event loops */
41 unsigned state; /**< encoded state */
42 int efd; /**< event notification */
43 void *holder; /**< holder of the evmgr */
44 struct sd_event *sdev; /**< the systemd event loop */
47 #define EVLOOP_STATE_WAIT 1U
48 #define EVLOOP_STATE_RUN 2U
51 * Run the event loop is set.
53 void evmgr_run(struct evmgr *evmgr)
58 evmgr->state = EVLOOP_STATE_WAIT|EVLOOP_STATE_RUN;
60 rc = sd_event_prepare(se);
63 CRITICAL("sd_event_prepare returned an error (state: %d): %m", sd_event_get_state(se));
67 rc = sd_event_wait(se, (uint64_t)(int64_t)-1);
70 ERROR("sd_event_wait returned an error (state: %d): %m", sd_event_get_state(se));
73 evmgr->state = EVLOOP_STATE_RUN;
75 rc = sd_event_dispatch(se);
78 ERROR("sd_event_dispatch returned an error (state: %d): %m", sd_event_get_state(se));
85 void evmgr_job_run(int signum, struct evmgr *evmgr)
93 int evmgr_can_run(struct evmgr *evmgr)
99 * Internal callback for evmgr management.
100 * The effect of this function is hidden: it exits
101 * the waiting poll if any.
103 static void evmgr_on_efd_event(struct evmgr *evmgr)
106 read(evmgr->efd, &x, sizeof x);
110 * wakeup the event loop if needed by sending
113 void evmgr_wakeup(struct evmgr *evmgr)
117 if (evmgr->state & EVLOOP_STATE_WAIT) {
119 write(evmgr->efd, &x, sizeof x);
125 void *evmgr_holder(struct evmgr *evmgr)
127 return evmgr->holder;
132 int evmgr_release_if(struct evmgr *evmgr, void *holder)
134 if (evmgr->holder != holder)
142 int evmgr_try_hold(struct evmgr *evmgr, void *holder)
145 evmgr->holder = holder;
146 return evmgr->holder == holder;
149 /******************************************************************************/
150 /******************************************************************************/
151 /****** SYSTEM D ******/
152 /******************************************************************************/
153 /******************************************************************************/
156 * Internal callback for evmgr management.
157 * The effect of this function is hidden: it exits
158 * the waiting poll if any. Then it wakes up a thread
159 * awaiting the evmgr using signal.
161 static int on_evmgr_efd(sd_event_source *s, int fd, uint32_t revents, void *userdata)
163 struct evmgr *evmgr = userdata;
164 evmgr_on_efd_event(evmgr);
169 * Gets a sd_event item for the current thread.
170 * @return a sd_event or NULL in case of error
172 int evmgr_create(struct evmgr **result)
177 /* creates the evmgr on need */
178 evmgr = malloc(sizeof *evmgr);
180 ERROR("out of memory");
185 /* creates the eventfd for waking up polls */
186 evmgr->efd = eventfd(0, EFD_CLOEXEC|EFD_SEMAPHORE);
187 if (evmgr->efd < 0) {
189 ERROR("can't make eventfd for events");
192 /* create the systemd event loop */
193 evmgr->sdev = systemd_get_event_loop();
196 ERROR("can't make new event loop");
199 /* put the eventfd in the event loop */
200 rc = sd_event_add_io(evmgr->sdev, NULL, evmgr->efd, EPOLLIN, on_evmgr_efd, evmgr);
202 ERROR("can't register eventfd");
206 /* start the creation */