RT_Thread内核机制学习(二)

news2024/11/26 4:28:02

对于RTT来说,每个线程创建时都自带一个定时器
在这里插入图片描述

rt_err_t rt_thread_sleep(rt_tick_t tick)
{
    register rt_base_t temp;
    struct rt_thread *thread;

    /* set to current thread */
    thread = rt_thread_self();
    RT_ASSERT(thread != RT_NULL);
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);

    /* disable interrupt */
    temp = rt_hw_interrupt_disable();

    /* suspend thread */
    rt_thread_suspend(thread); //从就绪链表移除

    /* reset the timeout of thread timer and start it */
    rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick); //设置定时器定时时间
    rt_timer_start(&(thread->thread_timer)); //开启定时器

    /* enable interrupt */
    rt_hw_interrupt_enable(temp);

    rt_schedule();

    /* clear error number of this thread to RT_EOK */
    if (thread->error == -RT_ETIMEOUT)
        thread->error = RT_EOK;

    return RT_EOK;
}

延时过程:

  1. 将线程从就绪链表移除。
  2. 设置/启动定时器
  3. 每个Tick判断,定时器是否超时,调用超时函数。
/**
 * This function is the timeout function for thread, normally which is invoked
 * when thread is timeout to wait some resource.
 *
 * @param parameter the parameter of thread timeout function
 */
void rt_thread_timeout(void *parameter)
{
    struct rt_thread *thread;

    thread = (struct rt_thread *)parameter;

    /* thread check */
    RT_ASSERT(thread != RT_NULL);
    RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND);
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);

    /* set error number */
    thread->error = -RT_ETIMEOUT; //表示被唤醒原因是:超时

    /* remove from suspend list */
    rt_list_remove(&(thread->tlist)); //可能因为等待队列等原因而挂起,先移除

    /* insert to schedule ready list */
    rt_schedule_insert_thread(thread);

    /* do schedule */
    rt_schedule();
}
RTM_EXPORT(rt_thread_timeout);

超时函数:

  1. 将线程放入就绪链表尾部
  2. 发起调度
void rt_schedule_remove_thread(struct rt_thread *thread)
{
    register rt_base_t level;

    RT_ASSERT(thread != RT_NULL);

    /* disable interrupt */
    level = rt_hw_interrupt_disable();

    RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("remove thread[%.*s], the priority: %d\n",
                                      RT_NAME_MAX, thread->name,
                                      thread->current_priority));

    /* remove thread from ready list */
    rt_list_remove(&(thread->tlist));
    if (rt_list_isempty(&(rt_thread_priority_table[thread->current_priority])))
    {
#if RT_THREAD_PRIORITY_MAX > 32
        rt_thread_ready_table[thread->number] &= ~thread->high_mask;
        if (rt_thread_ready_table[thread->number] == 0)
        {
            rt_thread_ready_priority_group &= ~thread->number_mask;
        }
#else
        rt_thread_ready_priority_group &= ~thread->number_mask;
#endif
    }

    /* enable interrupt */
    rt_hw_interrupt_enable(level);
}

将线程从就绪链表中移除,首先从链表中删除,再判断优先级对应的链表是否空了?

在这里插入图片描述
可以快速查找到哪一位是1。

每次Tick中断还需要检查定时器

/**
 * This function will check timer list, if a timeout event happens, the
 * corresponding timeout function will be invoked.
 *
 * @note this function shall be invoked in operating system timer interrupt.
 */
void rt_timer_check(void)
{
    struct rt_timer *t;
    rt_tick_t current_tick;
    register rt_base_t level;

    RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n"));

    current_tick = rt_tick_get();

    /* disable interrupt */
    level = rt_hw_interrupt_disable();

    while (!rt_list_isempty(&rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
    {
        t = rt_list_entry(rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
                          struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]); //从链表中取出定时器

        /*
         * It supposes that the new tick shall less than the half duration of
         * tick max.
         */
        if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2) //判断时间是否到了
        {
            RT_OBJECT_HOOK_CALL(rt_timer_enter_hook, (t));

            /* remove timer from timer list firstly */
            _rt_timer_remove(t);

            /* call timeout function */
            t->timeout_func(t->parameter);

            /* re-get tick */
            current_tick = rt_tick_get();

            RT_OBJECT_HOOK_CALL(rt_timer_exit_hook, (t));
            RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));

            if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
                (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
            {
                /* start it */
                t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
                rt_timer_start(t);
            }
            else
            {
                /* stop timer */
                t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
            }
        }
        else
            break;
    }

    /* enable interrupt */
    rt_hw_interrupt_enable(level);

    RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check leave\n"));
}

依次判断定时器时间是否到了,到了的话就调用定时器超时函数。
在这里插入图片描述
定时器启动后放到链表中。

Tick中断检查定时器时,也是从链表中取出判断。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/938901.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Protobuf高性能接口ZeroCopyStream

Protobuf ZeroCopyStream 1.ZeroCopyStream protobuf在io接口上有一个叫做ZeroCopyStream&#xff0c;对于IO的接口设计&#xff0c;pb提供了相关序列化与反序列化接口&#xff0c;如&#xff1a; // Read a protocol buffer from the given zero-copy input stream. If // su…

Bigemap在公路勘察设计行业中如何应用呢?

选择Bigemap的原因&#xff1a; Google 已经停止使用&#xff0c;天地图清晰度偏低&#xff0c;bigmap可以提供多种不同源的影像、矢量数据。奥维&#xff0c;有接触&#xff0c;做了比选&#xff0c;后来从技术本身去考虑这个问题&#xff0c;影像、矢量数据下载方便&#xf…

命令行环境题目

在后台产生一个ID 不会输出任何东西

Golang Gorm 一对多的添加

一对多的添加有两种情况&#xff1a; 一种是添加用户的时候同时创建文章其次是创建文章关联已经存在的用户。 package mainimport ("gorm.io/driver/mysql""gorm.io/gorm" )// User 用户表 一个用户拥有多篇文章 type User struct {ID int64Name …

强强联袂,产教融合丨知了汇智与成都世纪超体达成战略合作

为了共培数字营销人才&#xff0c;实现产业、教育双向赋能&#xff0c;为地方乃至全国电商发展注入源源不断的行业性人才&#xff0c;8月24日&#xff0c;成都知了汇智科技有限公司&#xff08;以下简称“知了汇智”&#xff09;与成都世纪超体科技有限公司&#xff08;以下简称…

科技资讯|苹果发布新专利:可在车内定位苹果的智能设备

根据美国商标和专利局近期公示的清单&#xff0c;苹果公司获得了一项名为《车内定位移动设备的系统和方式》专利&#xff0c;概述了在车内狭窄空间内如何定位 iPhone 等移动设备。 Find My 服务现阶段没有使用 UWB 来追踪 iPhone 或者 iPad&#xff0c;而是依赖 GPS 等相关辅…

iTubeGo for Mac视频下载器

iTubeGo YouTube Downloader是一款功能强大的YouTube视频下载工具&#xff0c; 它具有以下特色&#xff1a; 多种格式支持&#xff1a;iTubeGo YouTube Downloader可以将YouTube视频下载为多种常见的视频和音频格式&#xff0c;包括MP4、MP3、AVI、FLV、MOV、WMV等&#xff0c…

RFID服装管理系统:点亮时尚世界的新星

今天我们要聊聊一个真正酷炫的系统——RFID服装管理系统。別担心&#xff0c;我会用最地道的方式跟你聊&#xff0c;咱们来解开这神秘的时尚密码吧&#xff01; 首先&#xff0c;先別怕&#xff0c;RFID其实是射频识别技术的缩写。别觉得高大上&#xff0c;其实就是让你的服装…

docker容器查看所有没使用的镜像,并删除

文章目录 场景1. 删除不用的容器删除无效容器2. 删除不用的镜像 场景 最近工作中遇到服务器磁盘紧张的情况&#xff0c;想到docker镜像和容器可以删除些不用的&#xff0c;省出来一些空间。具体操作如下: 1. 删除不用的容器 首先执行命令 docker ps -a 查看容器列表&#xff…

Maven 基础之安装和命令行使用

Maven 的安装和命令行使用 1. 下载安装 下载解压 maven 压缩包&#xff08;http://maven.apache.org/&#xff09; 配置环境变量 前提&#xff1a;需要安装 java 。 在命令行执行如下命令&#xff1a; mvn --version如出现类似如下结果&#xff0c;则证明 maven 安装正确…

ZeroMQ入门

官网: ZeroMQ 简介 ZeroMQ是一个库&#xff0c;不是消息队列也不是消息中间件&#xff0c;介于应用层和传输层之间&#xff08;按照TCP/IP划分&#xff09;。 传统的Socket通信模式需要创建连接&#xff0c;销毁连接&#xff0c;选择协议等一些列操作。而ZeroMQ是在Socket封…

①matlab的命令掌握

目录 输入命令 命名变量 保存和加载变量 使用内置的函数和常量 输入命令 1.您可以通过在命令行窗口中 MATLAB 提示符 (>>) 后输入命令 任务 使用命令 3*5 将数值 3 和 5 相乘。 答案 3*5 2.除非另有指定&#xff0c;否则 MATLAB 会将计算结果存储在一个名为 ans…

No119.精选前端面试题,享受每天的挑战和学习

文章目录 实现栈&#xff0c;有入栈出栈的方法&#xff0c;以及length属性如何封装组件单页应用怎么跨页面传参权限怎么设计的map和forEach对于对象类型会不会改变 实现栈&#xff0c;有入栈出栈的方法&#xff0c;以及length属性 可以通过 JavaScript 的数组来实现一个栈结构…

倒数 2 周|期待 2023 Google开发者大会

9 月 6-7 日&#xff0c;中国上海 前沿科技&#xff0c;新知同享 趣味体验&#xff0c;灵感齐聚 技术生态&#xff0c;多元共进 关注官网最新信息&#xff0c;敬请期待大会开幕 2023 Google 开发者大会官网 相信你一定记得&#xff0c;在今年 5 月的 Google I/O 大会上&am…

考察交流 | 九江市浔阳区委常委、副区长雷霆钧一行考察中创算力

考察交流 8月25日&#xff0c;九江市浔阳区委常委、副区长雷霆钧来访中创算力开展招商考察&#xff0c;中创董事长许伟威热情接待了调研领导一行。浔阳区数字经济发展中心主任曹超成、九江电信浔阳分局局长黄健、九江新联智创董事长刘诚志、德国石荷州中资企业协会副会长陈虹瑾…

SAP从放弃到入门系列之abapGit安装

文章目录 一、概括二、系统环境三、安装独立版本四、安装开发者版本4.1、在线安装&#xff08;推荐&#xff09;4.2、离线安装 前段时间看了汪子熙老师关于abap2UI5的文章&#xff0c;感觉很有意思,来了解一下。abapGit 安装的文章已经有很多了&#xff0c;但是为了在系统里使用…

redis windows 版本安装

1. 下载windows安装包并解压 如果是Linux版本可以直接到官网下载&#xff0c;自3.x起官网和微软网站就没有redis安装包更新了&#xff0c;好在github有开发者在编译发布更新&#xff08;目前最新有5.0.9版本可下&#xff09;&#xff0c;地址&#xff1a;redis windows 5版本下…

即时通讯开发中的5个难点及解决方案

在当今数字化时代&#xff0c;人们越来越依赖即时通讯应用程序进行实时消息传递、语音通话和视频聊天。然而&#xff0c;即时通讯开发并非易事&#xff0c;开发人员需要克服许多技术和功能上的挑战。以下是即时通讯开发过程中最常见的5个难点&#xff0c;以及专家们提出的解决方…

新闻稿发布策略:选择合适渠道,让品牌故事传遍大江南北

新闻稿是企业宣传和传媒报道的重要工具&#xff0c;它可以传达企业的最新动态、产品推出、重要事件等信息。而如何正确发布新闻稿&#xff0c;选择合适的发布渠道&#xff0c;对于提高新闻稿的曝光度和影响力至关重要。在本文中&#xff0c;我们一秒推小编将探讨新闻稿的发布方…

完美解决Ubuntu网络故障,连接异常,IP地址一直显示127.0.0.1

终端输入ifconfig显示虚拟机IP地址为127.0.0.1&#xff0c;具体输出内容如下&#xff1a; wxyubuntu:~$ ifconfig lo: flags73<UP,LOOPBACK,RUNNING> mtu 65536inet 127.0.0.1 netmask 255.0.0.0inet6 ::1 prefixlen 128 scopeid 0x10<host>loop txqueuelen …