• 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 
19 #include <assert.h>
20 #include <utils/Log.h>
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 
29 #define GKI_NO_NEW_TMRS_STARTED (0x7fffffffL)   /* Largest signed positive timer count */
30 
31 // Used for controlling alarms from AlarmService.
32 extern void alarm_service_reschedule(void);
33 
34 /*******************************************************************************
35 **
36 ** Function         gki_timers_init
37 **
38 ** Description      This internal function is called once at startup to initialize
39 **                  all the timer structures.
40 **
41 ** Returns          void
42 **
43 *******************************************************************************/
gki_timers_init(void)44 void gki_timers_init(void)
45 {
46     UINT8   tt;
47 
48     gki_cb.com.OSTicksTilExp = 0;       /* Remaining time (of OSTimeCurTimeout) before next timer expires */
49     gki_cb.com.OSNumOrigTicks = 0;
50 
51     for (tt = 0; tt < GKI_MAX_TASKS; tt++)
52     {
53         gki_cb.com.OSWaitTmr   [tt] = 0;
54 
55 #if (GKI_NUM_TIMERS > 0)
56         gki_cb.com.OSTaskTmr0  [tt] = 0;
57         gki_cb.com.OSTaskTmr0R [tt] = 0;
58 #endif
59 
60 #if (GKI_NUM_TIMERS > 1)
61         gki_cb.com.OSTaskTmr1  [tt] = 0;
62         gki_cb.com.OSTaskTmr1R [tt] = 0;
63 #endif
64 
65 #if (GKI_NUM_TIMERS > 2)
66         gki_cb.com.OSTaskTmr2  [tt] = 0;
67         gki_cb.com.OSTaskTmr2R [tt] = 0;
68 #endif
69 
70 #if (GKI_NUM_TIMERS > 3)
71         gki_cb.com.OSTaskTmr3  [tt] = 0;
72         gki_cb.com.OSTaskTmr3R [tt] = 0;
73 #endif
74     }
75 
76     return;
77 }
78 
79 /*******************************************************************************
80 **
81 ** Function         gki_timers_is_timer_running
82 **
83 ** Description      This internal function is called to test if any gki timer are running
84 **
85 **
86 ** Returns          TRUE if at least one time is running in the system, FALSE else.
87 **
88 *******************************************************************************/
gki_timers_is_timer_running(void)89 BOOLEAN gki_timers_is_timer_running(void)
90 {
91     UINT8   tt;
92     for (tt = 0; tt < GKI_MAX_TASKS; tt++)
93     {
94 
95 #if (GKI_NUM_TIMERS > 0)
96         if(gki_cb.com.OSTaskTmr0  [tt])
97         {
98             return TRUE;
99         }
100 #endif
101 
102 #if (GKI_NUM_TIMERS > 1)
103         if(gki_cb.com.OSTaskTmr1  [tt] )
104         {
105             return TRUE;
106         }
107 #endif
108 
109 #if (GKI_NUM_TIMERS > 2)
110         if(gki_cb.com.OSTaskTmr2  [tt] )
111         {
112             return TRUE;
113         }
114 #endif
115 
116 #if (GKI_NUM_TIMERS > 3)
117         if(gki_cb.com.OSTaskTmr3  [tt] )
118         {
119             return TRUE;
120         }
121 #endif
122     }
123 
124     return FALSE;
125 
126 }
127 
128 /*******************************************************************************
129 **
130 ** Function         GKI_get_tick_count
131 **
132 ** Description      This function returns the current system ticks
133 **
134 ** Returns          The current number of system ticks
135 **
136 *******************************************************************************/
GKI_get_tick_count(void)137 UINT32  GKI_get_tick_count(void)
138 {
139     return gki_cb.com.OSTicks;
140 }
141 
142 
143 /*******************************************************************************
144 **
145 ** Function         GKI_ready_to_sleep
146 **
147 ** Description      This function returns the number of system ticks until the
148 **                  next timer will expire.  It is typically called by a power
149 **                  savings manager to find out how long it can have the system
150 **                  sleep before it needs to service the next entry.
151 **
152 ** Parameters:      None
153 **
154 ** Returns          Number of ticks til the next timer expires
155 **                  Note: the value is a signed  value.  This value should be
156 **                      compared to x > 0, to avoid misinterpreting negative tick
157 **                      values.
158 **
159 *******************************************************************************/
GKI_ready_to_sleep(void)160 INT32    GKI_ready_to_sleep (void)
161 {
162     return (gki_cb.com.OSTicksTilExp);
163 }
164 
165 
166 /*******************************************************************************
167 **
168 ** Function         GKI_start_timer
169 **
170 ** Description      An application can call this function to start one of
171 **                  it's four general purpose timers. Any of the four timers
172 **                  can be 1-shot or continuous. If a timer is already running,
173 **                  it will be reset to the new parameters.
174 **
175 ** Parameters       tnum            - (input) timer number to be started (TIMER_0,
176 **                                              TIMER_1, TIMER_2, or TIMER_3)
177 **                  ticks           - (input) the number of system ticks til the
178 **                                              timer expires.
179 **                  is_continuous   - (input) TRUE if timer restarts automatically,
180 **                                              else FALSE if it is a 'one-shot'.
181 **
182 ** Returns          void
183 **
184 *******************************************************************************/
GKI_start_timer(UINT8 tnum,INT32 ticks,BOOLEAN is_continuous)185 void GKI_start_timer (UINT8 tnum, INT32 ticks, BOOLEAN is_continuous)
186 {
187     INT32   reload;
188     INT32   orig_ticks;
189     UINT8   task_id = GKI_get_taskid();
190     BOOLEAN bad_timer = FALSE;
191 
192     if (ticks <= 0)
193         ticks = 1;
194 
195     orig_ticks = ticks;     /* save the ticks in case adjustment is necessary */
196 
197 
198     /* If continuous timer, set reload, else set it to 0 */
199     if (is_continuous)
200         reload = ticks;
201     else
202         reload = 0;
203 
204     GKI_disable();
205 
206     /* Add the time since the last task timer update.
207     ** Note that this works when no timers are active since
208     ** both OSNumOrigTicks and OSTicksTilExp are 0.
209     */
210     if (INT32_MAX - (gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) > ticks)
211     {
212         ticks += gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp;
213     }
214     else
215         ticks = INT32_MAX;
216 
217     switch (tnum)
218     {
219 #if (GKI_NUM_TIMERS > 0)
220         case TIMER_0:
221             gki_cb.com.OSTaskTmr0R[task_id] = reload;
222             gki_cb.com.OSTaskTmr0 [task_id] = ticks;
223             break;
224 #endif
225 
226 #if (GKI_NUM_TIMERS > 1)
227         case TIMER_1:
228             gki_cb.com.OSTaskTmr1R[task_id] = reload;
229             gki_cb.com.OSTaskTmr1 [task_id] = ticks;
230             break;
231 #endif
232 
233 #if (GKI_NUM_TIMERS > 2)
234         case TIMER_2:
235             gki_cb.com.OSTaskTmr2R[task_id] = reload;
236             gki_cb.com.OSTaskTmr2 [task_id] = ticks;
237             break;
238 #endif
239 
240 #if (GKI_NUM_TIMERS > 3)
241         case TIMER_3:
242             gki_cb.com.OSTaskTmr3R[task_id] = reload;
243             gki_cb.com.OSTaskTmr3 [task_id] = ticks;
244             break;
245 #endif
246         default:
247             bad_timer = TRUE;       /* Timer number is bad, so do not use */
248     }
249 
250     /* Update the expiration timeout if a legitimate timer */
251     if (!bad_timer)
252     {
253         /* Only update the timeout value if it is less than any other newly started timers */
254         gki_adjust_timer_count (orig_ticks);
255     }
256 
257     GKI_enable();
258 
259 }
260 
261 /*******************************************************************************
262 **
263 ** Function         GKI_stop_timer
264 **
265 ** Description      An application can call this function to stop one of
266 **                  it's four general purpose timers. There is no harm in
267 **                  stopping a timer that is already stopped.
268 **
269 ** Parameters       tnum            - (input) timer number to be started (TIMER_0,
270 **                                              TIMER_1, TIMER_2, or TIMER_3)
271 ** Returns          void
272 **
273 *******************************************************************************/
GKI_stop_timer(UINT8 tnum)274 void GKI_stop_timer (UINT8 tnum)
275 {
276     UINT8  task_id = GKI_get_taskid();
277 
278     switch (tnum)
279     {
280 #if (GKI_NUM_TIMERS > 0)
281         case TIMER_0:
282             gki_cb.com.OSTaskTmr0R[task_id] = 0;
283             gki_cb.com.OSTaskTmr0 [task_id] = 0;
284             break;
285 #endif
286 
287 #if (GKI_NUM_TIMERS > 1)
288         case TIMER_1:
289             gki_cb.com.OSTaskTmr1R[task_id] = 0;
290             gki_cb.com.OSTaskTmr1 [task_id] = 0;
291             break;
292 #endif
293 
294 #if (GKI_NUM_TIMERS > 2)
295         case TIMER_2:
296             gki_cb.com.OSTaskTmr2R[task_id] = 0;
297             gki_cb.com.OSTaskTmr2 [task_id] = 0;
298             break;
299 #endif
300 
301 #if (GKI_NUM_TIMERS > 3)
302         case TIMER_3:
303             gki_cb.com.OSTaskTmr3R[task_id] = 0;
304             gki_cb.com.OSTaskTmr3 [task_id] = 0;
305             break;
306 #endif
307     }
308 }
309 
310 
311 /*******************************************************************************
312 **
313 ** Function         GKI_timer_update
314 **
315 ** Description      This function is called by an OS to drive the GKI's timers.
316 **                  It is typically called at every system tick to
317 **                  update the timers for all tasks, and check for timeouts.
318 **
319 **                  Note: It has been designed to also allow for variable tick updates
320 **                      so that systems with strict power savings requirements can
321 **                      have the update occur at variable intervals.
322 **
323 ** Parameters:      ticks_since_last_update - (input) This is the number of TICKS that have
324 **                          occurred since the last time GKI_timer_update was called.
325 **
326 ** Returns          void
327 **
328 *******************************************************************************/
GKI_timer_update(INT32 ticks_since_last_update)329 void GKI_timer_update (INT32 ticks_since_last_update)
330 {
331     UINT8   task_id;
332     long    next_expiration;        /* Holds the next soonest expiration time after this update */
333 
334     /* Increment the number of ticks used for time stamps */
335     gki_cb.com.OSTicks += ticks_since_last_update;
336 
337     /* If any timers are running in any tasks, decrement the remaining time til
338      * the timer updates need to take place (next expiration occurs)
339      */
340     gki_cb.com.OSTicksTilExp -= ticks_since_last_update;
341 
342     /* Don't allow timer interrupt nesting */
343     if (gki_cb.com.timer_nesting)
344         return;
345 
346     gki_cb.com.timer_nesting = 1;
347 
348     /* No need to update the ticks if no timeout has occurred */
349     if (gki_cb.com.OSTicksTilExp > 0)
350     {
351         // When using alarms from AlarmService we should
352         // always have work to be done here.
353         ALOGE("%s no work to be done when expected work", __func__);
354         gki_cb.com.timer_nesting = 0;
355         return;
356     }
357 
358     next_expiration = GKI_NO_NEW_TMRS_STARTED;
359 
360     /* If here then gki_cb.com.OSTicksTilExp <= 0. If negative, then increase gki_cb.com.OSNumOrigTicks
361        to account for the difference so timer updates below are decremented by the full number
362        of ticks. gki_cb.com.OSNumOrigTicks is reset at the bottom of this function so changing this
363        value only affects the timer updates below
364      */
365     gki_cb.com.OSNumOrigTicks -= gki_cb.com.OSTicksTilExp;
366 
367     /* Protect this section because if a GKI_timer_stop happens between:
368      *   - gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks;
369      *   - gki_cb.com.OSTaskTmr0[task_id] = gki_cb.com.OSTaskTmr0R[task_id];
370      * then the timer may appear stopped while it is about to be reloaded.
371      */
372     GKI_disable();
373 
374     /* Check for OS Task Timers */
375     for (task_id = 0; task_id < GKI_MAX_TASKS; task_id++)
376     {
377         if (gki_cb.com.OSWaitTmr[task_id] > 0) /* If timer is running */
378         {
379             gki_cb.com.OSWaitTmr[task_id] -= gki_cb.com.OSNumOrigTicks;
380             if (gki_cb.com.OSWaitTmr[task_id] <= 0)
381             {
382                 /* Timer Expired */
383                 gki_cb.com.OSRdyTbl[task_id] = TASK_READY;
384             }
385         }
386 
387 #if (GKI_NUM_TIMERS > 0)
388          /* If any timer is running, decrement */
389         if (gki_cb.com.OSTaskTmr0[task_id] > 0)
390         {
391             gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks;
392 
393             if (gki_cb.com.OSTaskTmr0[task_id] <= 0)
394             {
395                 /* Reload timer and set Timer 0 Expired event mask */
396                 gki_cb.com.OSTaskTmr0[task_id] = gki_cb.com.OSTaskTmr0R[task_id];
397                 GKI_send_event (task_id, TIMER_0_EVT_MASK);
398             }
399         }
400 
401         /* Check to see if this timer is the next one to expire */
402         if (gki_cb.com.OSTaskTmr0[task_id] > 0 && gki_cb.com.OSTaskTmr0[task_id] < next_expiration)
403             next_expiration = gki_cb.com.OSTaskTmr0[task_id];
404 #endif
405 
406 #if (GKI_NUM_TIMERS > 1)
407          /* If any timer is running, decrement */
408         if (gki_cb.com.OSTaskTmr1[task_id] > 0)
409         {
410             gki_cb.com.OSTaskTmr1[task_id] -= gki_cb.com.OSNumOrigTicks;
411 
412             if (gki_cb.com.OSTaskTmr1[task_id] <= 0)
413             {
414                 /* Reload timer and set Timer 1 Expired event mask */
415                 gki_cb.com.OSTaskTmr1[task_id] = gki_cb.com.OSTaskTmr1R[task_id];
416                 GKI_send_event (task_id, TIMER_1_EVT_MASK);
417             }
418         }
419 
420         /* Check to see if this timer is the next one to expire */
421         if (gki_cb.com.OSTaskTmr1[task_id] > 0 && gki_cb.com.OSTaskTmr1[task_id] < next_expiration)
422             next_expiration = gki_cb.com.OSTaskTmr1[task_id];
423 #endif
424 
425 #if (GKI_NUM_TIMERS > 2)
426          /* If any timer is running, decrement */
427         if (gki_cb.com.OSTaskTmr2[task_id] > 0)
428         {
429             gki_cb.com.OSTaskTmr2[task_id] -= gki_cb.com.OSNumOrigTicks;
430 
431             if (gki_cb.com.OSTaskTmr2[task_id] <= 0)
432             {
433                 /* Reload timer and set Timer 2 Expired event mask */
434                 gki_cb.com.OSTaskTmr2[task_id] = gki_cb.com.OSTaskTmr2R[task_id];
435                 GKI_send_event (task_id, TIMER_2_EVT_MASK);
436             }
437         }
438 
439         /* Check to see if this timer is the next one to expire */
440         if (gki_cb.com.OSTaskTmr2[task_id] > 0 && gki_cb.com.OSTaskTmr2[task_id] < next_expiration)
441             next_expiration = gki_cb.com.OSTaskTmr2[task_id];
442 #endif
443 
444 #if (GKI_NUM_TIMERS > 3)
445          /* If any timer is running, decrement */
446         if (gki_cb.com.OSTaskTmr3[task_id] > 0)
447         {
448             gki_cb.com.OSTaskTmr3[task_id] -= gki_cb.com.OSNumOrigTicks;
449 
450             if (gki_cb.com.OSTaskTmr3[task_id] <= 0)
451             {
452                 /* Reload timer and set Timer 3 Expired event mask */
453                 gki_cb.com.OSTaskTmr3[task_id] = gki_cb.com.OSTaskTmr3R[task_id];
454                 GKI_send_event (task_id, TIMER_3_EVT_MASK);
455             }
456         }
457 
458         /* Check to see if this timer is the next one to expire */
459         if (gki_cb.com.OSTaskTmr3[task_id] > 0 && gki_cb.com.OSTaskTmr3[task_id] < next_expiration)
460             next_expiration = gki_cb.com.OSTaskTmr3[task_id];
461 #endif
462 
463     }
464     /* Set the next timer experation value if there is one to start */
465     if (next_expiration < GKI_NO_NEW_TMRS_STARTED)
466     {
467         gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = next_expiration;
468     }
469     else
470     {
471         gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = 0;
472     }
473 
474     // Set alarm service for next alarm.
475     alarm_service_reschedule();
476 
477     GKI_enable();
478 
479     gki_cb.com.timer_nesting = 0;
480 
481     return;
482 }
483 
484 /*******************************************************************************
485 **
486 ** Function         GKI_init_timer_list
487 **
488 ** Description      This function is called by applications when they
489 **                  want to initialize a timer list.
490 **
491 ** Parameters       p_timer_listq   - (input) pointer to the timer list queue object
492 **
493 ** Returns          void
494 **
495 *******************************************************************************/
GKI_init_timer_list(TIMER_LIST_Q * timer_q)496 void GKI_init_timer_list(TIMER_LIST_Q *timer_q) {
497     timer_q->p_first    = NULL;
498     timer_q->p_last     = NULL;
499 }
500 
GKI_timer_queue_is_empty(const TIMER_LIST_Q * timer_q)501 bool GKI_timer_queue_is_empty(const TIMER_LIST_Q *timer_q) {
502     assert(timer_q != NULL);
503     return (timer_q->p_first == NULL);
504 }
505 
GKI_timer_getfirst(const TIMER_LIST_Q * timer_q)506 TIMER_LIST_ENT *GKI_timer_getfirst(const TIMER_LIST_Q *timer_q) {
507     assert(timer_q != NULL);
508     return timer_q->p_first;
509 }
510 
511 /* Returns the initial number of ticks for this timer entry. */
GKI_timer_ticks_getinitial(const TIMER_LIST_ENT * tle)512 INT32 GKI_timer_ticks_getinitial(const TIMER_LIST_ENT *tle) {
513     assert(tle != NULL);
514     return tle->ticks_initial;
515 }
516 
517 /*******************************************************************************
518 **
519 ** Function         GKI_update_timer_list
520 **
521 ** Description      This function is called by the applications when they
522 **                  want to update a timer list. This should be at every
523 **                  timer list unit tick, e.g. once per sec, once per minute etc.
524 **
525 ** Parameters       p_timer_listq   - (input) pointer to the timer list queue object
526 **                  num_units_since_last_update - (input) number of units since the last update
527 **                                  (allows for variable unit update)
528 **
529 **      NOTE: The following timer list update routines should not be used for exact time
530 **            critical purposes.  The timer tasks should be used when exact timing is needed.
531 **
532 ** Returns          the number of timers that have expired
533 **
534 *******************************************************************************/
GKI_update_timer_list(TIMER_LIST_Q * p_timer_listq,INT32 num_units_since_last_update)535 UINT16 GKI_update_timer_list (TIMER_LIST_Q *p_timer_listq, INT32 num_units_since_last_update)
536 {
537     TIMER_LIST_ENT  *p_tle;
538     UINT16           num_time_out = 0;
539     INT32            rem_ticks;
540     INT32            temp_ticks;
541 
542     p_tle = p_timer_listq->p_first;
543 
544     /* First, get the guys who have previously timed out */
545     /* Note that the tick value of the timers should always be '0' */
546     while ((p_tle) && (p_tle->ticks <= 0))
547     {
548         num_time_out++;
549         p_tle = p_tle->p_next;
550     }
551 
552     /* Timer entriy tick values are relative to the preceeding entry */
553     rem_ticks = num_units_since_last_update;
554 
555     /* Now, adjust remaining timer entries */
556     while ((p_tle != NULL) && (rem_ticks > 0))
557     {
558         temp_ticks = p_tle->ticks;
559         p_tle->ticks -= rem_ticks;
560 
561         /* See if this timer has just timed out */
562         if (p_tle->ticks <= 0)
563         {
564             /* We set the number of ticks to '0' so that the legacy code
565              * that assumes a '0' or nonzero value will still work as coded. */
566             p_tle->ticks = 0;
567 
568             num_time_out++;
569         }
570 
571         rem_ticks -= temp_ticks;  /* Decrement the remaining ticks to process */
572         p_tle = p_tle->p_next;
573     }
574 
575     return (num_time_out);
576 }
577 
578 /*******************************************************************************
579 **
580 ** Function         GKI_get_remaining_ticks
581 **
582 ** Description      This function is called by an application to get remaining
583 **                  ticks to expire
584 **
585 ** Parameters       p_timer_listq   - (input) pointer to the timer list queue object
586 **                  p_target_tle    - (input) pointer to a timer list queue entry
587 **
588 ** Returns          0 if timer is not used or timer is not in the list
589 **                  remaining ticks if success
590 **
591 *******************************************************************************/
GKI_get_remaining_ticks(TIMER_LIST_Q * p_timer_listq,TIMER_LIST_ENT * p_target_tle)592 UINT32 GKI_get_remaining_ticks (TIMER_LIST_Q *p_timer_listq, TIMER_LIST_ENT  *p_target_tle)
593 {
594     TIMER_LIST_ENT  *p_tle;
595     UINT32           rem_ticks = 0;
596 
597     if (p_target_tle->in_use)
598     {
599         p_tle = p_timer_listq->p_first;
600 
601         /* adding up all of ticks in previous entries */
602         while ((p_tle)&&(p_tle != p_target_tle))
603         {
604             rem_ticks += p_tle->ticks;
605             p_tle = p_tle->p_next;
606         }
607 
608         /* if found target entry */
609         if (p_tle == p_target_tle)
610         {
611             rem_ticks += p_tle->ticks;
612         }
613         else
614         {
615             return(0);
616         }
617     }
618 
619     return (rem_ticks);
620 }
621 
622 /*******************************************************************************
623 **
624 ** Function         GKI_add_to_timer_list
625 **
626 ** Description      This function is called by an application to add a timer
627 **                  entry to a timer list.
628 **
629 **                  Note: A timer value of '0' will effectively insert an already
630 **                      expired event.  Negative tick values will be ignored.
631 **
632 ** Parameters       p_timer_listq   - (input) pointer to the timer list queue object
633 **                  p_tle           - (input) pointer to a timer list queue entry
634 **
635 ** Returns          void
636 **
637 *******************************************************************************/
GKI_add_to_timer_list(TIMER_LIST_Q * p_timer_listq,TIMER_LIST_ENT * p_tle)638 void GKI_add_to_timer_list (TIMER_LIST_Q *p_timer_listq, TIMER_LIST_ENT  *p_tle)
639 {
640     /* Only process valid tick values. */
641     if (p_tle->ticks < 0)
642         return;
643 
644     p_tle->p_prev = NULL;
645     p_tle->p_next = NULL;
646     p_tle->in_use = true;
647 
648     /* Insert at head. */
649     if (p_timer_listq->p_first == NULL)
650     {
651         p_timer_listq->p_first = p_tle;
652         p_timer_listq->p_last = p_tle;
653         return;
654     }
655 
656     /* Find the node before which we need to insert p_tle. */
657     TIMER_LIST_ENT *i = p_timer_listq->p_first;
658     while (i && p_tle->ticks > i->ticks)
659     {
660         if (i->ticks > 0)
661             p_tle->ticks -= i->ticks;
662         i = i->p_next;
663     }
664 
665     /* Insert at tail. */
666     if (!i)
667     {
668         p_timer_listq->p_last->p_next = p_tle;
669         p_tle->p_prev = p_timer_listq->p_last;
670         p_timer_listq->p_last = p_tle;
671         return;
672     }
673 
674     p_tle->p_prev = i->p_prev;
675     if (p_tle->p_prev)
676         p_tle->p_prev->p_next = p_tle;
677     p_tle->p_next = i;
678     i->p_prev = p_tle;
679     i->ticks -= p_tle->ticks;
680 
681     if (p_timer_listq->p_first == i)
682         p_timer_listq->p_first = p_tle;
683 }
684 
685 
686 /*******************************************************************************
687 **
688 ** Function         GKI_remove_from_timer_list
689 **
690 ** Description      This function is called by an application to remove a timer
691 **                  entry from a timer list.
692 **
693 ** Parameters       p_timer_listq   - (input) pointer to the timer list queue object
694 **                  p_tle           - (input) pointer to a timer list queue entry
695 **
696 ** Returns          TRUE if the entry has been unlinked successfully
697 **
698 *******************************************************************************/
GKI_remove_from_timer_list(TIMER_LIST_Q * p_timer_listq,TIMER_LIST_ENT * p_tle)699 BOOLEAN GKI_remove_from_timer_list (TIMER_LIST_Q *p_timer_listq, TIMER_LIST_ENT  *p_tle)
700 {
701     UINT8 tt;
702 
703     /* Verify that the entry is valid */
704     if (p_tle == NULL || p_timer_listq->p_first == NULL)
705         return FALSE;
706 
707     /* Add the ticks remaining in this timer (if any) to the next guy in the list.
708     ** Note: Expired timers have a tick value of '0'.
709     */
710     if (p_tle->p_next != NULL)
711     {
712         p_tle->p_next->ticks += p_tle->ticks;
713     }
714 
715     p_tle->ticks = 0;
716     p_tle->in_use = FALSE;
717 
718     /* Unlink timer from the list.
719     */
720     if (p_timer_listq->p_first == p_tle)
721     {
722         p_timer_listq->p_first = p_tle->p_next;
723 
724         if (p_timer_listq->p_first != NULL)
725             p_timer_listq->p_first->p_prev = NULL;
726 
727         if (p_timer_listq->p_last == p_tle)
728             p_timer_listq->p_last = NULL;
729     }
730     else
731     {
732         if (p_timer_listq->p_last == p_tle)
733         {
734             p_timer_listq->p_last = p_tle->p_prev;
735 
736             if (p_timer_listq->p_last != NULL)
737                 p_timer_listq->p_last->p_next = NULL;
738         }
739         else
740         {
741             if (p_tle->p_next != NULL && p_tle->p_next->p_prev == p_tle)
742                 p_tle->p_next->p_prev = p_tle->p_prev;
743             else
744                 return FALSE; // Timer list broken?!
745 
746             if (p_tle->p_prev != NULL && p_tle->p_prev->p_next == p_tle)
747                 p_tle->p_prev->p_next = p_tle->p_next;
748             else
749                 return FALSE; // Timer list broken?!
750         }
751     }
752 
753     p_tle->p_next = p_tle->p_prev = NULL;
754     return TRUE;
755 }
756 
757 
758 /*******************************************************************************
759 **
760 ** Function         gki_adjust_timer_count
761 **
762 ** Description      This function is called whenever a new timer or GKI_wait occurs
763 **                  to adjust (if necessary) the current time til the first expiration.
764 **                  This only needs to make an adjustment if the new timer (in ticks) is
765 **                  less than the number of ticks remaining on the current timer.
766 **
767 ** Parameters:      ticks - (input) number of system ticks of the new timer entry
768 **
769 **                  NOTE:  This routine MUST be called while interrupts are disabled to
770 **                          avoid updates while adjusting the timer variables.
771 **
772 ** Returns          void
773 **
774 *******************************************************************************/
gki_adjust_timer_count(INT32 ticks)775 void gki_adjust_timer_count (INT32 ticks)
776 {
777     if (ticks > 0)
778     {
779         /* See if the new timer expires before the current first expiration */
780         if (gki_cb.com.OSNumOrigTicks == 0 || (ticks < gki_cb.com.OSTicksTilExp && gki_cb.com.OSTicksTilExp > 0))
781         {
782             gki_cb.com.OSNumOrigTicks = (gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) + ticks;
783             gki_cb.com.OSTicksTilExp = ticks;
784             alarm_service_reschedule();
785         }
786     }
787 
788     return;
789 }
790