/*******************************************************************************
**
** Function         GKI_get_time_stamp
**
** Description      This function formats the time into a user area
**
** Parameters:      tbuf -  (output) the address to the memory containing the
**                  formatted time
**
** Returns          the address of the user area containing the formatted time
**                  The format of the time is ????
**
** NOTE             This function is only called by OBEX.
**
*******************************************************************************/
INT8 *GKI_get_time_stamp (INT8 *tbuf)
{
    UINT32 ms_time;
    UINT32 s_time;
    UINT32 m_time;
    UINT32 h_time;
    INT8   *p_out = tbuf;

    gki_cb.com.OSTicks = times(0);
    ms_time = GKI_TICKS_TO_MS(gki_cb.com.OSTicks);
    s_time  = ms_time/100;   /* 100 Ticks per second */
    m_time  = s_time/60;
    h_time  = m_time/60;

    ms_time -= s_time*100;
    s_time  -= m_time*60;
    m_time  -= h_time*60;

    *p_out++ = (INT8)((h_time / 10) + '0');
    *p_out++ = (INT8)((h_time % 10) + '0');
    *p_out++ = ':';
    *p_out++ = (INT8)((m_time / 10) + '0');
    *p_out++ = (INT8)((m_time % 10) + '0');
    *p_out++ = ':';
    *p_out++ = (INT8)((s_time / 10) + '0');
    *p_out++ = (INT8)((s_time % 10) + '0');
    *p_out++ = ':';
    *p_out++ = (INT8)((ms_time / 10) + '0');
    *p_out++ = (INT8)((ms_time % 10) + '0');
    *p_out++ = ':';
    *p_out   = 0;

    return (tbuf);
}
Beispiel #2
0
/*******************************************************************************
**
** Function         nfa_sys_ptim_timer_update
**
** Description      Update the protocol timer list and handle expired timers.
**                  This function is called from the task running the protocol
**                  timers when the periodic GKI timer expires.
**
** Returns          void
**
*******************************************************************************/
void nfa_sys_ptim_timer_update (tPTIM_CB *p_cb)
{
    TIMER_LIST_ENT *p_tle;
    BT_HDR *p_msg;
    UINT32 new_ticks_count;
    INT32  period_in_ticks;

    /* To handle the case when the function is called less frequently than the period
       we must convert determine the number of ticks since the last update, then
       convert back to milliseconds before updating timer list */
    new_ticks_count = GKI_get_tick_count ();

    /* Check for wrapped condition */
    if (new_ticks_count >= p_cb->last_gki_ticks)
    {
        period_in_ticks = (INT32) (new_ticks_count - p_cb->last_gki_ticks);
    }
    else
    {
        period_in_ticks = (INT32) (((UINT32) 0xffffffff - p_cb->last_gki_ticks)
                            + new_ticks_count + 1);
    }

    /* update timer list */
    GKI_update_timer_list (&p_cb->timer_queue, GKI_TICKS_TO_MS (period_in_ticks));

    p_cb->last_gki_ticks = new_ticks_count;

    /* while there are expired timers */
    while ((p_cb->timer_queue.p_first) && (p_cb->timer_queue.p_first->ticks <= 0))
    {
        /* removed expired timer from list */
        p_tle = p_cb->timer_queue.p_first;
        NFA_TRACE_DEBUG1 ("nfa_sys_ptim_timer_update expired: %08x", p_tle);
        GKI_remove_from_timer_list (&p_cb->timer_queue, p_tle);

        /* call timer callback */
        if (p_tle->p_cback)
        {
            (*p_tle->p_cback) (p_tle);
        }
        else if (p_tle->event)
        {
            if ((p_msg = (BT_HDR *) GKI_getbuf (sizeof (BT_HDR))) != NULL)
            {
                p_msg->event = p_tle->event;
                p_msg->layer_specific = 0;
                nfa_sys_sendmsg (p_msg);
            }
        }
    }

    /* if timer list is empty stop periodic GKI timer */
    if (p_cb->timer_queue.p_first == NULL)
    {
        NFA_TRACE_DEBUG0 ("ptim timer stop");
        GKI_stop_timer (p_cb->timer_id);
    }
}
Beispiel #3
0
/*******************************************************************************
**
** Function         rw_main_log_stats
**
** Description      Dump stats
**
** Returns          void
**
*******************************************************************************/
void rw_main_log_stats (void)
{
    UINT32 ticks, elapsed_ms;

    ticks = GKI_get_tick_count () - rw_cb.stats.start_tick;
    elapsed_ms = GKI_TICKS_TO_MS (ticks);

    RW_TRACE_DEBUG5 ("NFC tx stats: cmds:%i, retries:%i, aborted: %i, tx_errs: %i, bytes sent:%i", rw_cb.stats.num_ops, rw_cb.stats.num_retries, rw_cb.stats.num_fail, rw_cb.stats.num_trans_err, rw_cb.stats.bytes_sent);
    RW_TRACE_DEBUG2 ("    rx stats: rx-crc errors %i, bytes received: %i", rw_cb.stats.num_crc, rw_cb.stats.bytes_received);
    RW_TRACE_DEBUG1 ("    time activated %i ms", elapsed_ms);
}
void* timer_thread(void *arg)
{
    int timeout_ns=0;
    struct timespec timeout;
    struct timespec previous = {0,0};
    struct timespec current;
    int err;
    int delta_ns;
    int restart;
    tGKI_OS         *p_os = &gki_cb.os;
    int  *p_run_cond = &p_os->no_timer_suspend;

    /* Indicate that tick is just starting */
    restart = 1;

    prctl(PR_SET_NAME, (unsigned long)"gki timer", 0, 0, 0);

    raise_priority_a2dp(TASK_HIGH_GKI_TIMER);

    while(!shutdown_timer)
    {
        /* If the timer has been stopped (no SW timer running) */
        if (*p_run_cond == GKI_TIMER_TICK_STOP_COND)
        {
            /*
             * We will lock/wait on GKI_timer_mutex.
             * This mutex will be unlocked when timer is re-started
             */
            GKI_TRACE("GKI_run lock mutex");
            pthread_mutex_lock(&p_os->gki_timer_mutex);

            /* We are here because the mutex has been released by timer cback */
            /* Let's release it for future use */
            GKI_TRACE("GKI_run unlock mutex");
            pthread_mutex_unlock(&p_os->gki_timer_mutex);

            /* Indicate that tick is just starting */
            restart = 1;
        }

        /* Get time */
        clock_gettime(CLOCK_MONOTONIC, &current);

        /* Check if tick was just restarted, indicating to the compiler that this is
         * unlikely to happen (to help branch prediction) */
        if (__unlikely(restart))
        {
            /* Clear the restart indication */
            restart = 0;

            timeout_ns = (GKI_TICKS_TO_MS(1) * 1000000);
        }
        else
        {
            /* Compute time elapsed since last sleep start */
            delta_ns = current.tv_nsec - previous.tv_nsec;
            delta_ns += (current.tv_sec - previous.tv_sec) * 1000000000;

            /* Compute next timeout:
             *    timeout = (next theoretical expiration) - current time
             *    timeout = (previous time + timeout + delay) - current time
             *    timeout = timeout + delay - (current time - previous time)
             *    timeout += delay - delta */
            timeout_ns += (GKI_TICKS_TO_MS(1) * 1000000) - delta_ns;
        }
        /* Save the current time for next iteration */
        previous = current;

        timeout.tv_sec = 0;

        /* Sleep until next theoretical tick time.  In case of excessive
           elapsed time since last theoretical tick expiration, it is
           possible that the timeout value is negative.  To protect
           against this error, we set minimum sleep time to 10% of the
           tick period.  We indicate to compiler that this is unlikely to
           happen (to help branch prediction) */

        if (__unlikely(timeout_ns < ((GKI_TICKS_TO_MS(1) * 1000000) * 0.1)))
        {
            timeout.tv_nsec = (GKI_TICKS_TO_MS(1) * 1000000) * 0.1;

            /* Print error message if tick really got delayed
               (more than 5 ticks) */
            if (timeout_ns < GKI_TICKS_TO_MS(-5) * 1000000)
            {
                GKI_ERROR_LOG("tick delayed > 5 slots (%d,%d) -- cpu overload ? ",
                        timeout_ns, GKI_TICKS_TO_MS(-5) * 1000000);
            }
        }
        else
        {
            timeout.tv_nsec = timeout_ns;
        }

        do
        {
            /* [u]sleep can't be used because it uses SIGALRM */
            err = nanosleep(&timeout, &timeout);
        } while (err < 0 && errno == EINTR);

        /* Increment the GKI time value by one tick and update internal timers */
        GKI_timer_update(1);
    }
    GKI_TRACE("gki_ulinux: Exiting timer_thread");
    pthread_exit(NULL);
    return NULL;
}
/** Requests an alarm from AlarmService to fire when the next
  * timer in the timer queue is set to expire. Only takes a wakelock
  * if the timer tick expiration is a short interval in the future
  * and releases the wakelock if the timer is a longer interval
  * or if there are no more timers in the queue.
  *
  * NOTE: Must be called with GKI_disable() lock held.
  */
void alarm_service_reschedule()
{
    int32_t ticks_till_next_exp = GKI_ready_to_sleep();

    assert(ticks_till_next_exp >= 0);
    alarm_service.ticks_scheduled = ticks_till_next_exp;

    // No more timers remaining. Release wakelock if we're holding one.
    if (ticks_till_next_exp == 0)
    {
        alarm_service.timer_last_expired_us = 0;
        alarm_service.timer_started_us = 0;
        if (alarm_service.wakelock)
        {
            ALOGV("%s releasing wake lock.", __func__);
            alarm_service.wakelock = false;
            int rc = bt_os_callouts->release_wake_lock(WAKE_LOCK_ID);
            if (rc != BT_STATUS_SUCCESS)
            {
                ALOGE("%s unable to release wake lock with no timers: %d", __func__, rc);
            }
        }
        ALOGV("%s no more alarms.", __func__);
        return;
    }

    UINT64 ticks_in_millis = GKI_TICKS_TO_MS(ticks_till_next_exp);
    if (ticks_in_millis <= GKI_TIMER_INTERVAL_FOR_WAKELOCK)
    {
        // The next deadline is close, just take a wakelock and set a regular (non-wake) timer.
        if (!alarm_service.wakelock)
        {
            int rc = bt_os_callouts->acquire_wake_lock(WAKE_LOCK_ID);
            if (rc != BT_STATUS_SUCCESS)
            {
                ALOGE("%s unable to acquire wake lock: %d", __func__, rc);
                return;
            }
            alarm_service.wakelock = true;
        }
        ALOGV("%s acquired wake lock, setting short alarm (%lldms).", __func__, ticks_in_millis);

        if (!set_nonwake_alarm(ticks_in_millis))
        {
            ALOGE("%s unable to set short alarm.", __func__);
        }
    } else {
        // The deadline is far away, set a wake alarm and release wakelock if we're holding it.
        alarm_service.timer_started_us = GKI_now_us();
        alarm_service.timer_last_expired_us = 0;
        if (!bt_os_callouts->set_wake_alarm(ticks_in_millis, true, bt_alarm_cb, &alarm_service))
        {
            ALOGE("%s unable to set long alarm, releasing wake lock anyway.", __func__);
        } else {
            ALOGV("%s set long alarm (%lldms), releasing wake lock.", __func__, ticks_in_millis);
        }

        if (alarm_service.wakelock)
        {
            alarm_service.wakelock = false;
            bt_os_callouts->release_wake_lock(WAKE_LOCK_ID);
        }
    }
}