Rt-Thread 移植6--多线程(KF32)

news2024/11/21 0:32:05

6.1 就绪列表

6.1.1 线程就绪优先级组

线程优先级表的索引对应的线程的优先级。
在这里插入图片描述
为了快速的找到线程在线程优先级表的插入和移出的位置,RT-Thread专门设计了一个线程就绪优先级组。线程就绪优先组是一个32位的整型数,每一个位对应一个优先级,最多表示32个优先级

rt_uint32_t  rt_thread_ready_priority_group;

在这里插入图片描述

6.1.2 寻找优先级最高的线程

在这里插入图片描述
在这里插入图片描述

从图中看出,第一个置1的位是位1,即表示此时就绪的线程当中,优先级最高的线程1,然后调度器从线程优先级表的索引1下去除线程1的线程控制块,从而切换到线程1.
kservice.c中

const rt_uint8_t __lowest_bit_bitmap[] =
{
    /* 00 */ 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 10 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 20 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 30 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 40 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 50 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 60 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 70 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 80 */ 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* 90 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* A0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* B0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* C0 */ 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* D0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* E0 */ 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
    /* F0 */ 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
};

/**
 * This function finds the first bit set (beginning with the least significant bit)
 * in value and return the index of that bit.
 *
 * Bits are numbered starting at 1 (the least significant bit).  A return value of
 * zero from any of these functions means that the argument was zero.
 *
 * @return return the index of the first bit set. If value is 0, then this function
 * shall return 0.
 */
int __rt_ffs(int value)
{
    if (value == 0) return 0;

    if (value & 0xff)
        return __lowest_bit_bitmap[value & 0xff] + 1;

    if (value & 0xff00)
        return __lowest_bit_bitmap[(value & 0xff00) >> 8] + 9;

    if (value & 0xff0000)
        return __lowest_bit_bitmap[(value & 0xff0000) >> 16] + 17;

    return __lowest_bit_bitmap[(value & 0xff000000) >> 24] + 25;
}

6.1.3 线程优先级表

scheduler.c

rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];

在这里插入图片描述
将线程插入到线程优先级表和移出分别由scheduler.c的rt_schedule_insert_thread()和rt_schedule_remove_thread()这两个函数实现。

void rt_schedule_insert_thread(struct rt_thread *thread)
{
    register rt_base_t temp;


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

    /* change stat */
    thread->stat = RT_THREAD_READY | (thread->stat & ~RT_THREAD_STAT_MASK);

    /* insert thread to ready list */
    rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
                          &(thread->tlist));


    /* set priority mask */


#if RT_THREAD_PRIORITY_MAX > 32
    rt_thread_ready_table[thread->number] |= thread->high_mask;
#endif
    rt_thread_ready_priority_group |= thread->number_mask;

    P_DBG("insert thread %x grout %x\n",thread,rt_thread_ready_priority_group);
    /* enable interrupt */
    rt_hw_interrupt_enable(temp);
}

/*
 * This function will remove a thread from system ready queue.
 *
 * @param thread the thread to be removed
 *
 * @note Please do not invoke this function in user application.
 */
void rt_schedule_remove_thread(struct rt_thread *thread)
{
    register rt_base_t temp;



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


    /* remove thread from ready list */
    rt_list_remove(&(thread->tlist));
    if (rt_list_isempty(&(rt_thread_priority_table[thread->current_priority])))
    {

        rt_thread_ready_priority_group &= ~thread->number_mask;

    }

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

6.2 修改代码

6.2.1 修改线程控制块

struct rt_thread
{
	char name[RT_NAME_MAX];
	rt_uint8_t type;
	rt_uint8_t flag;
	rt_list_t list;
	void        *sp;	          /* 线程栈指针 */
	void        *entry;	          /* 线程入口地址 */
	void        *parameter;	      /* 线程形参 */	
	void        *stack_addr;      /* 线程起始地址 */
	rt_uint32_t stack_size;       /* 线程栈大小,单位为字节 */
	
	rt_list_t   tlist;            /* 线程链表节点 */
#if TEST_USE_TICK_ENABLE
	rt_ubase_t init_tick;
	rt_ubase_t remaining_tick;
#endif
	**rt_uint8_t current_priority;
	rt_uint8_t init_priority;
	rt_uint32_t number_mask;
	rt_err_t error;
	rt_uint8_t stat;**

};

rtdef.h中定义错误码

#define RT_EOK                          0               /**< There is no error */
#define RT_ERROR                        1               /**< A generic error happens */
#define RT_ETIMEOUT                     2               /**< Timed out */
#define RT_EFULL                        3               /**< The resource is full */
#define RT_EEMPTY                       4               /**< The resource is empty */
#define RT_ENOMEM                       5               /**< No memory */
#define RT_ENOSYS                       6               /**< No system */
#define RT_EBUSY                        7               /**< Busy */
#define RT_EIO                          8               /**< IO error */
#define RT_EINTR                        9               /**< Interrupted system call */
#define RT_EINVAL                       10              /**< Invalid argument */

定义线程状态

#define RT_THREAD_INIT                  0x00                /**< Initialized status */
#define RT_THREAD_READY                 0x01                /**< Ready status */
#define RT_THREAD_SUSPEND               0x02                /**< Suspend status */
#define RT_THREAD_RUNNING               0x03                /**< Running status */
#define RT_THREAD_BLOCK                 RT_THREAD_SUSPEND   /**< Blocked status */
#define RT_THREAD_CLOSE                 0x04                /**< Closed status */
#define RT_THREAD_STAT_MASK             0x0f

修改rt_system_scheduler_init()

void rt_system_scheduler_init(void)
{



	register rt_base_t offset;
	for(offset = 0; offset < RT_THREAD_PRIORITY_MAX;offset++)
	{
		rt_list_init(&rt_thread_priority_table[offset]);
	}
	rt_current_priority = RT_THREAD_PRIORITY_MAX - 1;
	rt_current_thread = RT_NULL;
	rt_thread_ready_priority_group = 0;

	/* 初始化线程休眠列表,当线程创建好没有启动之前会被放入到这个列表 */

}

6.2.3 修改线程初始化函数rt_thread_init()

rt_err_t rt_thread_init(struct rt_thread *thread,const char *name,
                        void (*entry)(void *parameter),
                        void             *parameter,
                        void             *stack_start,
                        rt_uint32_t       stack_size,
                        **rt_uint8_t priority**)
{
	rt_object_init((rt_object_t)thread,RT_Object_Class_Thread,name);
	rt_list_init(&(thread->tlist));

	thread->entry = (void *)entry;
	thread->parameter = parameter;

	thread->stack_addr = stack_start;
	thread->stack_size = stack_size;

	/* 初始化线程栈,并返回线程栈指针 */
	thread->sp = (void *)rt_hw_stack_init( thread->entry,
		                                   thread->parameter,
							               (void *)((char *)thread->stack_addr + thread->stack_size - 4) );
	**thread->init_priority = priority;
	thread->current_priority = priority;
	thread->number_mask = 0;
	thread->error = RT_EOK;
	thread->stat = RT_THREAD_INIT;**

}

6.2.4 添加线程启动函数rt_thread_startup()

rt_err_t rt_thread_startup(rt_thread_t thread)
{
	thread->current_priority = thread->init_priority;
	thread->number_mask = 1L << thread->current_priority;
	thread->stat = RT_THREAD_SUSPEND;
	rt_thread_resume(thread);
	if(rt_thread_self() != RT_NULL)
	{
		rt_schedule();
	}
}
rt_err_t rt_thread_resume(rt_thread_t thread)
{
	register rt_base_t temp;
	if((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_SUSPEND)
	{
		return -RT_ERROR;
	}
	temp = rt_hw_interrupt_disable();
	rt_list_remove(&(thread->tlist));

	rt_hw_interrupt_enable(temp);
	rt_schedule_insert_thread(thread);
}

6.2.5 修改空闲线程初始化函数rt_thread_idle_init()

void rt_thread_idle_init(void)
{
	    rt_thread_init(&idle,"idle",rt_thread_idle_entry,RT_NULL,&rt_thread_stack[0],sizeof(rt_thread_stack),RT_THREAD_PRIORITY_MAX - 1);

	**rt_thread_startup(&idle);**


}

6.2.6 修改启动系统调度器函数rt_system_scheduler_start()

不再是手动指定第一个需要运行的线程,而是根据优先级来决定第一个运行的线程。

void rt_system_scheduler_start(void)
{

	register struct rt_thread *to_thread;
	register rt_ubase_t highest_ready_priority;
	highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group)-1;
	P_DBG("first start pri %d\n",highest_ready_priority);
	to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,struct rt_thread,tlist);
	rt_current_thread = to_thread;
	rt_hw_context_switch_to((rt_uint32_t)&to_thread->sp);

}

6.2.7 修改系统调度函数rt_schedule()

根据优先级来实现

void rt_schedule(void)
{

	register rt_base_t temp;
	rt_base_t level;
	register rt_ubase_t highest_ready_priority;
	struct rt_thread *to_thread;
	struct rt_thread *from_thread;
	temp = rt_hw_interrupt_disable();
	highest_ready_priority = __rt_ffs(rt_thread_ready_priority_group)-1;
	P_DBG("read pri %d\n",highest_ready_priority);
	to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,struct rt_thread,tlist);
	P_DBG("read tgread %x\n",to_thread);
	if(to_thread != rt_current_thread)
	{
		P_DBG("!= current thread %x\n",rt_current_thread);
		rt_current_priority = (rt_uint8_t) highest_ready_priority;
		from_thread = rt_current_thread;
		rt_current_thread = to_thread;
		rt_hw_context_switch((rt_uint32_t)&from_thread->sp,(rt_uint32_t)&to_thread->sp);
		rt_hw_interrupt_enable(temp);
	}
	else
	{
		rt_hw_interrupt_enable(temp);
	}



	/* 产生上下文切换 */

}

6.2.8 修改线程阻塞函数


void rt_thread_delay(rt_tick_t tick)
{
	register rt_base_t temp;
	struct rt_thread *thread;
	temp = rt_hw_interrupt_disable(); 
	thread = rt_current_thread;
	thread->remaining_tick = tick;
	thread->stat = RT_THREAD_SUSPEND; 
	rt_thread_ready_priority_group &= ~thread->number_mask;
	rt_hw_interrupt_enable(temp);
	rt_schedule();
}

6.2.9 修改时基更i新函数rt_tick_increase()

void rt_tick_increase(void)
{
		rt_ubase_t i;
	struct rt_thread *thread;
	rt_tick++;
	for(i = 0;i < RT_THREAD_PRIORITY_MAX;i++)
	{
		thread = rt_list_entry(rt_thread_priority_table[i].next,struct rt_thread,tlist);
		if(thread->remaining_tick > 0)
		{
			thread->remaining_tick--;
			if(thread->remaining_tick == 0)
			{
				rt_thread_ready_priority_group |= thread->number_mask;
			}
		}
		rt_schedule();
	}
}

6.3 main.c


			/* 初始化线程 */
		rt_thread_init( &rt_flag1_thread,   "flag1",              /* 线程控制块 */
			                flag1_thread_entry,               /* 线程入口地址 */
			                RT_NULL,                          /* 线程形参 */
			                &rt_flag1_thread_stack[0],        /* 线程栈起始地址 */
			                sizeof(rt_flag1_thread_stack),3 );  /* 线程栈大小,单位为字节 */


			/* 将线程插入到就绪列表 */
		//rt_list_insert_before( &(rt_thread_priority_table[0]),&(rt_flag1_thread.tlist) );
		P_DBG("thread flag1 %x timer %s\n",&rt_flag1_thread,rt_flag1_thread.thread_timer.parent.name);
		rt_thread_startup(&rt_flag1_thread);
			/* 初始化线程 */

		rt_thread_init( &rt_flag2_thread,           "falg2",      /* 线程控制块 */
			                flag2_thread_entry,               /* 线程入口地址 */
			                RT_NULL,                          /* 线程形参 */
			                &rt_flag2_thread_stack[0],        /* 线程栈起始地址 */
			                sizeof(rt_flag2_thread_stack),4 );  /* 线程栈大小,单位为字节 */

/* 将线程插入到就绪列表 */
		P_DBG("thread flag1 %x timer %s\n",&rt_flag2_thread,rt_flag2_thread.thread_timer.parent.name);

		//rt_list_insert_before( &(rt_thread_priority_table[1]),&(rt_flag2_thread.tlist) );
		rt_thread_startup(&rt_flag2_thread);
			/* 启动系统调度器 */
		rt_system_scheduler_start();


/* 线程1 */
void flag1_thread_entry( void *p_arg )
{
	for( ;; )
	{
		P_DBG("flag1 thread\n");

		flag2 = 1;
		P_DBG("flag1 thread will dela1\n");
		rt_thread_delay(10);
		flag2 = 0;
		P_DBG("flag1 thread will dela2\n");
		rt_thread_delay(10);

	}
}

/* 线程2 */
void flag2_thread_entry( void *p_arg )
{
	for( ;; )
	{
		P_DBG("flag2 thread\n");

		flag2 = 1;
		rt_thread_delay(2);
		flag2 = 0;
		P_DBG("flag2 thread will dela1\n");
		rt_thread_delay(2);

	}
}

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

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

相关文章

Leetcode—69.x的平方根【简单】

2023每日刷题&#xff08;二十七&#xff09; Leetcode—69.x的平方根 直接法实现代码 int mySqrt(int x) {long long i 0;while(i * i < x) {i;}if(i * i > x) {return i - 1;}return i; }运行结果 二分法实现代码 int mySqrt(int x) {long long left 0, right (l…

数据拟合、参数估计、插值等数据处理算法

介绍 数据拟合&#xff1a; 数据拟合是通过选择或构建合适的函数模型&#xff0c;将给定的数据点与该函数模型进行匹配和拟合的过程。常见的数据拟合方法包括最小二乘法和非线性最小二乘法。最小二乘法通过最小化实际数据与拟合函数的残差平方和来求解最优拟合参数。非线性最小…

文本处理大师:Linux中grep、sed和awk的绝佳教程

1 grep 搜索关键字 全局搜索正则表达式 1.1 基本格式 grep root passwd #过滤含有root关键字-e 多个过滤词 grep -e root -e bash pa grep -E "root|bin" pa # 等同于上面的命令-i 忽略大小写 -E 过滤 grep -E "\<root" passwd ##root字符之前不能有…

中国建设银行转账模拟器,工商农业邮政中国招商假的回执单,易语言轻松实现

用易语言的选择夹画板黑月透明标签编辑框实现了一个假的转账模拟器&#xff0c;当然我还是加了水印的&#xff0c;这个图片你也用不了&#xff0c;只能是学习研究一下源码的实现逻辑&#xff0c;知道画板是怎么对编辑框输入的内容做出反应的&#xff0c;然后是如何获取画板上面…

Leetcode139单词拆分及其多种变体问题

1 声明 1.1 首先&#xff0c;大家常常把这道题当作了背包问题来做&#xff0c;因为其循环结构和背包问题刚好相反&#xff0c;但事实如此嘛&#xff1f; 背包问题通常都是组合问题&#xff0c;这其实是一道“”面向目标值的排列问题“&#xff0c;具体和背包问题有什么不同可…

PyQt制作【小红书图片抓取】神器

文章目录 &#x1f4e2;闲言碎语&#x1f43e;窗口设计&#x1f43e;功能设计&#x1f4da;资源领取 &#x1f4e2;闲言碎语 最近写一个系统&#xff0c;被一个Bug折腾了两天&#xff0c;至今还未解决。由于解决Bug弄得我有点心力憔悴&#xff0c;于是想着写其他小项目玩玩&am…

STM32F407的看门狗

文章目录 看门狗时钟两种看门狗IWDG结构图作用 寄存器IWDG_KR键值寄存器IWDG_PR预分频寄存器2-0 PR预分频器系数 IWDG_RLR重装载寄存器IWDG_SR状态寄存器1RVU 重载值更新0 PVU 预分频值更新注意 写保护超时时间使用步骤取消寄存器 写保护设置预分频系数和重装载值看门狗溢出时间…

2023年第十六届山东省职业院校技能大赛中职组“网络安全”赛项规程

第十六届山东省职业院校技能大赛 中职组“网络安全”赛项规程 一、赛项名称 赛项名称&#xff1a;网络安全 英文名称&#xff1a;Cyber Security 赛项组别&#xff1a;中职组 专业大类&#xff1a;电子与信息大类 二、竞赛目的 网络空间已经成为陆、海、空、天之后的第…

Openlayers:自定义Controls

Openlayers是一款优秀的二维开源地图框架,支持矢量/栅格图层,支持移动端,并且易于自定义和拓展。下面来讲述一下自定义Control的基本思路。 openlayers-features 问题描述 最近在做个人项目时,遇到了一个小问题,就是在地图中心添加一个十字针形状的符号,用来表示地图中心…

第25章_索引优化与查询优化

文章目录 1. 数据准备2.索引失效案例2.1全值匹配2.2最佳左前缀法则2.3主键插入顺序2.4 计算、函数导致索引失效2.5 类型转换导致索引失效2.6 范围条件右边的列索引失效2.7 不等于(! 或者<>)索引失效2.8 is null可以使用索引&#xff0c;is not null无法使用索引2.9 like以…

【数据结构初阶】顺序表SeqList

描述 顺序表我们可以把它想象成在一个表格里面填数据&#xff0c;并对数据做调整&#xff1b; 那我们的第一个问题是&#xff1a;怎么样在创建出足够的空间呢&#xff1f; 我们可以去堆上申请&#xff0c;用一个指针指向一块空间&#xff0c;如果申请的空间不够&#xff0c;我…

Spring基础学习——web

Spring基础学习——web 一、Spring整合Web环境1.1 JavaWeb三大组件作用及其特点1.2 Spring整合Web环境的思路及实现1.3 Spring开发Web环境组件spring-web1.4 web层MVC框架思想与设计思路 一、Spring整合Web环境 1.1 JavaWeb三大组件作用及其特点 在Java语言当中&#xff0c;w…

2023亚太杯数学建模A题思路

文章目录 0 赛题思路1 竞赛信息2 竞赛时间3 建模常见问题类型3.1 分类问题3.2 优化问题3.3 预测问题3.4 评价问题 4 建模资料5 最后 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 竞赛信息 2023年第十三…

【Java】Java8 Function 和 Consumer 接口的使用场景

文章目录 前言1. Function 示例2. Function 介绍3. Consumer 示例4. Consumer 介绍5. Function 和 Consumer 接口的使用场景后记 前言 在 《精通Java8》一书中有讲过 Java8的函数式接口可以简化设计模式的实施&#xff0c;这里记录一下Function 和 Consumer 的使用场景。 1. …

docker主备节点数据同步

主备节点挂载 在生产环境中&#xff0c;赋予一个docker操作系统的权限是一件不安全的事&#xff0c;在不具有系统操作权限的情况下&#xff0c;主备机无法通过nfs进行挂载。此时&#xff0c;可借助数据卷进行挂载 创建两个数据卷 docker volume create vol1 docker volume cr…

Java常用设计模式(23种)

文章目录 介绍 设计模式的六大原则 一、创建型模式 1、单例模式&#xff08;Singleton Pattern&#xff09; 1&#xff09;饿汉式 2&#xff09;懒汉式&#xff0c;双检锁 3&#xff09;静态内部类 4&#xff09;枚举 2、原型模式&#xff08;Prototype Pattern&#xff09…

(免费领源码)java#ssm#mysql在线学习平台85204-计算机毕业设计项目选题推荐

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;在线学习平台当然也不能排除在外。在线学习平台是以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#x…

线索二叉树(存储结构,线索化,寻找前驱/后继)

目录 1.线索二叉树1.中序线索二叉树2.后序线索二叉树3.先序线索二叉树 2.线索二叉树的存储结构3.二叉树的线索化1.中序线索化2.先序线索化3.后序线索化 4.寻找前驱/后继1.中序线索二叉树找后继2.中序线索二叉树找中序前驱3.先序线索二叉树找先序后继4.先序线索二叉树找先序前驱…

会员题-力扣408-有效单词缩写

有效单词缩写 字符串可以用 缩写 进行表示&#xff0c;缩写 的方法是将任意数量的 不相邻 的子字符串替换为相应子串的长度。例如&#xff0c;字符串 “substitution” 可以缩写为&#xff08;不止这几种方法&#xff09;&#xff1a; “s10n” (“s ubstitutio n”) “sub4…