RT_Thread临界区访问控制

更新时间:2023-05-12 13:38:03 阅读: 评论:0

RT_Thread临界区访问控制
⼀、WHY
什么是临界区,为什么我们需要临界区的访问控制?⾸先来看下wiki对临界区的定义:
在同步的中,临界区段(Critical ction)指的是⼀个访问共享资源(例如:共享设备或是共享存储器)的程序⽚段,⽽这些共享资源⽆法同时被多个访问的特性。当有线程进⼊临界区段时,其他线程或是进程必须等待,以确保这些共享资源是被的使⽤。⽐如打印机。
⼆、RT_Thread 临界区访问控制机制
2.1 全局中断:禁⽌全局中断,禁⽌抢占
全局中断开关也称为中断锁,是禁⽌多线程访问临界区最简单的⼀种⽅式,即通过关闭中断的⽅式,来保证当前线程不会被其他事件打断(因为整个系统已经不再响应那些可以触发线程重新调度的外部事件),也就是当前线程不会被抢占,除⾮这个线程主动放弃了处理器控制权,其函数接⼝如下:
rt_ba_t rt_hw_interrupt_disable(void);
void rt_hw_interrupt_enable(rt_ba_t level);
优点:使⽤中断锁来操作临界区的⽅法可以应⽤于任何场合,且其他⼏类同步⽅式都是依赖于中断锁⽽实现的,可以说中断锁是最强⼤的和最⾼效的同步⽅法。
缺点:在中断关闭期间系统将不再响应任何中断,也就不能响应外部的事件。所以中断锁对系统的实时性影响⾮常巨⼤,当使⽤不当的时候会导致系统完全⽆实时性可⾔。它属于粒度最⼤的访问控制机制
实现举例:
/*FILE: libcpu/arm/contex-m4/context_gcc.S*/
/*
* rt_ba_t rt_hw_interrupt_disable();
*/
.global rt_hw_interrupt_disable
.type rt_hw_interrupt_disable, %function
rt_hw_interrupt_disable:
MRS    r0, PRIMASK
CPSID  I
BX      LR
/*
* void rt_hw_interrupt_enable(rt_ba_t level);
*/
.global rt_hw_interrupt_enable
.type rt_hw_interrupt_enable, %function
rt_hw_interrupt_enable:
MSR    PRIMASK, r0
BX      LR
2.2 使能全局中断,禁⽌抢占
在这种情况下,打开全局中断,关闭调度功能,因为禁⽌了线程的调度器,所以哪怕是ISR中使⼀些thread恢复为ready 状态,其他线程也仍然不能抢占当前进程的运⾏。因此,该机制可以⽤来禁⽌多thread间的临界区同步。
优点:相⽐2.1,不会禁⽌全局中断, ISR仍然可以得到处理。
缺点:因为禁⽌了抢占,因为ISR资源(锁,信号量等)释放⽽重新ready的⾼优先级thread并不能抢占当前的thread,所以仍然会影响到实时性。
代码实现:
void rt_enter_critical(void)
{
register rt_ba_t level;
/
* disable interrupt */
level = rt_hw_interrupt_disable();
/*
* the maximal number of nest is RT_UINT16_MAX, which is big
* enough and does not check here
*/
rt_scheduler_lock_nest ++;
/* enable interrupt */
rt_hw_interrupt_enable(level);
}
void rt_exit_critical(void)
{
register rt_ba_t level;
/* disable interrupt */
level = rt_hw_interrupt_disable();
rt_scheduler_lock_nest --;
if (rt_scheduler_lock_nest <= 0)
{
rt_scheduler_lock_nest = 0;
/* enable interrupt */
rt_hw_interrupt_enable(level);
if (rt_current_thread)
{
/* if scheduler is started, do a schedule */
rt_schedule();
}
}
el
{
/* enable interrupt */
rt_hw_interrupt_enable(level);
}
}
2.3 使能全局中断,使能抢占,使⽤互斥锁同步
该机制会在临界区访问之前去检查锁是否有效,如果有效,则上锁并开始访问临界区,访问结束后释放锁;如果⽆效,则可以阻塞等待该锁有效。通过该机制,可以保证只有⼀个thread可以访问临界区。
优点:对系统的ISR处理和其他thread影响最⼩。
缺点:因为存在着锁的获取,释放,容易出现编程错误,产⽣死锁。
实现代码:
/**
* This function will take a mutex, if the mutex is unavailable, the
* This function will take a mutex, if the mutex is unavailable, the
* thread shall wait for a specified time.
*
* @param mutex the mutex object
* @param time the waiting time
*
* @return the error code
*/
rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time)
{
register rt_ba_t temp;
struct rt_thread *thread;
/* this function must not be ud in interrupt even if time = 0 */
RT_DEBUG_IN_THREAD_CONTEXT; 【1】
/
* get current thread */
thread = rt_thread_lf();
/* disable interrupt */
temp = rt_hw_interrupt_disable();
/* ret thread error */
thread->error = RT_EOK;
if (mutex->owner == thread)
{
/* it's the same thread */
mutex->hold ++;  【2】
}
el
{
__again:
/* The value of mutex is 1 in initial status. Therefore, if the
* value is great than 0, it indicates the mutex is avaible.
*/
if (mutex->value > 0)
{
/* mutex is available */
mutex->value --;
/* t mutex owner and original priority */
mutex->owner            = thread;
mutex->original_priority = thread->current_priority; 【3】
mutex->hold ++;
}
el
{
/* no waiting, return with timeout */
if (time == 0)
{
/* t error as timeout */
thread->error = -RT_ETIMEOUT;
/
* enable interrupt */
rt_hw_interrupt_enable(temp);
return -RT_ETIMEOUT;
}
el
{
/* mutex is unavailable, push to suspend list */
/* change the owner thread priority of mutex */
if (thread->current_priority < mutex->owner->current_priority)                {
/* change the owner thread priority */
rt_thread_control(mutex->owner,
RT_THREAD_CTRL_CHANGE_PRIORITY,
&thread->current_priority); 【4】
}
/* suspend current thread */
rt_ipc_list_suspend(&(mutex->parent.suspend_thread),
thread,
mutex->parent.parent.flag);
/* has waiting time, start thread timer */
if (time > 0)
{
/* ret the timeout of thread timer and start it */
rt_timer_control(&(thread->thread_timer),
RT_TIMER_CTRL_SET_TIME,
&time);
rt_timer_start(&(thread->thread_timer)); 【5】
}
/* enable interrupt */
rt_hw_interrupt_enable(temp);
/* do schedule */
rt_schedule();    【6】
if (thread->error != RT_EOK)
{
/
* interrupt by signal, try it again */
if (thread->error == -RT_EINTR) goto __again; 【7】
/* return error */
return thread->error;    【8】
}
el
{
/* the mutex is taken successfully. */
/* disable interrupt */
temp = rt_hw_interrupt_disable();
}
}
}
}
/* enable interrupt */
rt_hw_interrupt_enable(temp);
return RT_EOK;
}
【1】:需要保证调⽤该function的时候处于⾮中断上下⽂状态;why?
【2】:使⽤hold 计数来记录同⼀个thread占⽤锁的次数,⽅便同⼀线程的不同⼦函数的编程;
【3】【4】:为了消除优先级反转的问题,当等待互斥锁的thread A的优先级⽐占⽤锁的thread B优先级⾼,则提⾼thread B的优先级。【5】设定等待锁time out时间并开启timer
【6】调度调度器
【7】如果当前thread等待锁被signal 打断,则再次等待锁
【8】time out 时间到,退出等待
对应着锁释放代码实现:
/**
* This function will relea a mutex, if there are threads suspended on mutex, * it will be waked up.
*
* @param mutex the mutex object
*
* @return the error code
*/
rt_err_t rt_mutex_relea(rt_mutex_t mutex)
{
register rt_ba_t temp;
struct rt_thread *thread;
rt_bool_t need_schedule;
need_schedule = RT_FALSE;
/* only thread could relea mutex becau we need test the ownership */    RT_DEBUG_IN_THREAD_CONTEXT;
/* get current thread */
thread = rt_thread_lf();
/* disable interrupt */
temp = rt_hw_interrupt_disable();
/* mutex only can be relead by owner */
if (thread != mutex->owner)
{
thread->error = -RT_ERROR;
/* enable interrupt */
rt_hw_interrupt_enable(temp);
return -RT_ERROR;
}
/* decrea hold */
mutex->hold --;
/* if no hold */
if (mutex->hold == 0)
{
/* change the owner thread to original priority */
if (mutex->original_priority != mutex->owner->current_priority)
{
rt_thread_control(mutex->owner,
RT_THREAD_CTRL_CHANGE_PRIORITY,
&(mutex->original_priority));
}
/* wakeup suspended thread */
if (!rt_list_impty(&mutex->parent.suspend_thread))
{
/
* get suspended thread */
thread = rt_list_entry(mutex->parent.,
struct rt_thread,
tlist);
/* t new owner and priority */
mutex->owner            = thread;
mutex->original_priority = thread->current_priority;
mutex->hold ++;
/* resume thread */

本文发布于:2023-05-12 13:38:03,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/600053.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:中断   线程   全局
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图