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.
32extern 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*******************************************************************************/
44void 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*******************************************************************************/
89BOOLEAN 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*******************************************************************************/
137UINT32  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*******************************************************************************/
160INT32    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*******************************************************************************/
185void 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*******************************************************************************/
274void 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*******************************************************************************/
329void 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*******************************************************************************/
496void GKI_init_timer_list(TIMER_LIST_Q *timer_q) {
497    timer_q->p_first    = NULL;
498    timer_q->p_last     = NULL;
499}
500
501bool 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
506TIMER_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. */
512INT32 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*******************************************************************************/
535UINT16 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*******************************************************************************/
592UINT32 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*******************************************************************************/
638void 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*******************************************************************************/
699BOOLEAN 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*******************************************************************************/
775void 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