• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright (C) 1999-2012 Broadcom Corporation
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 #include <android-base/logging.h>
19 #include <android-base/stringprintf.h>
20 
21 #include "gki_int.h"
22 
23 /* Make sure that this has been defined in target.h */
24 #ifndef GKI_NUM_TIMERS
25 #error NO TIMERS: Must define at least 1 timer in the system!
26 #endif
27 
28 /* Largest signed positive timer count */
29 #define GKI_NO_NEW_TMRS_STARTED (0x7fffffffL)
30 /* Marks an unused timer list entry (initial value) */
31 #define GKI_UNUSED_LIST_ENTRY (0x80000000L)
32 #define GKI_MAX_INT32 (0x7fffffffL)
33 
34 using android::base::StringPrintf;
35 
36 /*******************************************************************************
37 **
38 ** Function         gki_timers_init
39 **
40 ** Description      This internal function is called once at startup to
41 **                  initialize all the timer structures.
42 **
43 ** Returns          void
44 **
45 *******************************************************************************/
gki_timers_init(void)46 void gki_timers_init(void) {
47   uint8_t tt;
48 
49   gki_cb.com.OSTicksTilExp =
50       0; /* Remaining time (of OSTimeCurTimeout) before next timer expires */
51   gki_cb.com.OSNumOrigTicks = 0;
52 #if (GKI_DELAY_STOP_SYS_TICK > 0)
53   gki_cb.com.OSTicksTilStop = 0; /* clear inactivity delay timer */
54 #endif
55 
56   for (tt = 0; tt < GKI_MAX_TASKS; tt++) {
57     gki_cb.com.OSWaitTmr[tt] = 0;
58 
59 #if (GKI_NUM_TIMERS > 0)
60     gki_cb.com.OSTaskTmr0[tt] = 0;
61     gki_cb.com.OSTaskTmr0R[tt] = 0;
62 #endif
63 
64 #if (GKI_NUM_TIMERS > 1)
65     gki_cb.com.OSTaskTmr1[tt] = 0;
66     gki_cb.com.OSTaskTmr1R[tt] = 0;
67 #endif
68 
69 #if (GKI_NUM_TIMERS > 2)
70     gki_cb.com.OSTaskTmr2[tt] = 0;
71     gki_cb.com.OSTaskTmr2R[tt] = 0;
72 #endif
73 
74 #if (GKI_NUM_TIMERS > 3)
75     gki_cb.com.OSTaskTmr3[tt] = 0;
76     gki_cb.com.OSTaskTmr3R[tt] = 0;
77 #endif
78   }
79 
80   for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) {
81     gki_cb.com.timer_queues[tt] = nullptr;
82   }
83 
84   gki_cb.com.p_tick_cb = nullptr;
85   gki_cb.com.system_tick_running = false;
86 
87   return;
88 }
89 
90 /*******************************************************************************
91 **
92 ** Function         gki_timers_is_timer_running
93 **
94 ** Description      This internal function is called to test if any gki timer
95 **                  are running
96 **
97 **
98 ** Returns          TRUE if at least one time is running in the system, FALSE
99 **                  else.
100 **
101 *******************************************************************************/
gki_timers_is_timer_running(void)102 bool gki_timers_is_timer_running(void) {
103   uint8_t tt;
104   for (tt = 0; tt < GKI_MAX_TASKS; tt++) {
105 #if (GKI_NUM_TIMERS > 0)
106     if (gki_cb.com.OSTaskTmr0[tt]) {
107       return true;
108     }
109 #endif
110 
111 #if (GKI_NUM_TIMERS > 1)
112     if (gki_cb.com.OSTaskTmr1[tt]) {
113       return true;
114     }
115 #endif
116 
117 #if (GKI_NUM_TIMERS > 2)
118     if (gki_cb.com.OSTaskTmr2[tt]) {
119       return true;
120     }
121 #endif
122 
123 #if (GKI_NUM_TIMERS > 3)
124     if (gki_cb.com.OSTaskTmr3[tt]) {
125       return true;
126     }
127 #endif
128   }
129 
130   return false;
131 }
132 
133 /*******************************************************************************
134 **
135 ** Function         GKI_get_tick_count
136 **
137 ** Description      This function returns the current system ticks
138 **
139 ** Returns          The current number of system ticks
140 **
141 *******************************************************************************/
GKI_get_tick_count(void)142 uint32_t GKI_get_tick_count(void) { return gki_cb.com.OSTicks; }
143 
144 /*******************************************************************************
145 **
146 ** Function         GKI_ready_to_sleep
147 **
148 ** Description      This function returns the number of system ticks until the
149 **                  next timer will expire.  It is typically called by a power
150 **                  savings manager to find out how long it can have the system
151 **                  sleep before it needs to service the next entry.
152 **
153 ** Parameters:      None
154 **
155 ** Returns          Number of ticks til the next timer expires
156 **                  Note: The value is a signed  value.  This value should be
157 **                      compared to x > 0, to avoid misinterpreting negative
158 **                      tick values.
159 **
160 *******************************************************************************/
GKI_ready_to_sleep(void)161 int32_t GKI_ready_to_sleep(void) { return (gki_cb.com.OSTicksTilExp); }
162 
163 /*******************************************************************************
164 **
165 ** Function         GKI_start_timer
166 **
167 ** Description      An application can call this function to start one of
168 **                  it's four general purpose timers. Any of the four timers
169 **                  can be 1-shot or continuous. If a timer is already running,
170 **                  it will be reset to the new parameters.
171 **
172 ** Parameters       tnum            - (input) timer number to be started
173 **                                            (TIMER_0, TIMER_1, TIMER_2, or
174 **                                            TIMER_3)
175 **                  ticks           - (input) the number of system ticks til the
176 **                                            timer expires.
177 **                  is_continuous   - (input) TRUE if timer restarts
178 **                                            automatically, else FALSE if it is
179 **                                            a 'one-shot'.
180 **
181 ** Returns          void
182 **
183 *******************************************************************************/
GKI_start_timer(uint8_t tnum,int32_t ticks,bool is_continuous)184 void GKI_start_timer(uint8_t tnum, int32_t ticks, bool is_continuous) {
185   int32_t reload;
186   int32_t orig_ticks;
187   uint8_t task_id = GKI_get_taskid();
188   bool bad_timer = false;
189 
190   if (task_id >= GKI_MAX_TASKS) {
191     LOG(ERROR) << StringPrintf("%s: invalid task_id:0x%02x. start timer failed",
192                                __func__, task_id);
193     return;
194   }
195 
196   if (ticks <= 0) ticks = 1;
197 
198   orig_ticks = ticks; /* save the ticks in case adjustment is necessary */
199 
200   /* If continuous timer, set reload, else set it to 0 */
201   if (is_continuous)
202     reload = ticks;
203   else
204     reload = 0;
205 
206   GKI_disable();
207 
208   if (gki_timers_is_timer_running() == false) {
209 #if (GKI_DELAY_STOP_SYS_TICK > 0)
210     /* if inactivity delay timer is not running, start system tick */
211     if (gki_cb.com.OSTicksTilStop == 0) {
212 #endif
213       if (gki_cb.com.p_tick_cb) {
214         /* start system tick */
215         gki_cb.com.system_tick_running = true;
216         (gki_cb.com.p_tick_cb)(true);
217       }
218 #if (GKI_DELAY_STOP_SYS_TICK > 0)
219     } else {
220       /* clear inactivity delay timer */
221       gki_cb.com.OSTicksTilStop = 0;
222     }
223 #endif
224   }
225   /* Add the time since the last task timer update.
226   ** Note that this works when no timers are active since
227   ** both OSNumOrigTicks and OSTicksTilExp are 0.
228   */
229   if (GKI_MAX_INT32 - (gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) >
230       ticks) {
231     ticks += gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp;
232   } else
233     ticks = GKI_MAX_INT32;
234 
235   switch (tnum) {
236 #if (GKI_NUM_TIMERS > 0)
237     case TIMER_0:
238       gki_cb.com.OSTaskTmr0R[task_id] = reload;
239       gki_cb.com.OSTaskTmr0[task_id] = ticks;
240       break;
241 #endif
242 
243 #if (GKI_NUM_TIMERS > 1)
244     case TIMER_1:
245       gki_cb.com.OSTaskTmr1R[task_id] = reload;
246       gki_cb.com.OSTaskTmr1[task_id] = ticks;
247       break;
248 #endif
249 
250 #if (GKI_NUM_TIMERS > 2)
251     case TIMER_2:
252       gki_cb.com.OSTaskTmr2R[task_id] = reload;
253       gki_cb.com.OSTaskTmr2[task_id] = ticks;
254       break;
255 #endif
256 
257 #if (GKI_NUM_TIMERS > 3)
258     case TIMER_3:
259       gki_cb.com.OSTaskTmr3R[task_id] = reload;
260       gki_cb.com.OSTaskTmr3[task_id] = ticks;
261       break;
262 #endif
263     default:
264       bad_timer = true; /* Timer number is bad, so do not use */
265   }
266 
267   /* Update the expiration timeout if a legitimate timer */
268   if (!bad_timer) {
269     /* Only update the timeout value if it is less than any other newly started
270      * timers */
271     gki_adjust_timer_count(orig_ticks);
272   }
273 
274   GKI_enable();
275 }
276 
277 /*******************************************************************************
278 **
279 ** Function         GKI_stop_timer
280 **
281 ** Description      An application can call this function to stop one of
282 **                  it's four general purpose timers. There is no harm in
283 **                  stopping a timer that is already stopped.
284 **
285 ** Parameters       tnum - (input) timer number to be started (TIMER_0,
286 **                                 TIMER_1, TIMER_2, or TIMER_3)
287 ** Returns          void
288 **
289 *******************************************************************************/
GKI_stop_timer(uint8_t tnum)290 void GKI_stop_timer(uint8_t tnum) {
291   uint8_t task_id = GKI_get_taskid();
292 
293   GKI_disable();
294   if (task_id < GKI_MAX_TASKS) {
295     switch (tnum) {
296 #if (GKI_NUM_TIMERS > 0)
297       case TIMER_0:
298         gki_cb.com.OSTaskTmr0R[task_id] = 0;
299         gki_cb.com.OSTaskTmr0[task_id] = 0;
300         break;
301 #endif
302 
303 #if (GKI_NUM_TIMERS > 1)
304       case TIMER_1:
305         gki_cb.com.OSTaskTmr1R[task_id] = 0;
306         gki_cb.com.OSTaskTmr1[task_id] = 0;
307         break;
308 #endif
309 
310 #if (GKI_NUM_TIMERS > 2)
311       case TIMER_2:
312         gki_cb.com.OSTaskTmr2R[task_id] = 0;
313         gki_cb.com.OSTaskTmr2[task_id] = 0;
314         break;
315 #endif
316 
317 #if (GKI_NUM_TIMERS > 3)
318       case TIMER_3:
319         gki_cb.com.OSTaskTmr3R[task_id] = 0;
320         gki_cb.com.OSTaskTmr3[task_id] = 0;
321         break;
322 #endif
323     }
324   }
325 
326   if (gki_timers_is_timer_running() == false) {
327     if (gki_cb.com.p_tick_cb) {
328 #if (GKI_DELAY_STOP_SYS_TICK > 0)
329       /* if inactivity delay timer is not running */
330       if ((gki_cb.com.system_tick_running) &&
331           (gki_cb.com.OSTicksTilStop == 0)) {
332         /* set inactivity delay timer */
333         /* when timer expires, system tick will be stopped */
334         gki_cb.com.OSTicksTilStop = GKI_DELAY_STOP_SYS_TICK;
335       }
336 #else
337       gki_cb.com.system_tick_running = false;
338       (gki_cb.com.p_tick_cb)(false); /* stop system tick */
339 #endif
340     }
341   }
342 
343   GKI_enable();
344 }
345 
346 /*******************************************************************************
347 **
348 ** Function         GKI_timer_update
349 **
350 ** Description      This function is called by an OS to drive the GKI's timers.
351 **                  It is typically called at every system tick to
352 **                  update the timers for all tasks, and check for timeouts.
353 **
354 **                  Note: It has been designed to also allow for variable tick
355 **                        updates so that systems with strict power savings
356 **                        requirements can have the update occur at variable
357 **                        intervals.
358 **
359 ** Parameters:      ticks_since_last_update - (input) This is the number of
360 **                  TICKS that have occurred since the last time
361 **                  GKI_timer_update was called.
362 **
363 ** Returns          void
364 **
365 *******************************************************************************/
GKI_timer_update(int32_t ticks_since_last_update)366 void GKI_timer_update(int32_t ticks_since_last_update) {
367   uint8_t task_id;
368   long next_expiration; /* Holds the next soonest expiration time after this
369                            update */
370 
371   /* Increment the number of ticks used for time stamps */
372   gki_cb.com.OSTicks += ticks_since_last_update;
373 
374   /* If any timers are running in any tasks, decrement the remaining time til
375    * the timer updates need to take place (next expiration occurs)
376    */
377   gki_cb.com.OSTicksTilExp -= ticks_since_last_update;
378 
379   /* Don't allow timer interrupt nesting */
380   if (gki_cb.com.timer_nesting) return;
381 
382   gki_cb.com.timer_nesting = 1;
383 
384 #if (GKI_DELAY_STOP_SYS_TICK > 0)
385   /* if inactivity delay timer is set and expired */
386   if (gki_cb.com.OSTicksTilStop) {
387     if (gki_cb.com.OSTicksTilStop <= (uint32_t)ticks_since_last_update) {
388       if (gki_cb.com.p_tick_cb) {
389         gki_cb.com.system_tick_running = false;
390         (gki_cb.com.p_tick_cb)(false); /* stop system tick */
391       }
392       gki_cb.com.OSTicksTilStop = 0; /* clear inactivity delay timer */
393       gki_cb.com.timer_nesting = 0;
394       return;
395     } else
396       gki_cb.com.OSTicksTilStop -= ticks_since_last_update;
397   }
398 #endif
399 
400   /* No need to update the ticks if no timeout has occurred */
401   if (gki_cb.com.OSTicksTilExp > 0) {
402     gki_cb.com.timer_nesting = 0;
403     return;
404   }
405 
406   GKI_disable();
407 
408   next_expiration = GKI_NO_NEW_TMRS_STARTED;
409 
410   /* If here then gki_cb.com.OSTicksTilExp <= 0. If negative, then increase
411      gki_cb.com.OSNumOrigTicks
412      to account for the difference so timer updates below are decremented by the
413      full number
414      of ticks. gki_cb.com.OSNumOrigTicks is reset at the bottom of this function
415      so changing this
416      value only affects the timer updates below
417    */
418   gki_cb.com.OSNumOrigTicks -= gki_cb.com.OSTicksTilExp;
419 
420   /* Check for OS Task Timers */
421   for (task_id = 0; task_id < GKI_MAX_TASKS; task_id++) {
422     if (gki_cb.com.OSRdyTbl[task_id] == TASK_DEAD) {
423       // task is shutdown do not try to service timers
424       continue;
425     }
426 
427     if (gki_cb.com.OSWaitTmr[task_id] > 0) /* If timer is running */
428     {
429       gki_cb.com.OSWaitTmr[task_id] -= gki_cb.com.OSNumOrigTicks;
430       if (gki_cb.com.OSWaitTmr[task_id] <= 0) {
431         /* Timer Expired */
432         gki_cb.com.OSRdyTbl[task_id] = TASK_READY;
433       }
434     }
435 
436 #if (GKI_NUM_TIMERS > 0)
437     /* If any timer is running, decrement */
438     if (gki_cb.com.OSTaskTmr0[task_id] > 0) {
439       gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks;
440 
441       if (gki_cb.com.OSTaskTmr0[task_id] <= 0) {
442 /* Set Timer 0 Expired event mask and reload timer */
443 #if (GKI_TIMER_UPDATES_FROM_ISR == TRUE)
444         GKI_isend_event(task_id, TIMER_0_EVT_MASK);
445 #else
446         GKI_send_event(task_id, TIMER_0_EVT_MASK);
447 #endif
448         gki_cb.com.OSTaskTmr0[task_id] = gki_cb.com.OSTaskTmr0R[task_id];
449       }
450     }
451 
452     /* Check to see if this timer is the next one to expire */
453     if (gki_cb.com.OSTaskTmr0[task_id] > 0 &&
454         gki_cb.com.OSTaskTmr0[task_id] < next_expiration)
455       next_expiration = gki_cb.com.OSTaskTmr0[task_id];
456 #endif
457 
458 #if (GKI_NUM_TIMERS > 1)
459     /* If any timer is running, decrement */
460     if (gki_cb.com.OSTaskTmr1[task_id] > 0) {
461       gki_cb.com.OSTaskTmr1[task_id] -= gki_cb.com.OSNumOrigTicks;
462 
463       if (gki_cb.com.OSTaskTmr1[task_id] <= 0) {
464 /* Set Timer 1 Expired event mask and reload timer */
465 #if (GKI_TIMER_UPDATES_FROM_ISR == TRUE)
466         GKI_isend_event(task_id, TIMER_1_EVT_MASK);
467 #else
468         GKI_send_event(task_id, TIMER_1_EVT_MASK);
469 #endif
470         gki_cb.com.OSTaskTmr1[task_id] = gki_cb.com.OSTaskTmr1R[task_id];
471       }
472     }
473 
474     /* Check to see if this timer is the next one to expire */
475     if (gki_cb.com.OSTaskTmr1[task_id] > 0 &&
476         gki_cb.com.OSTaskTmr1[task_id] < next_expiration)
477       next_expiration = gki_cb.com.OSTaskTmr1[task_id];
478 #endif
479 
480 #if (GKI_NUM_TIMERS > 2)
481     /* If any timer is running, decrement */
482     if (gki_cb.com.OSTaskTmr2[task_id] > 0) {
483       gki_cb.com.OSTaskTmr2[task_id] -= gki_cb.com.OSNumOrigTicks;
484 
485       if (gki_cb.com.OSTaskTmr2[task_id] <= 0) {
486 /* Set Timer 2 Expired event mask and reload timer */
487 #if (GKI_TIMER_UPDATES_FROM_ISR == TRUE)
488         GKI_isend_event(task_id, TIMER_2_EVT_MASK);
489 #else
490         GKI_send_event(task_id, TIMER_2_EVT_MASK);
491 #endif
492         gki_cb.com.OSTaskTmr2[task_id] = gki_cb.com.OSTaskTmr2R[task_id];
493       }
494     }
495 
496     /* Check to see if this timer is the next one to expire */
497     if (gki_cb.com.OSTaskTmr2[task_id] > 0 &&
498         gki_cb.com.OSTaskTmr2[task_id] < next_expiration)
499       next_expiration = gki_cb.com.OSTaskTmr2[task_id];
500 #endif
501 
502 #if (GKI_NUM_TIMERS > 3)
503     /* If any timer is running, decrement */
504     if (gki_cb.com.OSTaskTmr3[task_id] > 0) {
505       gki_cb.com.OSTaskTmr3[task_id] -= gki_cb.com.OSNumOrigTicks;
506 
507       if (gki_cb.com.OSTaskTmr3[task_id] <= 0) {
508 /* Set Timer 3 Expired event mask and reload timer */
509 #if (GKI_TIMER_UPDATES_FROM_ISR == TRUE)
510         GKI_isend_event(task_id, TIMER_3_EVT_MASK);
511 #else
512         GKI_send_event(task_id, TIMER_3_EVT_MASK);
513 #endif
514         gki_cb.com.OSTaskTmr3[task_id] = gki_cb.com.OSTaskTmr3R[task_id];
515       }
516     }
517 
518     /* Check to see if this timer is the next one to expire */
519     if (gki_cb.com.OSTaskTmr3[task_id] > 0 &&
520         gki_cb.com.OSTaskTmr3[task_id] < next_expiration)
521       next_expiration = gki_cb.com.OSTaskTmr3[task_id];
522 #endif
523   }
524 
525   /* Set the next timer experation value if there is one to start */
526   if (next_expiration < GKI_NO_NEW_TMRS_STARTED) {
527     gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = next_expiration;
528   } else {
529     gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = 0;
530   }
531 
532   gki_cb.com.timer_nesting = 0;
533 
534   GKI_enable();
535 
536   return;
537 }
538 
539 /*******************************************************************************
540 **
541 ** Function         GKI_timer_queue_empty
542 **
543 ** Description      This function is called by applications to see whether the
544 **                  timer queue is empty
545 **
546 ** Parameters
547 **
548 ** Returns          bool
549 **
550 *******************************************************************************/
GKI_timer_queue_empty(void)551 bool GKI_timer_queue_empty(void) {
552   uint8_t tt;
553 
554   for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) {
555     if (gki_cb.com.timer_queues[tt]) return false;
556   }
557 
558   return true;
559 }
560 
561 /*******************************************************************************
562 **
563 ** Function         GKI_timer_queue_register_callback
564 **
565 ** Description      This function is called by applications to register system
566 **                  tick start/stop callback for time queues
567 **
568 **
569 ** Parameters       p_callback - (input) pointer to the system tick callback
570 **
571 ** Returns          bool
572 **
573 *******************************************************************************/
GKI_timer_queue_register_callback(SYSTEM_TICK_CBACK * p_callback)574 void GKI_timer_queue_register_callback(SYSTEM_TICK_CBACK* p_callback) {
575   gki_cb.com.p_tick_cb = p_callback;
576 
577   return;
578 }
579 
580 /*******************************************************************************
581 **
582 ** Function         GKI_init_timer_list
583 **
584 ** Description      This function is called by applications when they
585 **                  want to initialize a timer list.
586 **
587 ** Parameters       p_timer_listq - (input) pointer to the timer list queue
588 **                                          object
589 **
590 ** Returns          void
591 **
592 *******************************************************************************/
GKI_init_timer_list(TIMER_LIST_Q * p_timer_listq)593 void GKI_init_timer_list(TIMER_LIST_Q* p_timer_listq) {
594   p_timer_listq->p_first = nullptr;
595   p_timer_listq->p_last = nullptr;
596   p_timer_listq->last_ticks = 0;
597 
598   return;
599 }
600 
601 /*******************************************************************************
602 **
603 ** Function         GKI_init_timer_list_entry
604 **
605 ** Description      This function is called by the applications when they
606 **                  want to initialize a timer list entry. This must be
607 **                  done prior to first use of the entry.
608 **
609 ** Parameters       p_tle - (input) pointer to a timer list queue entry
610 **
611 ** Returns          void
612 **
613 *******************************************************************************/
GKI_init_timer_list_entry(TIMER_LIST_ENT * p_tle)614 void GKI_init_timer_list_entry(TIMER_LIST_ENT* p_tle) {
615   p_tle->p_next = nullptr;
616   p_tle->p_prev = nullptr;
617   p_tle->ticks = GKI_UNUSED_LIST_ENTRY;
618   p_tle->in_use = false;
619 }
620 
621 /*******************************************************************************
622 **
623 ** Function         GKI_update_timer_list
624 **
625 ** Description      This function is called by the applications when they
626 **                  want to update a timer list. This should be at every
627 **                  timer list unit tick, e.g. once per sec, once per minute
628 **                  etc.
629 **
630 ** Parameters       p_timer_listq - (input) pointer to the timer list queue
631 **                  object
632 **                  num_units_since_last_update - (input) number of units since
633 **                  the last update (allows for variable unit update)
634 **
635 ** NOTE: The following timer list update routines should not be used for exact
636 **       time critical purposes.  The timer tasks should be used when exact
637 **       timing is needed.
638 **
639 ** Returns          the number of timers that have expired
640 **
641 *******************************************************************************/
GKI_update_timer_list(TIMER_LIST_Q * p_timer_listq,int32_t num_units_since_last_update)642 uint16_t GKI_update_timer_list(TIMER_LIST_Q* p_timer_listq,
643                                int32_t num_units_since_last_update) {
644   TIMER_LIST_ENT* p_tle;
645   uint16_t num_time_out = 0;
646   int32_t rem_ticks;
647   int32_t temp_ticks;
648 
649   p_tle = p_timer_listq->p_first;
650 
651   /* First, get the guys who have previously timed out */
652   /* Note that the tick value of the timers should always be '0' */
653   while ((p_tle) && (p_tle->ticks <= 0)) {
654     num_time_out++;
655     p_tle = p_tle->p_next;
656   }
657 
658   /* Timer entriy tick values are relative to the preceeding entry */
659   rem_ticks = num_units_since_last_update;
660 
661   /* Now, adjust remaining timer entries */
662   while ((p_tle != nullptr) && (rem_ticks > 0)) {
663     temp_ticks = p_tle->ticks;
664     p_tle->ticks -= rem_ticks;
665 
666     /* See if this timer has just timed out */
667     if (p_tle->ticks <= 0) {
668       /* We set the number of ticks to '0' so that the legacy code
669        * that assumes a '0' or nonzero value will still work as coded. */
670       p_tle->ticks = 0;
671 
672       num_time_out++;
673     }
674 
675     rem_ticks -= temp_ticks; /* Decrement the remaining ticks to process */
676     p_tle = p_tle->p_next;
677   }
678 
679   if (p_timer_listq->last_ticks > 0) {
680     p_timer_listq->last_ticks -= num_units_since_last_update;
681 
682     /* If the last timer has expired set last_ticks to 0 so that other list
683      * update
684      * functions will calculate correctly
685      */
686     if (p_timer_listq->last_ticks < 0) p_timer_listq->last_ticks = 0;
687   }
688 
689   return (num_time_out);
690 }
691 
GKI_timer_list_empty(TIMER_LIST_Q * p_timer_listq)692 bool GKI_timer_list_empty(TIMER_LIST_Q* p_timer_listq) {
693   return p_timer_listq->p_first == nullptr;
694 }
695 
GKI_timer_list_first(TIMER_LIST_Q * p_timer_listq)696 TIMER_LIST_ENT* GKI_timer_list_first(TIMER_LIST_Q* p_timer_listq) {
697   return p_timer_listq->p_first;
698 }
699 
700 /*******************************************************************************
701 **
702 ** Function         GKI_get_remaining_ticks
703 **
704 ** Description      This function is called by an application to get remaining
705 **                  ticks to expire
706 **
707 ** Parameters       p_timer_listq - (input) pointer to the timer list queue
708 **                                          object
709 **                  p_target_tle - (input) pointer to a timer list queue entry
710 **
711 ** Returns          0 if timer is not used or timer is not in the list
712 **                  remaining ticks if success
713 **
714 *******************************************************************************/
GKI_get_remaining_ticks(TIMER_LIST_Q * p_timer_listq,TIMER_LIST_ENT * p_target_tle)715 uint32_t GKI_get_remaining_ticks(TIMER_LIST_Q* p_timer_listq,
716                                  TIMER_LIST_ENT* p_target_tle) {
717   TIMER_LIST_ENT* p_tle;
718   uint32_t rem_ticks = 0;
719 
720   if (p_target_tle->in_use) {
721     p_tle = p_timer_listq->p_first;
722 
723     /* adding up all of ticks in previous entries */
724     while ((p_tle) && (p_tle != p_target_tle)) {
725       rem_ticks += p_tle->ticks;
726       p_tle = p_tle->p_next;
727     }
728 
729     /* if found target entry */
730     if (p_tle == p_target_tle) {
731       rem_ticks += p_tle->ticks;
732     } else {
733       LOG(ERROR) << StringPrintf(
734           "GKI_get_remaining_ticks: No timer entry in the list");
735       return (0);
736     }
737   } else {
738     LOG(ERROR) << StringPrintf(
739         "GKI_get_remaining_ticks: timer entry is not active");
740   }
741 
742   return (rem_ticks);
743 }
744 
745 /*******************************************************************************
746 **
747 ** Function         GKI_add_to_timer_list
748 **
749 ** Description      This function is called by an application to add a timer
750 **                  entry to a timer list.
751 **
752 **                  Note: A timer value of '0' will effectively insert an
753 **                        already expired event.  Negative tick values will be
754 **                        ignored.
755 **
756 ** Parameters       p_timer_listq - (input) pointer to the timer list queue
757 **                                          object
758 **                  p_tle - (input) pointer to a timer list queue entry
759 **
760 ** Returns          void
761 **
762 *******************************************************************************/
GKI_add_to_timer_list(TIMER_LIST_Q * p_timer_listq,TIMER_LIST_ENT * p_tle)763 void GKI_add_to_timer_list(TIMER_LIST_Q* p_timer_listq, TIMER_LIST_ENT* p_tle) {
764   uint32_t nr_ticks_total;
765   uint8_t tt;
766   TIMER_LIST_ENT* p_temp;
767   if (p_tle == nullptr || p_timer_listq == nullptr) {
768     LOG(VERBOSE) << StringPrintf(
769         "%s: invalid argument %p, %p****************************<<", __func__,
770         p_timer_listq, p_tle);
771     return;
772   }
773 
774   /* Only process valid tick values */
775   if (p_tle->ticks >= 0) {
776     /* If this entry is the last in the list */
777     if (p_tle->ticks >= p_timer_listq->last_ticks) {
778       /* If this entry is the only entry in the list */
779       if (p_timer_listq->p_first == nullptr)
780         p_timer_listq->p_first = p_tle;
781       else {
782         /* Insert the entry onto the end of the list */
783         if (p_timer_listq->p_last != nullptr)
784           p_timer_listq->p_last->p_next = p_tle;
785 
786         p_tle->p_prev = p_timer_listq->p_last;
787       }
788 
789       p_tle->p_next = nullptr;
790       p_timer_listq->p_last = p_tle;
791       nr_ticks_total = p_tle->ticks;
792       p_tle->ticks -= p_timer_listq->last_ticks;
793 
794       p_timer_listq->last_ticks = nr_ticks_total;
795     } else /* This entry needs to be inserted before the last entry */
796     {
797       /* Find the entry that the new one needs to be inserted in front of */
798       p_temp = p_timer_listq->p_first;
799       while (p_tle->ticks > p_temp->ticks) {
800         /* Update the tick value if looking at an unexpired entry */
801         if (p_temp->ticks > 0) p_tle->ticks -= p_temp->ticks;
802 
803         p_temp = p_temp->p_next;
804       }
805 
806       /* The new entry is the first in the list */
807       if (p_temp == p_timer_listq->p_first) {
808         p_tle->p_next = p_timer_listq->p_first;
809         p_timer_listq->p_first->p_prev = p_tle;
810         p_timer_listq->p_first = p_tle;
811       } else {
812         p_temp->p_prev->p_next = p_tle;
813         p_tle->p_prev = p_temp->p_prev;
814         p_temp->p_prev = p_tle;
815         p_tle->p_next = p_temp;
816       }
817       p_temp->ticks -= p_tle->ticks;
818     }
819 
820     p_tle->in_use = true;
821 
822     /* if we already add this timer queue to the array */
823     for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) {
824       if (gki_cb.com.timer_queues[tt] == p_timer_listq) return;
825     }
826     /* add this timer queue to the array */
827     for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) {
828       if (gki_cb.com.timer_queues[tt] == nullptr) break;
829     }
830     if (tt < GKI_MAX_TIMER_QUEUES) {
831       gki_cb.com.timer_queues[tt] = p_timer_listq;
832     }
833   }
834 
835   return;
836 }
837 
838 /*******************************************************************************
839 **
840 ** Function         GKI_remove_from_timer_list
841 **
842 ** Description      This function is called by an application to remove a timer
843 **                  entry from a timer list.
844 **
845 ** Parameters       p_timer_listq  - (input) pointer to the timer list queue
846 **                                            object
847 **                  p_tle - (input) pointer to a timer list queue entry
848 **
849 ** Returns          void
850 **
851 *******************************************************************************/
GKI_remove_from_timer_list(TIMER_LIST_Q * p_timer_listq,TIMER_LIST_ENT * p_tle)852 void GKI_remove_from_timer_list(TIMER_LIST_Q* p_timer_listq,
853                                 TIMER_LIST_ENT* p_tle) {
854   uint8_t tt;
855 
856   /* Verify that the entry is valid */
857   if (p_tle == nullptr || p_tle->in_use == false ||
858       p_timer_listq->p_first == nullptr) {
859     return;
860   }
861 
862   /* Add the ticks remaining in this timer (if any) to the next guy in the list.
863   ** Note: Expired timers have a tick value of '0'.
864   */
865   if (p_tle->p_next != nullptr) {
866     p_tle->p_next->ticks += p_tle->ticks;
867   } else {
868     p_timer_listq->last_ticks -= p_tle->ticks;
869   }
870 
871   /* Unlink timer from the list. */
872   if (p_timer_listq->p_first == p_tle) {
873     p_timer_listq->p_first = p_tle->p_next;
874 
875     if (p_timer_listq->p_first != nullptr)
876       p_timer_listq->p_first->p_prev = nullptr;
877 
878     if (p_timer_listq->p_last == p_tle) p_timer_listq->p_last = nullptr;
879   } else {
880     if (p_timer_listq->p_last == p_tle) {
881       p_timer_listq->p_last = p_tle->p_prev;
882 
883       if (p_timer_listq->p_last != nullptr)
884         p_timer_listq->p_last->p_next = nullptr;
885     } else {
886       if (p_tle->p_next != nullptr && p_tle->p_next->p_prev == p_tle)
887         p_tle->p_next->p_prev = p_tle->p_prev;
888       else {
889         /* Error case - chain messed up ?? */
890         return;
891       }
892 
893       if (p_tle->p_prev != nullptr && p_tle->p_prev->p_next == p_tle)
894         p_tle->p_prev->p_next = p_tle->p_next;
895       else {
896         /* Error case - chain messed up ?? */
897         return;
898       }
899     }
900   }
901 
902   p_tle->p_next = p_tle->p_prev = nullptr;
903   p_tle->ticks = GKI_UNUSED_LIST_ENTRY;
904   p_tle->in_use = false;
905 
906   /* if timer queue is empty */
907   if (p_timer_listq->p_first == nullptr && p_timer_listq->p_last == nullptr) {
908     for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) {
909       if (gki_cb.com.timer_queues[tt] == p_timer_listq) {
910         gki_cb.com.timer_queues[tt] = nullptr;
911         break;
912       }
913     }
914     /* Recovering from unexpected state.
915        e.g. when TIMER_LIST_ENT is cleared before stop */
916     if (p_timer_listq->last_ticks) p_timer_listq->last_ticks = 0;
917   }
918 
919   return;
920 }
921 
922 /*******************************************************************************
923 **
924 ** Function         gki_adjust_timer_count
925 **
926 ** Description      This function is called whenever a new timer or GKI_wait
927 **                  occurs to adjust (if necessary) the current time til the
928 **                  first expiration. This only needs to make an adjustment if
929 **                  the new timer (in ticks) is less than the number of ticks
930 **                  remaining on the current timer.
931 **
932 ** Parameters:      ticks - (input) number of system ticks of the new timer
933 **                                  entry
934 **
935 **                  NOTE:  This routine MUST be called while interrupts are
936 **                         disabled to avoid updates while adjusting the timer
937 **                         variables.
938 **
939 ** Returns          void
940 **
941 *******************************************************************************/
gki_adjust_timer_count(int32_t ticks)942 void gki_adjust_timer_count(int32_t ticks) {
943   if (ticks > 0) {
944     /* See if the new timer expires before the current first expiration */
945     if (gki_cb.com.OSNumOrigTicks == 0 ||
946         (ticks < gki_cb.com.OSTicksTilExp && gki_cb.com.OSTicksTilExp > 0)) {
947       gki_cb.com.OSNumOrigTicks =
948           (gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) + ticks;
949       gki_cb.com.OSTicksTilExp = ticks;
950     }
951   }
952 
953   return;
954 }
955