diff options
Diffstat (limited to 'gki/common/gki_time.c')
-rw-r--r-- | gki/common/gki_time.c | 1016 |
1 files changed, 1016 insertions, 0 deletions
diff --git a/gki/common/gki_time.c b/gki/common/gki_time.c new file mode 100644 index 0000000..8121654 --- /dev/null +++ b/gki/common/gki_time.c @@ -0,0 +1,1016 @@ + +/**************************************************************************** +** +** Name GKI_time.c +** +** Function this file contains GKI time related functions +** +** Copyright (c) 1999-2011, Broadcom Corp., All Rights Reserved. +** Proprietary and confidential. +** +*****************************************************************************/ + +#include "gki_int.h" + +#ifndef BT_ERROR_TRACE_0 +#define BT_ERROR_TRACE_0(l,m) +#endif + +/* Make sure that this has been defined in target.h */ +#ifndef GKI_NUM_TIMERS +#error NO TIMERS: Must define at least 1 timer in the system! +#endif + + +#define GKI_NO_NEW_TMRS_STARTED (0x7fffffffL) /* Largest signed positive timer count */ +#define GKI_UNUSED_LIST_ENTRY (0x80000000L) /* Marks an unused timer list entry (initial value) */ +#define GKI_MAX_INT32 (0x7fffffffL) + +/******************************************************************************* +** +** Function gki_timers_init +** +** Description This internal function is called once at startup to initialize +** all the timer structures. +** +** Returns void +** +*******************************************************************************/ +void gki_timers_init(void) +{ + UINT8 tt; + + gki_cb.com.OSTicksTilExp = 0; /* Remaining time (of OSTimeCurTimeout) before next timer expires */ + gki_cb.com.OSNumOrigTicks = 0; +#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) + gki_cb.com.OSTicksTilStop = 0; /* clear inactivity delay timer */ +#endif + + for (tt = 0; tt < GKI_MAX_TASKS; tt++) + { + gki_cb.com.OSWaitTmr [tt] = 0; + +#if (GKI_NUM_TIMERS > 0) + gki_cb.com.OSTaskTmr0 [tt] = 0; + gki_cb.com.OSTaskTmr0R [tt] = 0; +#endif + +#if (GKI_NUM_TIMERS > 1) + gki_cb.com.OSTaskTmr1 [tt] = 0; + gki_cb.com.OSTaskTmr1R [tt] = 0; +#endif + +#if (GKI_NUM_TIMERS > 2) + gki_cb.com.OSTaskTmr2 [tt] = 0; + gki_cb.com.OSTaskTmr2R [tt] = 0; +#endif + +#if (GKI_NUM_TIMERS > 3) + gki_cb.com.OSTaskTmr3 [tt] = 0; + gki_cb.com.OSTaskTmr3R [tt] = 0; +#endif + } + + for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) + { + gki_cb.com.timer_queues[tt] = NULL; + } + + gki_cb.com.p_tick_cb = NULL; + gki_cb.com.system_tick_running = FALSE; + + return; +} + +/******************************************************************************* +** +** Function gki_timers_is_timer_running +** +** Description This internal function is called to test if any gki timer are running +** +** +** Returns TRUE if at least one time is running in the system, FALSE else. +** +*******************************************************************************/ +BOOLEAN gki_timers_is_timer_running(void) +{ + UINT8 tt; + for (tt = 0; tt < GKI_MAX_TASKS; tt++) + { + +#if (GKI_NUM_TIMERS > 0) + if(gki_cb.com.OSTaskTmr0 [tt]) + { + return TRUE; + } +#endif + +#if (GKI_NUM_TIMERS > 1) + if(gki_cb.com.OSTaskTmr1 [tt] ) + { + return TRUE; + } +#endif + +#if (GKI_NUM_TIMERS > 2) + if(gki_cb.com.OSTaskTmr2 [tt] ) + { + return TRUE; + } +#endif + +#if (GKI_NUM_TIMERS > 3) + if(gki_cb.com.OSTaskTmr3 [tt] ) + { + return TRUE; + } +#endif + } + + return FALSE; + +} + +/******************************************************************************* +** +** Function GKI_get_tick_count +** +** Description This function returns the current system ticks +** +** Returns The current number of system ticks +** +*******************************************************************************/ +UINT32 GKI_get_tick_count(void) +{ + return gki_cb.com.OSTicks; +} + + +/******************************************************************************* +** +** Function GKI_ready_to_sleep +** +** Description This function returns the number of system ticks until the +** next timer will expire. It is typically called by a power +** savings manager to find out how long it can have the system +** sleep before it needs to service the next entry. +** +** Parameters: None +** +** Returns Number of ticks til the next timer expires +** Note: the value is a signed value. This value should be +** compared to x > 0, to avoid misinterpreting negative tick +** values. +** +*******************************************************************************/ +INT32 GKI_ready_to_sleep (void) +{ + return (gki_cb.com.OSTicksTilExp); +} + + +/******************************************************************************* +** +** Function GKI_start_timer +** +** Description An application can call this function to start one of +** it's four general purpose timers. Any of the four timers +** can be 1-shot or continuous. If a timer is already running, +** it will be reset to the new parameters. +** +** Parameters tnum - (input) timer number to be started (TIMER_0, +** TIMER_1, TIMER_2, or TIMER_3) +** ticks - (input) the number of system ticks til the +** timer expires. +** is_continuous - (input) TRUE if timer restarts automatically, +** else FALSE if it is a 'one-shot'. +** +** Returns void +** +*******************************************************************************/ +void GKI_start_timer (UINT8 tnum, INT32 ticks, BOOLEAN is_continuous) +{ + INT32 reload; + INT32 orig_ticks; + UINT8 task_id = GKI_get_taskid(); + BOOLEAN bad_timer = FALSE; + + if (ticks <= 0) + ticks = 1; + + orig_ticks = ticks; /* save the ticks in case adjustment is necessary */ + + + /* If continuous timer, set reload, else set it to 0 */ + if (is_continuous) + reload = ticks; + else + reload = 0; + + GKI_disable(); + + if(gki_timers_is_timer_running() == FALSE) + { +#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) + /* if inactivity delay timer is not running, start system tick */ + if(gki_cb.com.OSTicksTilStop == 0) + { +#endif + if(gki_cb.com.p_tick_cb) + { + /* start system tick */ + gki_cb.com.system_tick_running = TRUE; + (gki_cb.com.p_tick_cb) (TRUE); + } +#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) + } + else + { + /* clear inactivity delay timer */ + gki_cb.com.OSTicksTilStop = 0; + } +#endif + } + /* Add the time since the last task timer update. + ** Note that this works when no timers are active since + ** both OSNumOrigTicks and OSTicksTilExp are 0. + */ + if (GKI_MAX_INT32 - (gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) > ticks) + { + ticks += gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp; + } + else + ticks = GKI_MAX_INT32; + + switch (tnum) + { +#if (GKI_NUM_TIMERS > 0) + case TIMER_0: + gki_cb.com.OSTaskTmr0R[task_id] = reload; + gki_cb.com.OSTaskTmr0 [task_id] = ticks; + break; +#endif + +#if (GKI_NUM_TIMERS > 1) + case TIMER_1: + gki_cb.com.OSTaskTmr1R[task_id] = reload; + gki_cb.com.OSTaskTmr1 [task_id] = ticks; + break; +#endif + +#if (GKI_NUM_TIMERS > 2) + case TIMER_2: + gki_cb.com.OSTaskTmr2R[task_id] = reload; + gki_cb.com.OSTaskTmr2 [task_id] = ticks; + break; +#endif + +#if (GKI_NUM_TIMERS > 3) + case TIMER_3: + gki_cb.com.OSTaskTmr3R[task_id] = reload; + gki_cb.com.OSTaskTmr3 [task_id] = ticks; + break; +#endif + default: + bad_timer = TRUE; /* Timer number is bad, so do not use */ + } + + /* Update the expiration timeout if a legitimate timer */ + if (!bad_timer) + { + /* Only update the timeout value if it is less than any other newly started timers */ + gki_adjust_timer_count (orig_ticks); + } + + GKI_enable(); + +} + +/******************************************************************************* +** +** Function GKI_stop_timer +** +** Description An application can call this function to stop one of +** it's four general purpose timers. There is no harm in +** stopping a timer that is already stopped. +** +** Parameters tnum - (input) timer number to be started (TIMER_0, +** TIMER_1, TIMER_2, or TIMER_3) +** Returns void +** +*******************************************************************************/ +void GKI_stop_timer (UINT8 tnum) +{ + UINT8 task_id = GKI_get_taskid(); + + switch (tnum) + { +#if (GKI_NUM_TIMERS > 0) + case TIMER_0: + gki_cb.com.OSTaskTmr0R[task_id] = 0; + gki_cb.com.OSTaskTmr0 [task_id] = 0; + break; +#endif + +#if (GKI_NUM_TIMERS > 1) + case TIMER_1: + gki_cb.com.OSTaskTmr1R[task_id] = 0; + gki_cb.com.OSTaskTmr1 [task_id] = 0; + break; +#endif + +#if (GKI_NUM_TIMERS > 2) + case TIMER_2: + gki_cb.com.OSTaskTmr2R[task_id] = 0; + gki_cb.com.OSTaskTmr2 [task_id] = 0; + break; +#endif + +#if (GKI_NUM_TIMERS > 3) + case TIMER_3: + gki_cb.com.OSTaskTmr3R[task_id] = 0; + gki_cb.com.OSTaskTmr3 [task_id] = 0; + break; +#endif + } + + GKI_disable(); + + if (gki_timers_is_timer_running() == FALSE) + { + if (gki_cb.com.p_tick_cb) + { +#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) + /* if inactivity delay timer is not running */ + if ((gki_cb.com.system_tick_running)&&(gki_cb.com.OSTicksTilStop == 0)) + { + /* set inactivity delay timer */ + /* when timer expires, system tick will be stopped */ + gki_cb.com.OSTicksTilStop = GKI_DELAY_STOP_SYS_TICK; + } +#else + gki_cb.com.system_tick_running = FALSE; + gki_cb.com.p_tick_cb(FALSE); /* stop system tick */ +#endif + } + } + + GKI_enable(); + + +} + + +/******************************************************************************* +** +** Function GKI_timer_update +** +** Description This function is called by an OS to drive the GKI's timers. +** It is typically called at every system tick to +** update the timers for all tasks, and check for timeouts. +** +** Note: It has been designed to also allow for variable tick updates +** so that systems with strict power savings requirements can +** have the update occur at variable intervals. +** +** Parameters: ticks_since_last_update - (input) This is the number of TICKS that have +** occurred since the last time GKI_timer_update was called. +** +** Returns void +** +*******************************************************************************/ +void GKI_timer_update (INT32 ticks_since_last_update) +{ + UINT8 task_id; + long next_expiration; /* Holds the next soonest expiration time after this update */ + + /* Increment the number of ticks used for time stamps */ + gki_cb.com.OSTicks += ticks_since_last_update; + + /* If any timers are running in any tasks, decrement the remaining time til + * the timer updates need to take place (next expiration occurs) + */ + gki_cb.com.OSTicksTilExp -= ticks_since_last_update; + + /* Don't allow timer interrupt nesting */ + if (gki_cb.com.timer_nesting) + return; + + gki_cb.com.timer_nesting = 1; + +#if (defined(GKI_DELAY_STOP_SYS_TICK) && (GKI_DELAY_STOP_SYS_TICK > 0)) + /* if inactivity delay timer is set and expired */ + if (gki_cb.com.OSTicksTilStop) + { + if( gki_cb.com.OSTicksTilStop <= (UINT32)ticks_since_last_update ) + { + if(gki_cb.com.p_tick_cb) + { + gki_cb.com.system_tick_running = FALSE; + (gki_cb.com.p_tick_cb) (FALSE); /* stop system tick */ + } + gki_cb.com.OSTicksTilStop = 0; /* clear inactivity delay timer */ + gki_cb.com.timer_nesting = 0; + return; + } + else + gki_cb.com.OSTicksTilStop -= ticks_since_last_update; + } +#endif + + /* No need to update the ticks if no timeout has occurred */ + if (gki_cb.com.OSTicksTilExp > 0) + { + gki_cb.com.timer_nesting = 0; + return; + } + + next_expiration = GKI_NO_NEW_TMRS_STARTED; + + /* If here then gki_cb.com.OSTicksTilExp <= 0. If negative, then increase gki_cb.com.OSNumOrigTicks + to account for the difference so timer updates below are decremented by the full number + of ticks. gki_cb.com.OSNumOrigTicks is reset at the bottom of this function so changing this + value only affects the timer updates below + */ + gki_cb.com.OSNumOrigTicks -= gki_cb.com.OSTicksTilExp; + +#if GKI_TIMER_LIST_NOPREEMPT == TRUE + /* Protect this section because if a GKI_timer_stop happens between: + * - gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks; + * - gki_cb.com.OSTaskTmr0[task_id] = gki_cb.com.OSTaskTmr0R[task_id]; + * then the timer may appear stopped while it is about to be reloaded. + * Note: Not needed if this function cannot be preempted (typical). + */ + GKI_disable(); +#endif + + /* Check for OS Task Timers */ + for (task_id = 0; task_id < GKI_MAX_TASKS; task_id++) + { + if (gki_cb.com.OSWaitTmr[task_id] > 0) /* If timer is running */ + { + gki_cb.com.OSWaitTmr[task_id] -= gki_cb.com.OSNumOrigTicks; + if (gki_cb.com.OSWaitTmr[task_id] <= 0) + { + /* Timer Expired */ + gki_cb.com.OSRdyTbl[task_id] = TASK_READY; + } + } + +#if (GKI_NUM_TIMERS > 0) + /* If any timer is running, decrement */ + if (gki_cb.com.OSTaskTmr0[task_id] > 0) + { + gki_cb.com.OSTaskTmr0[task_id] -= gki_cb.com.OSNumOrigTicks; + + if (gki_cb.com.OSTaskTmr0[task_id] <= 0) + { + /* Reload timer and set Timer 0 Expired event mask */ + gki_cb.com.OSTaskTmr0[task_id] = gki_cb.com.OSTaskTmr0R[task_id]; + +#if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE) + GKI_isend_event (task_id, TIMER_0_EVT_MASK); +#else + GKI_send_event (task_id, TIMER_0_EVT_MASK); +#endif + } + } + + /* Check to see if this timer is the next one to expire */ + if (gki_cb.com.OSTaskTmr0[task_id] > 0 && gki_cb.com.OSTaskTmr0[task_id] < next_expiration) + next_expiration = gki_cb.com.OSTaskTmr0[task_id]; +#endif + +#if (GKI_NUM_TIMERS > 1) + /* If any timer is running, decrement */ + if (gki_cb.com.OSTaskTmr1[task_id] > 0) + { + gki_cb.com.OSTaskTmr1[task_id] -= gki_cb.com.OSNumOrigTicks; + + if (gki_cb.com.OSTaskTmr1[task_id] <= 0) + { + /* Reload timer and set Timer 1 Expired event mask */ + gki_cb.com.OSTaskTmr1[task_id] = gki_cb.com.OSTaskTmr1R[task_id]; + +#if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE) + GKI_isend_event (task_id, TIMER_1_EVT_MASK); +#else + GKI_send_event (task_id, TIMER_1_EVT_MASK); +#endif + } + } + + /* Check to see if this timer is the next one to expire */ + if (gki_cb.com.OSTaskTmr1[task_id] > 0 && gki_cb.com.OSTaskTmr1[task_id] < next_expiration) + next_expiration = gki_cb.com.OSTaskTmr1[task_id]; +#endif + +#if (GKI_NUM_TIMERS > 2) + /* If any timer is running, decrement */ + if (gki_cb.com.OSTaskTmr2[task_id] > 0) + { + gki_cb.com.OSTaskTmr2[task_id] -= gki_cb.com.OSNumOrigTicks; + + if (gki_cb.com.OSTaskTmr2[task_id] <= 0) + { + /* Reload timer and set Timer 2 Expired event mask */ + gki_cb.com.OSTaskTmr2[task_id] = gki_cb.com.OSTaskTmr2R[task_id]; + +#if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE) + GKI_isend_event (task_id, TIMER_2_EVT_MASK); +#else + GKI_send_event (task_id, TIMER_2_EVT_MASK); +#endif + } + } + + /* Check to see if this timer is the next one to expire */ + if (gki_cb.com.OSTaskTmr2[task_id] > 0 && gki_cb.com.OSTaskTmr2[task_id] < next_expiration) + next_expiration = gki_cb.com.OSTaskTmr2[task_id]; +#endif + +#if (GKI_NUM_TIMERS > 3) + /* If any timer is running, decrement */ + if (gki_cb.com.OSTaskTmr3[task_id] > 0) + { + gki_cb.com.OSTaskTmr3[task_id] -= gki_cb.com.OSNumOrigTicks; + + if (gki_cb.com.OSTaskTmr3[task_id] <= 0) + { + /* Reload timer and set Timer 3 Expired event mask */ + gki_cb.com.OSTaskTmr3[task_id] = gki_cb.com.OSTaskTmr3R[task_id]; + +#if (defined(GKI_TIMER_UPDATES_FROM_ISR) && GKI_TIMER_UPDATES_FROM_ISR == TRUE) + GKI_isend_event (task_id, TIMER_3_EVT_MASK); +#else + GKI_send_event (task_id, TIMER_3_EVT_MASK); +#endif + } + } + + /* Check to see if this timer is the next one to expire */ + if (gki_cb.com.OSTaskTmr3[task_id] > 0 && gki_cb.com.OSTaskTmr3[task_id] < next_expiration) + next_expiration = gki_cb.com.OSTaskTmr3[task_id]; +#endif + + } + +#if GKI_TIMER_LIST_NOPREEMPT == TRUE + /* End the critical section */ + GKI_enable(); +#endif + + /* Set the next timer experation value if there is one to start */ + if (next_expiration < GKI_NO_NEW_TMRS_STARTED) + { + gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = next_expiration; + } + else + { + gki_cb.com.OSTicksTilExp = gki_cb.com.OSNumOrigTicks = 0; + } + + gki_cb.com.timer_nesting = 0; + + return; +} + + +/******************************************************************************* +** +** Function GKI_timer_queue_empty +** +** Description This function is called by applications to see whether the timer +** queue is empty +** +** Parameters +** +** Returns BOOLEAN +** +*******************************************************************************/ +BOOLEAN GKI_timer_queue_empty (void) +{ + UINT8 tt; + + for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) + { + if (gki_cb.com.timer_queues[tt]) + return FALSE; + } + + return TRUE; +} + +/******************************************************************************* +** +** Function GKI_timer_queue_register_callback +** +** Description This function is called by applications to register system tick +** start/stop callback for time queues +** +** +** Parameters p_callback - (input) pointer to the system tick callback +** +** Returns BOOLEAN +** +*******************************************************************************/ +void GKI_timer_queue_register_callback (SYSTEM_TICK_CBACK *p_callback) +{ + gki_cb.com.p_tick_cb = p_callback; + + return; +} + +/******************************************************************************* +** +** Function GKI_init_timer_list +** +** Description This function is called by applications when they +** want to initialize a timer list. +** +** Parameters p_timer_listq - (input) pointer to the timer list queue object +** +** Returns void +** +*******************************************************************************/ +void GKI_init_timer_list (TIMER_LIST_Q *p_timer_listq) +{ + p_timer_listq->p_first = NULL; + p_timer_listq->p_last = NULL; + p_timer_listq->last_ticks = 0; + + return; +} + +/******************************************************************************* +** +** Function GKI_init_timer_list_entry +** +** Description This function is called by the applications when they +** want to initialize a timer list entry. This must be +** done prior to first use of the entry. +** +** Parameters p_tle - (input) pointer to a timer list queue entry +** +** Returns void +** +*******************************************************************************/ +void GKI_init_timer_list_entry (TIMER_LIST_ENT *p_tle) +{ + p_tle->p_next = NULL; + p_tle->p_prev = NULL; + p_tle->ticks = GKI_UNUSED_LIST_ENTRY; + p_tle->in_use = FALSE; +} + + +/******************************************************************************* +** +** Function GKI_update_timer_list +** +** Description This function is called by the applications when they +** want to update a timer list. This should be at every +** timer list unit tick, e.g. once per sec, once per minute etc. +** +** Parameters p_timer_listq - (input) pointer to the timer list queue object +** num_units_since_last_update - (input) number of units since the last update +** (allows for variable unit update) +** +** NOTE: The following timer list update routines should not be used for exact time +** critical purposes. The timer tasks should be used when exact timing is needed. +** +** Returns the number of timers that have expired +** +*******************************************************************************/ +UINT16 GKI_update_timer_list (TIMER_LIST_Q *p_timer_listq, INT32 num_units_since_last_update) +{ + TIMER_LIST_ENT *p_tle; + UINT16 num_time_out = 0; + INT32 rem_ticks; + INT32 temp_ticks; + + p_tle = p_timer_listq->p_first; + + /* First, get the guys who have previously timed out */ + /* Note that the tick value of the timers should always be '0' */ + while ((p_tle) && (p_tle->ticks <= 0)) + { + num_time_out++; + p_tle = p_tle->p_next; + } + + /* Timer entriy tick values are relative to the preceeding entry */ + rem_ticks = num_units_since_last_update; + + /* Now, adjust remaining timer entries */ + while ((p_tle != NULL) && (rem_ticks > 0)) + { + temp_ticks = p_tle->ticks; + p_tle->ticks -= rem_ticks; + + /* See if this timer has just timed out */ + if (p_tle->ticks <= 0) + { + /* We set the number of ticks to '0' so that the legacy code + * that assumes a '0' or nonzero value will still work as coded. */ + p_tle->ticks = 0; + + num_time_out++; + } + + rem_ticks -= temp_ticks; /* Decrement the remaining ticks to process */ + p_tle = p_tle->p_next; + } + + if (p_timer_listq->last_ticks > 0) + { + p_timer_listq->last_ticks -= num_units_since_last_update; + + /* If the last timer has expired set last_ticks to 0 so that other list update + * functions will calculate correctly + */ + if (p_timer_listq->last_ticks < 0) + p_timer_listq->last_ticks = 0; + } + + return (num_time_out); +} + +/******************************************************************************* +** +** Function GKI_get_remaining_ticks +** +** Description This function is called by an application to get remaining +** ticks to expire +** +** Parameters p_timer_listq - (input) pointer to the timer list queue object +** p_target_tle - (input) pointer to a timer list queue entry +** +** Returns 0 if timer is not used or timer is not in the list +** remaining ticks if success +** +*******************************************************************************/ +UINT32 GKI_get_remaining_ticks (TIMER_LIST_Q *p_timer_listq, TIMER_LIST_ENT *p_target_tle) +{ + TIMER_LIST_ENT *p_tle; + UINT32 rem_ticks = 0; + + if (p_target_tle->in_use) + { + p_tle = p_timer_listq->p_first; + + /* adding up all of ticks in previous entries */ + while ((p_tle)&&(p_tle != p_target_tle)) + { + rem_ticks += p_tle->ticks; + p_tle = p_tle->p_next; + } + + /* if found target entry */ + if (p_tle == p_target_tle) + { + rem_ticks += p_tle->ticks; + } + else + { + BT_ERROR_TRACE_0(TRACE_LAYER_GKI, "GKI_get_remaining_ticks: No timer entry in the list"); + return(0); + } + } + else + { + BT_ERROR_TRACE_0(TRACE_LAYER_GKI, "GKI_get_remaining_ticks: timer entry is not active"); + } + + return (rem_ticks); +} + +/******************************************************************************* +** +** Function GKI_add_to_timer_list +** +** Description This function is called by an application to add a timer +** entry to a timer list. +** +** Note: A timer value of '0' will effectively insert an already +** expired event. Negative tick values will be ignored. +** +** Parameters p_timer_listq - (input) pointer to the timer list queue object +** p_tle - (input) pointer to a timer list queue entry +** +** Returns void +** +*******************************************************************************/ +void GKI_add_to_timer_list (TIMER_LIST_Q *p_timer_listq, TIMER_LIST_ENT *p_tle) +{ + UINT32 nr_ticks_total; + UINT8 tt; + TIMER_LIST_ENT *p_temp; + + /* Only process valid tick values */ + if (p_tle->ticks >= 0) + { + /* If this entry is the last in the list */ + if (p_tle->ticks >= p_timer_listq->last_ticks) + { + /* If this entry is the only entry in the list */ + if (p_timer_listq->p_first == NULL) + p_timer_listq->p_first = p_tle; + else + { + /* Insert the entry onto the end of the list */ + if (p_timer_listq->p_last != NULL) + p_timer_listq->p_last->p_next = p_tle; + + p_tle->p_prev = p_timer_listq->p_last; + } + + p_tle->p_next = NULL; + p_timer_listq->p_last = p_tle; + nr_ticks_total = p_tle->ticks; + p_tle->ticks -= p_timer_listq->last_ticks; + + p_timer_listq->last_ticks = nr_ticks_total; + } + else /* This entry needs to be inserted before the last entry */ + { + /* Find the entry that the new one needs to be inserted in front of */ + p_temp = p_timer_listq->p_first; + while (p_tle->ticks > p_temp->ticks) + { + /* Update the tick value if looking at an unexpired entry */ + if (p_temp->ticks > 0) + p_tle->ticks -= p_temp->ticks; + + p_temp = p_temp->p_next; + } + + /* The new entry is the first in the list */ + if (p_temp == p_timer_listq->p_first) + { + p_tle->p_next = p_timer_listq->p_first; + p_timer_listq->p_first->p_prev = p_tle; + p_timer_listq->p_first = p_tle; + } + else + { + p_temp->p_prev->p_next = p_tle; + p_tle->p_prev = p_temp->p_prev; + p_temp->p_prev = p_tle; + p_tle->p_next = p_temp; + } + p_temp->ticks -= p_tle->ticks; + } + + p_tle->in_use = TRUE; + + /* if we already add this timer queue to the array */ + for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) + { + if (gki_cb.com.timer_queues[tt] == p_timer_listq) + return; + } + /* add this timer queue to the array */ + for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) + { + if (gki_cb.com.timer_queues[tt] == NULL) + break; + } + if (tt < GKI_MAX_TIMER_QUEUES) + { + gki_cb.com.timer_queues[tt] = p_timer_listq; + } + } + + return; +} + + +/******************************************************************************* +** +** Function GKI_remove_from_timer_list +** +** Description This function is called by an application to remove a timer +** entry from a timer list. +** +** Parameters p_timer_listq - (input) pointer to the timer list queue object +** p_tle - (input) pointer to a timer list queue entry +** +** Returns void +** +*******************************************************************************/ +void GKI_remove_from_timer_list (TIMER_LIST_Q *p_timer_listq, TIMER_LIST_ENT *p_tle) +{ + UINT8 tt; + + /* Verify that the entry is valid */ + if (p_tle == NULL || p_tle->in_use == FALSE || p_timer_listq->p_first == NULL) + { + return; + } + + /* Add the ticks remaining in this timer (if any) to the next guy in the list. + ** Note: Expired timers have a tick value of '0'. + */ + if (p_tle->p_next != NULL) + { + p_tle->p_next->ticks += p_tle->ticks; + } + else + { + p_timer_listq->last_ticks -= p_tle->ticks; + } + + /* Unlink timer from the list. + */ + if (p_timer_listq->p_first == p_tle) + { + p_timer_listq->p_first = p_tle->p_next; + + if (p_timer_listq->p_first != NULL) + p_timer_listq->p_first->p_prev = NULL; + + if (p_timer_listq->p_last == p_tle) + p_timer_listq->p_last = NULL; + } + else + { + if (p_timer_listq->p_last == p_tle) + { + p_timer_listq->p_last = p_tle->p_prev; + + if (p_timer_listq->p_last != NULL) + p_timer_listq->p_last->p_next = NULL; + } + else + { + if (p_tle->p_next != NULL && p_tle->p_next->p_prev == p_tle) + p_tle->p_next->p_prev = p_tle->p_prev; + else + { + /* Error case - chain messed up ?? */ + return; + } + + if (p_tle->p_prev != NULL && p_tle->p_prev->p_next == p_tle) + p_tle->p_prev->p_next = p_tle->p_next; + else + { + /* Error case - chain messed up ?? */ + return; + } + } + } + + p_tle->p_next = p_tle->p_prev = NULL; + p_tle->ticks = GKI_UNUSED_LIST_ENTRY; + p_tle->in_use = FALSE; + + /* if timer queue is empty */ + if (p_timer_listq->p_first == NULL && p_timer_listq->p_last == NULL) + { + for (tt = 0; tt < GKI_MAX_TIMER_QUEUES; tt++) + { + if (gki_cb.com.timer_queues[tt] == p_timer_listq) + { + gki_cb.com.timer_queues[tt] = NULL; + break; + } + } + } + + return; +} + + +/******************************************************************************* +** +** Function gki_adjust_timer_count +** +** Description This function is called whenever a new timer or GKI_wait occurs +** to adjust (if necessary) the current time til the first expiration. +** This only needs to make an adjustment if the new timer (in ticks) is +** less than the number of ticks remaining on the current timer. +** +** Parameters: ticks - (input) number of system ticks of the new timer entry +** +** NOTE: This routine MUST be called while interrupts are disabled to +** avoid updates while adjusting the timer variables. +** +** Returns void +** +*******************************************************************************/ +void gki_adjust_timer_count (INT32 ticks) +{ + if (ticks > 0) + { + /* See if the new timer expires before the current first expiration */ + if (gki_cb.com.OSNumOrigTicks == 0 || (ticks < gki_cb.com.OSTicksTilExp && gki_cb.com.OSTicksTilExp > 0)) + { + gki_cb.com.OSNumOrigTicks = (gki_cb.com.OSNumOrigTicks - gki_cb.com.OSTicksTilExp) + ticks; + gki_cb.com.OSTicksTilExp = ticks; + } + } + + return; +} |