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 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 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 75 reactor_status_t reactor_start(reactor_t *reactor) { 76 assert(reactor != NULL); 77 return run_reactor(reactor, 0, NULL); 78 } 79 80 reactor_status_t reactor_run_once(reactor_t *reactor) { 81 assert(reactor != NULL); 82 return run_reactor(reactor, 1, NULL); 83 } 84 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 94 void reactor_stop(reactor_t *reactor) { 95 assert(reactor != NULL); 96 97 eventfd_write(reactor->event_fd, 1); 98 } 99 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 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. 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