1 /* //device/libs/telephony/ril_event.cpp 2 ** 3 ** Copyright 2008, The Android Open Source Project 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 #define LOG_TAG "RILC" 19 20 #include <stdlib.h> 21 #include <unistd.h> 22 #include <errno.h> 23 #include <fcntl.h> 24 #include <utils/Log.h> 25 #include <ril_event.h> 26 #include <string.h> 27 #include <sys/time.h> 28 #include <time.h> 29 30 #include <pthread.h> 31 static pthread_mutex_t listMutex; 32 #define MUTEX_ACQUIRE() pthread_mutex_lock(&listMutex) 33 #define MUTEX_RELEASE() pthread_mutex_unlock(&listMutex) 34 #define MUTEX_INIT() pthread_mutex_init(&listMutex, NULL) 35 #define MUTEX_DESTROY() pthread_mutex_destroy(&listMutex) 36 37 #ifndef timeradd 38 #define timeradd(tvp, uvp, vvp) \ 39 do { \ 40 (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \ 41 (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \ 42 if ((vvp)->tv_usec >= 1000000) { \ 43 (vvp)->tv_sec++; \ 44 (vvp)->tv_usec -= 1000000; \ 45 } \ 46 } while (0) 47 #endif 48 49 #ifndef timercmp 50 #define timercmp(a, b, op) \ 51 ((a)->tv_sec == (b)->tv_sec \ 52 ? (a)->tv_usec op (b)->tv_usec \ 53 : (a)->tv_sec op (b)->tv_sec) 54 #endif 55 56 #ifndef timersub 57 #define timersub(a, b, res) \ 58 do { \ 59 (res)->tv_sec = (a)->tv_sec - (b)->tv_sec; \ 60 (res)->tv_usec = (a)->tv_usec - (b)->tv_usec; \ 61 if ((res)->tv_usec < 0) { \ 62 (res)->tv_usec += 1000000; \ 63 (res)->tv_sec -= 1; \ 64 } \ 65 } while(0); 66 #endif 67 68 static fd_set readFds; 69 static int nfds = 0; 70 71 static struct ril_event * watch_table[MAX_FD_EVENTS]; 72 static struct ril_event timer_list; 73 static struct ril_event pending_list; 74 75 #define DEBUG 0 76 77 #if DEBUG 78 #define dlog(x...) RLOGD( x ) 79 static void dump_event(struct ril_event * ev) 80 { 81 dlog("~~~~ Event %x ~~~~", (unsigned int)ev); 82 dlog(" next = %x", (unsigned int)ev->next); 83 dlog(" prev = %x", (unsigned int)ev->prev); 84 dlog(" fd = %d", ev->fd); 85 dlog(" pers = %d", ev->persist); 86 dlog(" timeout = %ds + %dus", (int)ev->timeout.tv_sec, (int)ev->timeout.tv_usec); 87 dlog(" func = %x", (unsigned int)ev->func); 88 dlog(" param = %x", (unsigned int)ev->param); 89 dlog("~~~~~~~~~~~~~~~~~~"); 90 } 91 #else 92 #define dlog(x...) do {} while(0) 93 #define dump_event(x) do {} while(0) 94 #endif 95 96 static void getNow(struct timeval * tv) 97 { 98 struct timespec ts; 99 clock_gettime(CLOCK_MONOTONIC, &ts); 100 tv->tv_sec = ts.tv_sec; 101 tv->tv_usec = ts.tv_nsec/1000; 102 } 103 104 static void init_list(struct ril_event * list) 105 { 106 memset(list, 0, sizeof(struct ril_event)); 107 list->next = list; 108 list->prev = list; 109 list->fd = -1; 110 } 111 112 static void addToList(struct ril_event * ev, struct ril_event * list) 113 { 114 ev->next = list; 115 ev->prev = list->prev; 116 ev->prev->next = ev; 117 list->prev = ev; 118 dump_event(ev); 119 } 120 121 static void removeFromList(struct ril_event * ev) 122 { 123 dlog("~~~~ +removeFromList ~~~~"); 124 dump_event(ev); 125 126 ev->next->prev = ev->prev; 127 ev->prev->next = ev->next; 128 ev->next = NULL; 129 ev->prev = NULL; 130 dlog("~~~~ -removeFromList ~~~~"); 131 } 132 133 134 static void removeWatch(struct ril_event * ev, int index) 135 { 136 dlog("~~~~ +removeWatch ~~~~"); 137 watch_table[index] = NULL; 138 ev->index = -1; 139 140 FD_CLR(ev->fd, &readFds); 141 142 if (ev->fd+1 == nfds) { 143 int n = 0; 144 145 for (int i = 0; i < MAX_FD_EVENTS; i++) { 146 struct ril_event * rev = watch_table[i]; 147 148 if ((rev != NULL) && (rev->fd > n)) { 149 n = rev->fd; 150 } 151 } 152 nfds = n + 1; 153 dlog("~~~~ nfds = %d ~~~~", nfds); 154 } 155 dlog("~~~~ -removeWatch ~~~~"); 156 } 157 158 static void processTimeouts() 159 { 160 dlog("~~~~ +processTimeouts ~~~~"); 161 MUTEX_ACQUIRE(); 162 struct timeval now; 163 struct ril_event * tev = timer_list.next; 164 struct ril_event * next; 165 166 getNow(&now); 167 // walk list, see if now >= ev->timeout for any events 168 169 dlog("~~~~ Looking for timers <= %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec); 170 while ((tev != &timer_list) && (timercmp(&now, &tev->timeout, >))) { 171 // Timer expired 172 dlog("~~~~ firing timer ~~~~"); 173 next = tev->next; 174 removeFromList(tev); 175 addToList(tev, &pending_list); 176 tev = next; 177 } 178 MUTEX_RELEASE(); 179 dlog("~~~~ -processTimeouts ~~~~"); 180 } 181 182 static void processReadReadies(fd_set * rfds, int n) 183 { 184 dlog("~~~~ +processReadReadies (%d) ~~~~", n); 185 MUTEX_ACQUIRE(); 186 187 for (int i = 0; (i < MAX_FD_EVENTS) && (n > 0); i++) { 188 struct ril_event * rev = watch_table[i]; 189 if (rev != NULL && FD_ISSET(rev->fd, rfds)) { 190 addToList(rev, &pending_list); 191 if (rev->persist == false) { 192 removeWatch(rev, i); 193 } 194 n--; 195 } 196 } 197 198 MUTEX_RELEASE(); 199 dlog("~~~~ -processReadReadies (%d) ~~~~", n); 200 } 201 202 static void firePending() 203 { 204 dlog("~~~~ +firePending ~~~~"); 205 struct ril_event * ev = pending_list.next; 206 while (ev != &pending_list) { 207 struct ril_event * next = ev->next; 208 removeFromList(ev); 209 ev->func(ev->fd, 0, ev->param); 210 ev = next; 211 } 212 dlog("~~~~ -firePending ~~~~"); 213 } 214 215 static int calcNextTimeout(struct timeval * tv) 216 { 217 struct ril_event * tev = timer_list.next; 218 struct timeval now; 219 220 getNow(&now); 221 222 // Sorted list, so calc based on first node 223 if (tev == &timer_list) { 224 // no pending timers 225 return -1; 226 } 227 228 dlog("~~~~ now = %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec); 229 dlog("~~~~ next = %ds + %dus ~~~~", 230 (int)tev->timeout.tv_sec, (int)tev->timeout.tv_usec); 231 if (timercmp(&tev->timeout, &now, >)) { 232 timersub(&tev->timeout, &now, tv); 233 } else { 234 // timer already expired. 235 tv->tv_sec = tv->tv_usec = 0; 236 } 237 return 0; 238 } 239 240 // Initialize internal data structs 241 void ril_event_init() 242 { 243 MUTEX_INIT(); 244 245 FD_ZERO(&readFds); 246 init_list(&timer_list); 247 init_list(&pending_list); 248 memset(watch_table, 0, sizeof(watch_table)); 249 } 250 251 // Initialize an event 252 void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param) 253 { 254 dlog("~~~~ ril_event_set %x ~~~~", (unsigned int)ev); 255 memset(ev, 0, sizeof(struct ril_event)); 256 ev->fd = fd; 257 ev->index = -1; 258 ev->persist = persist; 259 ev->func = func; 260 ev->param = param; 261 fcntl(fd, F_SETFL, O_NONBLOCK); 262 } 263 264 // Add event to watch list 265 void ril_event_add(struct ril_event * ev) 266 { 267 dlog("~~~~ +ril_event_add ~~~~"); 268 MUTEX_ACQUIRE(); 269 for (int i = 0; i < MAX_FD_EVENTS; i++) { 270 if (watch_table[i] == NULL) { 271 watch_table[i] = ev; 272 ev->index = i; 273 dlog("~~~~ added at %d ~~~~", i); 274 dump_event(ev); 275 FD_SET(ev->fd, &readFds); 276 if (ev->fd >= nfds) nfds = ev->fd+1; 277 dlog("~~~~ nfds = %d ~~~~", nfds); 278 break; 279 } 280 } 281 MUTEX_RELEASE(); 282 dlog("~~~~ -ril_event_add ~~~~"); 283 } 284 285 // Add timer event 286 void ril_timer_add(struct ril_event * ev, struct timeval * tv) 287 { 288 dlog("~~~~ +ril_timer_add ~~~~"); 289 MUTEX_ACQUIRE(); 290 291 struct ril_event * list; 292 if (tv != NULL) { 293 // add to timer list 294 list = timer_list.next; 295 ev->fd = -1; // make sure fd is invalid 296 297 struct timeval now; 298 getNow(&now); 299 timeradd(&now, tv, &ev->timeout); 300 301 // keep list sorted 302 while (timercmp(&list->timeout, &ev->timeout, < ) 303 && (list != &timer_list)) { 304 list = list->next; 305 } 306 // list now points to the first event older than ev 307 addToList(ev, list); 308 } 309 310 MUTEX_RELEASE(); 311 dlog("~~~~ -ril_timer_add ~~~~"); 312 } 313 314 // Remove event from watch or timer list 315 void ril_event_del(struct ril_event * ev) 316 { 317 dlog("~~~~ +ril_event_del ~~~~"); 318 MUTEX_ACQUIRE(); 319 320 if (ev->index < 0 || ev->index >= MAX_FD_EVENTS) { 321 MUTEX_RELEASE(); 322 return; 323 } 324 325 removeWatch(ev, ev->index); 326 327 MUTEX_RELEASE(); 328 dlog("~~~~ -ril_event_del ~~~~"); 329 } 330 331 #if DEBUG 332 static void printReadies(fd_set * rfds) 333 { 334 for (int i = 0; (i < MAX_FD_EVENTS); i++) { 335 struct ril_event * rev = watch_table[i]; 336 if (rev != NULL && FD_ISSET(rev->fd, rfds)) { 337 dlog("DON: fd=%d is ready", rev->fd); 338 } 339 } 340 } 341 #else 342 #define printReadies(rfds) do {} while(0) 343 #endif 344 345 void ril_event_loop() 346 { 347 int n; 348 fd_set rfds; 349 struct timeval tv; 350 struct timeval * ptv; 351 352 353 for (;;) { 354 355 // make local copy of read fd_set 356 memcpy(&rfds, &readFds, sizeof(fd_set)); 357 if (-1 == calcNextTimeout(&tv)) { 358 // no pending timers; block indefinitely 359 dlog("~~~~ no timers; blocking indefinitely ~~~~"); 360 ptv = NULL; 361 } else { 362 dlog("~~~~ blocking for %ds + %dus ~~~~", (int)tv.tv_sec, (int)tv.tv_usec); 363 ptv = &tv; 364 } 365 printReadies(&rfds); 366 n = select(nfds, &rfds, NULL, NULL, ptv); 367 printReadies(&rfds); 368 dlog("~~~~ %d events fired ~~~~", n); 369 if (n < 0) { 370 if (errno == EINTR) continue; 371 372 RLOGE("ril_event: select error (%d)", errno); 373 // bail? 374 return; 375 } 376 377 // Check for timeouts 378 processTimeouts(); 379 // Check for read-ready 380 processReadReadies(&rfds, n); 381 // Fire away 382 firePending(); 383 } 384 } 385