1 /******************************************************************************
2 *
3 * Copyright (C) 2014 Google, Inc.
4 *
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:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
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.
16 *
17 ******************************************************************************/
18
19 #define LOG_TAG "bt_osi_reactor"
20
21 #include <assert.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <sys/eventfd.h>
25 #include <sys/select.h>
26 #include <utils/Log.h>
27
28 #include "list.h"
29 #include "reactor.h"
30
31 #if !defined(EFD_SEMAPHORE)
32 # define EFD_SEMAPHORE (1 << 0)
33 #endif
34
35 struct reactor_t {
36 int event_fd;
37 list_t *objects;
38 };
39
40 static reactor_status_t run_reactor(reactor_t *reactor, int iterations, struct timeval *tv);
41
reactor_new(void)42 reactor_t *reactor_new(void) {
43 reactor_t *ret = (reactor_t *)calloc(1, sizeof(reactor_t));
44 if (!ret)
45 return NULL;
46
47 ret->event_fd = eventfd(0, EFD_SEMAPHORE);
48 if (ret->event_fd == -1) {
49 ALOGE("%s unable to create eventfd: %s", __func__, strerror(errno));
50 goto error;
51 }
52
53 ret->objects = list_new(NULL);
54 if (!ret->objects)
55 goto error;
56
57 return ret;
58
59 error:;
60 list_free(ret->objects);
61 close(ret->event_fd);
62 free(ret);
63 return NULL;
64 }
65
reactor_free(reactor_t * reactor)66 void reactor_free(reactor_t *reactor) {
67 if (!reactor)
68 return;
69
70 list_free(reactor->objects);
71 close(reactor->event_fd);
72 free(reactor);
73 }
74
reactor_start(reactor_t * reactor)75 reactor_status_t reactor_start(reactor_t *reactor) {
76 assert(reactor != NULL);
77 return run_reactor(reactor, 0, NULL);
78 }
79
reactor_run_once(reactor_t * reactor)80 reactor_status_t reactor_run_once(reactor_t *reactor) {
81 assert(reactor != NULL);
82 return run_reactor(reactor, 1, NULL);
83 }
84
reactor_run_once_timeout(reactor_t * reactor,timeout_t timeout_ms)85 reactor_status_t reactor_run_once_timeout(reactor_t *reactor, timeout_t timeout_ms) {
86 assert(reactor != NULL);
87
88 struct timeval tv;
89 tv.tv_sec = timeout_ms / 1000;
90 tv.tv_usec = (timeout_ms % 1000) * 1000;
91 return run_reactor(reactor, 1, &tv);
92 }
93
reactor_stop(reactor_t * reactor)94 void reactor_stop(reactor_t *reactor) {
95 assert(reactor != NULL);
96
97 eventfd_write(reactor->event_fd, 1);
98 }
99
reactor_register(reactor_t * reactor,reactor_object_t * obj)100 void reactor_register(reactor_t *reactor, reactor_object_t *obj) {
101 assert(reactor != NULL);
102 assert(obj != NULL);
103
104 list_append(reactor->objects, obj);
105 }
106
reactor_unregister(reactor_t * reactor,reactor_object_t * obj)107 void reactor_unregister(reactor_t *reactor, reactor_object_t *obj) {
108 assert(reactor != NULL);
109 assert(obj != NULL);
110
111 list_remove(reactor->objects, obj);
112 }
113
114 // Runs the reactor loop for a maximum of |iterations| with the given timeout, |tv|.
115 // 0 |iterations| means loop forever.
116 // NULL |tv| means no timeout (block until an event occurs).
117 // |reactor| may not be NULL.
run_reactor(reactor_t * reactor,int iterations,struct timeval * tv)118 static reactor_status_t run_reactor(reactor_t *reactor, int iterations, struct timeval *tv) {
119 assert(reactor != NULL);
120
121 for (int i = 0; iterations == 0 || i < iterations; ++i) {
122 fd_set read_set;
123 fd_set write_set;
124 FD_ZERO(&read_set);
125 FD_ZERO(&write_set);
126 FD_SET(reactor->event_fd, &read_set);
127
128 int max_fd = reactor->event_fd;
129 for (const list_node_t *iter = list_begin(reactor->objects); iter != list_end(reactor->objects); iter = list_next(iter)) {
130 reactor_object_t *object = (reactor_object_t *)list_node(iter);
131 int fd = object->fd;
132 reactor_interest_t interest = object->interest;
133 if (interest & REACTOR_INTEREST_READ)
134 FD_SET(fd, &read_set);
135 if (interest & REACTOR_INTEREST_WRITE)
136 FD_SET(fd, &write_set);
137 if (fd > max_fd)
138 max_fd = fd;
139 }
140
141 int ret;
142 do {
143 ret = select(max_fd + 1, &read_set, &write_set, NULL, tv);
144 } while (ret == -1 && errno == EINTR);
145
146 if (ret == -1) {
147 ALOGE("%s error in select: %s", __func__, strerror(errno));
148 return REACTOR_STATUS_ERROR;
149 }
150
151 if (ret == 0)
152 return REACTOR_STATUS_TIMEOUT;
153
154 if (FD_ISSET(reactor->event_fd, &read_set)) {
155 eventfd_t value;
156 eventfd_read(reactor->event_fd, &value);
157 return REACTOR_STATUS_STOP;
158 }
159
160 for (const list_node_t *iter = list_begin(reactor->objects); ret > 0 && iter != list_end(reactor->objects); iter = list_next(iter)) {
161 reactor_object_t *object = (reactor_object_t *)list_node(iter);
162 int fd = object->fd;
163 if (FD_ISSET(fd, &read_set)) {
164 object->read_ready(object->context);
165 --ret;
166 }
167 if (FD_ISSET(fd, &write_set)) {
168 object->write_ready(object->context);
169 --ret;
170 }
171 }
172 }
173 return REACTOR_STATUS_DONE;
174 }
175