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 #ifdef HAVE_POSIX_CLOCKS 99 struct timespec ts; 100 clock_gettime(CLOCK_MONOTONIC, &ts); 101 tv->tv_sec = ts.tv_sec; 102 tv->tv_usec = ts.tv_nsec/1000; 103 #else 104 gettimeofday(tv, NULL); 105 #endif 106 } 107 108 static void init_list(struct ril_event * list) 109 { 110 memset(list, 0, sizeof(struct ril_event)); 111 list->next = list; 112 list->prev = list; 113 list->fd = -1; 114 } 115 116 static void addToList(struct ril_event * ev, struct ril_event * list) 117 { 118 ev->next = list; 119 ev->prev = list->prev; 120 ev->prev->next = ev; 121 list->prev = ev; 122 dump_event(ev); 123 } 124 125 static void removeFromList(struct ril_event * ev) 126 { 127 dlog("~~~~ Removing event ~~~~"); 128 dump_event(ev); 129 130 ev->next->prev = ev->prev; 131 ev->prev->next = ev->next; 132 ev->next = NULL; 133 ev->prev = NULL; 134 } 135 136 137 static void removeWatch(struct ril_event * ev, int index) 138 { 139 watch_table[index] = NULL; 140 ev->index = -1; 141 142 FD_CLR(ev->fd, &readFds); 143 144 if (ev->fd+1 == nfds) { 145 int n = 0; 146 147 for (int i = 0; i < MAX_FD_EVENTS; i++) { 148 struct ril_event * rev = watch_table[i]; 149 150 if ((rev != NULL) && (rev->fd > n)) { 151 n = rev->fd; 152 } 153 } 154 nfds = n + 1; 155 dlog("~~~~ nfds = %d ~~~~", nfds); 156 } 157 } 158 159 static void processTimeouts() 160 { 161 dlog("~~~~ +processTimeouts ~~~~"); 162 MUTEX_ACQUIRE(); 163 struct timeval now; 164 struct ril_event * tev = timer_list.next; 165 struct ril_event * next; 166 167 getNow(&now); 168 // walk list, see if now >= ev->timeout for any events 169 170 dlog("~~~~ Looking for timers <= %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec); 171 while ((tev != &timer_list) && (timercmp(&now, &tev->timeout, >))) { 172 // Timer expired 173 dlog("~~~~ firing timer ~~~~"); 174 next = tev->next; 175 removeFromList(tev); 176 addToList(tev, &pending_list); 177 tev = next; 178 } 179 MUTEX_RELEASE(); 180 dlog("~~~~ -processTimeouts ~~~~"); 181 } 182 183 static void processReadReadies(fd_set * rfds, int n) 184 { 185 dlog("~~~~ +processReadReadies (%d) ~~~~", n); 186 MUTEX_ACQUIRE(); 187 188 for (int i = 0; (i < MAX_FD_EVENTS) && (n > 0); i++) { 189 struct ril_event * rev = watch_table[i]; 190 if (rev != NULL && FD_ISSET(rev->fd, rfds)) { 191 addToList(rev, &pending_list); 192 if (rev->persist == false) { 193 removeWatch(rev, i); 194 } 195 n--; 196 } 197 } 198 199 MUTEX_RELEASE(); 200 dlog("~~~~ -processReadReadies (%d) ~~~~", n); 201 } 202 203 static void firePending() 204 { 205 dlog("~~~~ +firePending ~~~~"); 206 struct ril_event * ev = pending_list.next; 207 while (ev != &pending_list) { 208 struct ril_event * next = ev->next; 209 removeFromList(ev); 210 ev->func(ev->fd, 0, ev->param); 211 ev = next; 212 } 213 dlog("~~~~ -firePending ~~~~"); 214 } 215 216 static int calcNextTimeout(struct timeval * tv) 217 { 218 struct ril_event * tev = timer_list.next; 219 struct timeval now; 220 221 getNow(&now); 222 223 // Sorted list, so calc based on first node 224 if (tev == &timer_list) { 225 // no pending timers 226 return -1; 227 } 228 229 dlog("~~~~ now = %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec); 230 dlog("~~~~ next = %ds + %dus ~~~~", 231 (int)tev->timeout.tv_sec, (int)tev->timeout.tv_usec); 232 if (timercmp(&tev->timeout, &now, >)) { 233 timersub(&tev->timeout, &now, tv); 234 } else { 235 // timer already expired. 236 tv->tv_sec = tv->tv_usec = 0; 237 } 238 return 0; 239 } 240 241 // Initialize internal data structs 242 void ril_event_init() 243 { 244 MUTEX_INIT(); 245 246 FD_ZERO(&readFds); 247 init_list(&timer_list); 248 init_list(&pending_list); 249 memset(watch_table, 0, sizeof(watch_table)); 250 } 251 252 // Initialize an event 253 void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param) 254 { 255 dlog("~~~~ ril_event_set %x ~~~~", (unsigned int)ev); 256 memset(ev, 0, sizeof(struct ril_event)); 257 ev->fd = fd; 258 ev->index = -1; 259 ev->persist = persist; 260 ev->func = func; 261 ev->param = param; 262 fcntl(fd, F_SETFL, O_NONBLOCK); 263 } 264 265 // Add event to watch list 266 void ril_event_add(struct ril_event * ev) 267 { 268 dlog("~~~~ +ril_event_add ~~~~"); 269 MUTEX_ACQUIRE(); 270 for (int i = 0; i < MAX_FD_EVENTS; i++) { 271 if (watch_table[i] == NULL) { 272 watch_table[i] = ev; 273 ev->index = i; 274 dlog("~~~~ added at %d ~~~~", i); 275 dump_event(ev); 276 FD_SET(ev->fd, &readFds); 277 if (ev->fd >= nfds) nfds = ev->fd+1; 278 dlog("~~~~ nfds = %d ~~~~", nfds); 279 break; 280 } 281 } 282 MUTEX_RELEASE(); 283 dlog("~~~~ -ril_event_add ~~~~"); 284 } 285 286 // Add timer event 287 void ril_timer_add(struct ril_event * ev, struct timeval * tv) 288 { 289 dlog("~~~~ +ril_timer_add ~~~~"); 290 MUTEX_ACQUIRE(); 291 292 struct ril_event * list; 293 if (tv != NULL) { 294 // add to timer list 295 list = timer_list.next; 296 ev->fd = -1; // make sure fd is invalid 297 298 struct timeval now; 299 getNow(&now); 300 timeradd(&now, tv, &ev->timeout); 301 302 // keep list sorted 303 while (timercmp(&list->timeout, &ev->timeout, < ) 304 && (list != &timer_list)) { 305 list = list->next; 306 } 307 // list now points to the first event older than ev 308 addToList(ev, list); 309 } 310 311 MUTEX_RELEASE(); 312 dlog("~~~~ -ril_timer_add ~~~~"); 313 } 314 315 // Remove event from watch or timer list 316 void ril_event_del(struct ril_event * ev) 317 { 318 dlog("~~~~ +ril_event_del ~~~~"); 319 MUTEX_ACQUIRE(); 320 321 if (ev->index < 0 || ev->index >= MAX_FD_EVENTS) { 322 MUTEX_RELEASE(); 323 return; 324 } 325 326 removeWatch(ev, ev->index); 327 328 MUTEX_RELEASE(); 329 dlog("~~~~ -ril_event_del ~~~~"); 330 } 331 332 #if DEBUG 333 static void printReadies(fd_set * rfds) 334 { 335 for (int i = 0; (i < MAX_FD_EVENTS); i++) { 336 struct ril_event * rev = watch_table[i]; 337 if (rev != NULL && FD_ISSET(rev->fd, rfds)) { 338 dlog("DON: fd=%d is ready", rev->fd); 339 } 340 } 341 } 342 #else 343 #define printReadies(rfds) do {} while(0) 344 #endif 345 346 void ril_event_loop() 347 { 348 int n; 349 fd_set rfds; 350 struct timeval tv; 351 struct timeval * ptv; 352 353 354 for (;;) { 355 356 // make local copy of read fd_set 357 memcpy(&rfds, &readFds, sizeof(fd_set)); 358 if (-1 == calcNextTimeout(&tv)) { 359 // no pending timers; block indefinitely 360 dlog("~~~~ no timers; blocking indefinitely ~~~~"); 361 ptv = NULL; 362 } else { 363 dlog("~~~~ blocking for %ds + %dus ~~~~", (int)tv.tv_sec, (int)tv.tv_usec); 364 ptv = &tv; 365 } 366 printReadies(&rfds); 367 n = select(nfds, &rfds, NULL, NULL, ptv); 368 printReadies(&rfds); 369 dlog("~~~~ %d events fired ~~~~", n); 370 if (n < 0) { 371 if (errno == EINTR) continue; 372 373 RLOGE("ril_event: select error (%d)", errno); 374 // bail? 375 return; 376 } 377 378 // Check for timeouts 379 processTimeouts(); 380 // Check for read-ready 381 processReadReadies(&rfds, n); 382 // Fire away 383 firePending(); 384 } 385 } 386