1 /* //device/libs/telephony/ril_event.cpp
3 ** Copyright 2008, The Android Open Source Project
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
9 ** http://www.apache.org/licenses/LICENSE-2.0
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.
18 #define LOG_TAG "RILC"
24 #include <utils/Log.h>
25 #include <ril_event.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)
38 #define timeradd(tvp, uvp, vvp) \
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) { \
44 (vvp)->tv_usec -= 1000000; \
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)
57 #define timersub(a, b, res) \
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; \
68 static fd_set readFds;
71 static struct ril_event * watch_table[MAX_FD_EVENTS];
72 static struct ril_event timer_list;
73 static struct ril_event pending_list;
78 #define dlog(x...) RLOGD( x )
79 static void dump_event(struct ril_event * ev)
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("~~~~~~~~~~~~~~~~~~");
92 #define dlog(x...) do {} while(0)
93 #define dump_event(x) do {} while(0)
96 static void getNow(struct timeval * tv)
98 #ifdef HAVE_POSIX_CLOCKS
100 clock_gettime(CLOCK_MONOTONIC, &ts);
101 tv->tv_sec = ts.tv_sec;
102 tv->tv_usec = ts.tv_nsec/1000;
104 gettimeofday(tv, NULL);
108 static void init_list(struct ril_event * list)
110 memset(list, 0, sizeof(struct ril_event));
116 static void addToList(struct ril_event * ev, struct ril_event * list)
119 ev->prev = list->prev;
125 static void removeFromList(struct ril_event * ev)
127 dlog("~~~~ Removing event ~~~~");
130 ev->next->prev = ev->prev;
131 ev->prev->next = ev->next;
137 static void removeWatch(struct ril_event * ev, int index)
139 watch_table[index] = NULL;
142 FD_CLR(ev->fd, &readFds);
144 if (ev->fd+1 == nfds) {
147 for (int i = 0; i < MAX_FD_EVENTS; i++) {
148 struct ril_event * rev = watch_table[i];
150 if ((rev != NULL) && (rev->fd > n)) {
155 dlog("~~~~ nfds = %d ~~~~", nfds);
159 static void processTimeouts()
161 dlog("~~~~ +processTimeouts ~~~~");
164 struct ril_event * tev = timer_list.next;
165 struct ril_event * next;
168 // walk list, see if now >= ev->timeout for any events
170 dlog("~~~~ Looking for timers <= %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec);
171 while ((tev != &timer_list) && (timercmp(&now, &tev->timeout, >))) {
173 dlog("~~~~ firing timer ~~~~");
176 addToList(tev, &pending_list);
180 dlog("~~~~ -processTimeouts ~~~~");
183 static void processReadReadies(fd_set * rfds, int n)
185 dlog("~~~~ +processReadReadies (%d) ~~~~", n);
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) {
200 dlog("~~~~ -processReadReadies (%d) ~~~~", n);
203 static void firePending()
205 dlog("~~~~ +firePending ~~~~");
206 struct ril_event * ev = pending_list.next;
207 while (ev != &pending_list) {
208 struct ril_event * next = ev->next;
210 ev->func(ev->fd, 0, ev->param);
213 dlog("~~~~ -firePending ~~~~");
216 static int calcNextTimeout(struct timeval * tv)
218 struct ril_event * tev = timer_list.next;
223 // Sorted list, so calc based on first node
224 if (tev == &timer_list) {
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);
235 // timer already expired.
236 tv->tv_sec = tv->tv_usec = 0;
241 // Initialize internal data structs
242 void ril_event_init()
247 init_list(&timer_list);
248 init_list(&pending_list);
249 memset(watch_table, 0, sizeof(watch_table));
252 // Initialize an event
253 void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param)
255 dlog("~~~~ ril_event_set %x ~~~~", (unsigned int)ev);
256 memset(ev, 0, sizeof(struct ril_event));
259 ev->persist = persist;
262 fcntl(fd, F_SETFL, O_NONBLOCK);
265 // Add event to watch list
266 void ril_event_add(struct ril_event * ev)
268 dlog("~~~~ +ril_event_add ~~~~");
270 for (int i = 0; i < MAX_FD_EVENTS; i++) {
271 if (watch_table[i] == NULL) {
274 dlog("~~~~ added at %d ~~~~", i);
276 FD_SET(ev->fd, &readFds);
277 if (ev->fd >= nfds) nfds = ev->fd+1;
278 dlog("~~~~ nfds = %d ~~~~", nfds);
283 dlog("~~~~ -ril_event_add ~~~~");
287 void ril_timer_add(struct ril_event * ev, struct timeval * tv)
289 dlog("~~~~ +ril_timer_add ~~~~");
292 struct ril_event * list;
295 list = timer_list.next;
296 ev->fd = -1; // make sure fd is invalid
300 timeradd(&now, tv, &ev->timeout);
303 while (timercmp(&list->timeout, &ev->timeout, < )
304 && (list != &timer_list)) {
307 // list now points to the first event older than ev
312 dlog("~~~~ -ril_timer_add ~~~~");
315 // Remove event from watch or timer list
316 void ril_event_del(struct ril_event * ev)
318 dlog("~~~~ +ril_event_del ~~~~");
321 if (ev->index < 0 || ev->index >= MAX_FD_EVENTS) {
326 removeWatch(ev, ev->index);
329 dlog("~~~~ -ril_event_del ~~~~");
333 static void printReadies(fd_set * rfds)
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);
343 #define printReadies(rfds) do {} while(0)
346 void ril_event_loop()
351 struct timeval * ptv;
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 ~~~~");
363 dlog("~~~~ blocking for %ds + %dus ~~~~", (int)tv.tv_sec, (int)tv.tv_usec);
367 n = select(nfds, &rfds, NULL, NULL, ptv);
369 dlog("~~~~ %d events fired ~~~~", n);
371 if (errno == EINTR) continue;
373 RLOGE("ril_event: select error (%d)", errno);
378 // Check for timeouts
380 // Check for read-ready
381 processReadReadies(&rfds, n);