设为首页 加入收藏

TOP

Zephyr学习(四)系统时钟(四)
2019-09-01 23:08:47 】 浏览:96
Tags:Zephyr 学习 系统 时钟
ssed in the same order they were 64 * added, time-wise. 65
*/ 66 67 sys_dlist_prepend(&expired, node); 68 69 timeout->delta_ticks_from_prev = _EXPIRED; 70 71 } else if (ticks <= 0) { 72 break; 73 } 74 75 irq_unlock(key); 76 key = irq_lock(); 77 78 timeout = (struct _timeout *)next; 79 } 80 81 irq_unlock(key); 82 83 _handle_expired_timeouts(&expired); 84 }

代码有点多,但是原理比较简单。

第7行,初始化一个超时双向链表,用于后面存放已经超时(到期)的线程。

第11行,取出超时队列的头节点。

第17行,即如果超时队列为空(没有超时任务要处理),则直接返回。

第30行,遍历超时队列。

第41行,如果取出的线程剩余的超时时间小于ticks(这里是1),则说面线程到期了,第42行将线程的超时时间置为0。否则,第44行,将超时时间减ticks。

第47行,剩下的ticks个数,其值可能为负数。

第49行,取出下一个节点。

第51行,如果当前线程的超时时间已经到了,则if条件成立。

第54行,将当前线程从超时队列移除。

第67行,将当前线程加入到临时队列里,后面会统一处理这个队列里的线程。

第69行,将当前线程的超时时间置为_EXPIRED。

如此循环,直到ticks用完(其值小于等于0),然后跳出循环,调用83行的_handle_expired_timeouts()函数,定义在zephyr-zephyr-v1.13.0\kernel\include\timeout_q.h:

1  static inline void _handle_expired_timeouts(sys_dlist_t *expired)
2  {
3      struct _timeout *timeout;
4  
5      SYS_DLIST_FOR_EACH_CONTAINER(expired, timeout, node) {
6          _handle_one_expired_timeout(timeout);
7      }
8  }

即遍历临时队列,每次调用_handle_one_expired_timeout()函数,定义在zephyr-zephyr-v1.13.0\kernel\include\timeout_q.h:

1  static inline void _handle_one_expired_timeout(struct _timeout *timeout)
2  {
3      struct k_thread *thread = timeout->thread;
4      unsigned int key = irq_lock();
5  
6      timeout->delta_ticks_from_prev = _INACTIVE;
7  
8      K_DEBUG("timeout %p\n", timeout);
9      if (thread) {
10         _unpend_thread_timing_out(thread, timeout);
11         _mark_thread_as_started(thread);
12         _ready_thread(thread);
13         irq_unlock(key);
14     } else {
15         irq_unlock(key);
16         if (timeout->func) {
17             timeout->func(timeout);
18         }
19     }
20 }

第6行,将超时时间置为_INACTIVE。

超时的方式有两种,一是线程调用k_sleep()等函数后将自己挂起导致的超时,二是线程调用软件定时器k_timer_start()函数导致的超时,线程本身不会挂起,只是开启了一个定时器。所以就有了第9行和第14行两种不同路径。

先看第一种方式,第10行,调用_unpend_thread_timing_out()函数,定义在zephyr-zephyr-v1.13.0\kernel\include\timeout_q.h:

1  static inline void _unpend_thread_timing_out(struct k_thread *thread,
2                           struct _timeout *timeout_obj)
3  {
4      if (timeout_obj->wait_q) {
5          _unpend_thread_no_timeout(thread);
6          thread->base.timeout.wait_q = NULL;
7      }
8  }

第5行,调用_unpend_thread_no_timeout()函数,定义在zephyr-zephyr-v1.13.0\kernel\sched.c:

1  void _unpend_thread_no_timeout(struct k_thread *thread)
2  {
3      LOCKED(&sched_lock) {
4          _priq_wait_remove(&pended_on(thread)->waitq, thread);
5          _mark_thread_as_not_pending(thread);
6      }
7  }

第4行,实际上调用的是_priq_dumb_remove()函数,定义在zephyr-zephyr-v1.13.0\kernel\sched.c:

void _priq_dumb_remove(sys_dlist_t *pq, struct k_thread *thread)
{
    __ASSERT_NO_MSG(!_is_idle(thread));

    sys_dlist_remove(&thread->base.qnode_dlist);
}

将线程从队列移除。

回到_unpend_thread_no_timeout()函数,第5行,将线程状态设置为不是_THREAD_PENDING。

回到_handle_one_expired_timeout()函数,第11~12行这两个函数在上一篇随笔里已经分析过了。第16~17行,如果定时器超时函数不为空,则调用定时器超时函数。

至此,handle_timeouts()函数分析完了。

回到_nano_sys_clock_tick_announce()函数,第15行,调用handle_time_slicing()函数,定义在zephyr-zephyr-v1.13.0\kernel\sys_clock.c:

1 static void handle_time_slicing(s32_t ticks)
2 {
3     if (!_is_thread_time_slicing(_current)) {
4         return;
5     }
6 
7     _time_slice_elapsed += tic
首页 上一页 1 2 3 4 5 下一页 尾页 4/5/5
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇per-CPU变量 下一篇网络中的NAT模式

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目