• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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