alarm_new("btif_rc.rc_play_status_timer");
alarm_new_internal(name, false);
if (!alarms) //static list_t *alarms;
lazy_initialize()
alarms = list_new(NULL);
if (!timer_create_internal(CLOCK_ID, &timer))
if (!timer_create_internal(CLOCK_ID_ALARM, &wakeup_timer))
struct sigevent sigevent;
//使用线程方式,当timer到期之后,调用sigev_notify_function()
sigevent.sigev_notify = SIGEV_THREAD;
sigevent.sigev_notify_function = (void (*)(union sigval))timer_callback;
// timer到期后,Callback function for wake alarms and our posix timer
static void timer_callback(UNUSED_ATTR void *ptr) {
semaphore_post(alarm_expired);
}
if (timer_create(clock_id, &sigevent, timer) == -1)
//创建一个eventfd(value, EFD_SEMAPHORE);
alarm_expired = semaphore_new(0);
=====
//创建一个默认的alarm线程
default_callback_thread = thread_new_sized("alarm_default_callbacks", SIZE_MAX);
//创建一个队列
default_callback_queue = fixed_queue_new(SIZE_MAX);
//将队列加入到线程里面去
alarm_register_processing_queue(default_callback_queue, default_callback_thread);
//把队列里面的dequeue_sem加入到线程的epoll监控里面去,当有消息时alarm_queue_ready函数会被调用
fixed_queue_register_dequeue(
queue,
thread_get_reactor(thread),
alarm_queue_ready,
NULL);
======
//在之前的线程文章中说过,可以通过fixed_queue_register_dequeue添加新的队列和处理函数,比如:
//通用的alarm队列
btu_general_alarm_queue = fixed_queue_new(SIZE_MAX);
//做了一个封装,公用alarm_queue_ready处理函数
alarm_register_processing_queue(btu_general_alarm_queue, bt_workqueue_thread);
fixed_queue_register_dequeue(queue, thread_get_reactor(thread),
alarm_queue_ready, NULL);
//从上面的函数可以看出,在bluedroid中会添加多个队列,但公用alarm_queue_ready一个处理函数
alarm_queue_ready
//从队列里面取出一个alarm
alarm_t *alarm = (alarm_t *)fixed_queue_try_dequeue(queue);
//执行即可
alarm_callback_t callback = alarm->callback;
callback(data);
//继续分析lazy_initialize
//创建一个线程
dispatcher_thread = thread_new("alarm_dispatcher");
//使用默认队列,传递处理函数
thread_post(dispatcher_thread, callback_dispatch, NULL);
//这个函数的目的是:当timer到期,把对应的消息放入到队列里面去处理
callback_dispatch
while (true) {//无限循环
//等待alarm_expired ;timer到期后
semaphore_wait(alarm_expired);
//定时器到达之前可能被取消
//定时器还未到达到期
//退出,重新调度
if (list_is_empty(alarms) ||
(alarm = list_front(alarms))->deadline > now()) {
reschedule_root_alarm();
pthread_mutex_unlock(&monitor);
continue;
}
list_remove(alarms, alarm);
//执行完一个到期的定时器后,重新调动一个新的的timer
reschedule_root_alarm();
// Enqueue the alarm for processing
// 放入alarm队列里面去执行
fixed_queue_enqueue(alarm->queue, alarm);
}
//下面有两种启动timer的方式
//指定队列
alarm_set_on_queue(btif_rc_cb.rc_play_status_timer,
BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
btif_rc_play_status_timer_timeout, NULL,
btu_general_alarm_queue);
alarm_set_on_queue(alarm, interval_ms, cb, data, btu_general_alarm_queue);
//默认队列
alarm_set(btif_media_cb.media_alarm, BTIF_MEDIA_TIME_TICK,
btif_media_task_alarm_cb, NULL);
alarm_set_on_queue(alarm, interval_ms, cb, data, default_callback_queue);
alarm->creation_time = now();
alarm->period = period; // 定时时间
alarm->queue = queue; // default_callback_queue / btu_general_alarm_queue
alarm->callback = cb; // btif_media_task_alarm_cb / btif_rc_play_status_timer_timeout
alarm->data = data;
schedule_next_instance(alarm);
//如果已经添加了但还未执行,先删除掉,根据最新的重新排列
if (alarm->callback)
remove_pending_alarm(alarm)
// 根据到期时间的大小进行排序,然后插入正确的位置
// Calculate the next deadline for this alarm
// Add it into the timer list sorted by deadline (earliest deadline first).
static list_t *alarms;
list_prepend(alarms, alarm);
list_insert_after(alarms, node, alarm);
// If the new alarm has the earliest deadline, we need to re-evaluate our schedule.
if (needs_reschedule ||
(!list_is_empty(alarms) && list_front(alarms) == alarm)) {
reschedule_root_alarm(); //新的timer是最接近到期,马上调度
alarm->stats.scheduled_count++;
最后看下:
reschedule_root_alarm
// If used in a zeroed state, disarms the timer.
struct itimerspec timer_time;
memset(&timer_time, 0, sizeof(timer_time));
//取出最接近到期的alarm
const alarm_t *next = list_front(alarms);
const int64_t next_expiration = next->deadline - now();
//如果到期时间小于 int64_t TIMER_INTERVAL_FOR_WAKELOCK_IN_MS = 3000; 3秒
if (next_expiration < TIMER_INTERVAL_FOR_WAKELOCK_IN_MS)
wakelock_acquire() //禁止休眠
//计算到期时间
timer_time.it_value.tv_sec = (next->deadline / 1000);
timer_time.it_value.tv_nsec = (next->deadline % 1000) * 1000000LL;
//???还没研究wakeup_timer
// 猜测是唤醒系统的wakeup_timer
// 此时已经禁止休眠,等待timer到期,应该删除wakeup_timer,但开销太大,所以设置一个很大很大的超时值
struct itimerspec end_of_time;
memset(&end_of_time, 0, sizeof(end_of_time));
end_of_time.it_value.tv_sec = (time_t)(1LL << (sizeof(time_t) * 8 - 2));
timer_settime(wakeup_timer, TIMER_ABSTIME, &end_of_time, NULL);
else
struct itimerspec wakeup_time;
memset(&wakeup_time, 0, sizeof(wakeup_time));
wakeup_time.it_value.tv_sec = (next->deadline / 1000);
wakeup_time.it_value.tv_nsec = (next->deadline % 1000) * 1000000LL;
//将到期时间设置为唤醒的timer值
if (timer_settime(wakeup_timer, TIMER_ABSTIME, &wakeup_time, NULL) == -1)
//If new_value->it_value specifies a zero value (i.e., both subfields are zero), then the timer is disarmed.
// 0值的话,timer会被取消
if (timer_settime(timer, TIMER_ABSTIME, &timer_time, NULL) == -1)
//考虑到一种情况,定时时间非常短,由于上下文??? 没有被执行,这里检测到这种情况,然后手动执行
//执行两次也没关系
if (timer_set) {
struct itimerspec time_to_expire;
timer_gettime(timer, &time_to_expire);
if (time_to_expire.it_value.tv_sec == 0 &&
time_to_expire.it_value.tv_nsec == 0) {
LOG_DEBUG(LOG_TAG, "%s alarm expiration too close for posix timers, switching to guns", __func__);
semaphore_post(alarm_expired);
}
}
总结:
1 timer 用来执行进程中所有的 alarm, alarms 保存根据时间排序组织成链表;
2 一类timer 只能一个执行完后,再次添加进去,再执行; 如果还没被执行时,再次被添加则取消前一个,重新排序;
3 当timer到期后,把消息放到队列去执行
bluedroid alarm
猜你喜欢
转载自blog.csdn.net/x19910304xiaoyao/article/details/82958080
今日推荐
周排行