2.uC/OS III 内核, 关于临界段

来源:互联网 发布:阿里云华东1 编辑:程序博客网 时间:2024/05/21 06:37

摘抄自uC/OS-III Users Manual Chapter 4 - Critical Section.

A critical section of code, also called a critical region, is code that needs to be treated indivisibly. There are many critical section of code contained in uC/OS-III. if a critical section is accessible by an Interrupt Service Rountine (ISR) and a task, then disabling interrupts is necessary to protect the critical region. If the critical section is only accessible by task level code, the critical section may be protected through the use of a preemption lock

代码的临界段,也称为临界区,是需要处理不可分割的代码。在uc/os-iii中包含了许多关键的代码段。如果一个临界段可以被中断服务(ISR)和一个任务访问,那么就需要禁用中断来保护临界区域。如果临界段只能通过任务级代码访问,那么关键部分可以通过使用抢占锁来保护。

Within uC/OS-III, the critical section access method depends on which ISR post method is used by interrupts (see Chapater 9, “Interrupt Management” on page 157).

在uC/OS-III中,临界段访问方法依赖于中断使用的ISR 提交方法(见第157页的“中断管理”)。

If OS_CFG_ISR_POST_DEFERRED_EN is set to 0 (see OS_CFG.H) then uC/OS-III will disable interrupts when accessing internal critical sections.

 如果OS_CFG_ISR_POST_DEFERRED_EN被设置为0 (参见OS_CFG.H),那么uC/OS-III将在访问内部临界段时禁用中断。

If OS_CFG_ISR_POST_DEFERRED_EN is set to 1 then uC/OS-III will lock the scheduler when accessing most of its internal critical sections.

如果OS_CFG_ISR_POST_DEFERRED_EN被设置为1,那么uC/OS-III将在访问大多数内部临界段时锁定调度程序。

Chapter 9, “Interrupt Management” on page 157 discusses how to select the method to use.

第 9 章,“中断管理”页数157:讨论了如何选择使用的方法

Kernel defines one macro for entering a critical section and two macros for leaving

内核定义一个进入临界段宏和两个离开临界段的宏,如下:
OS_CRITICAL_ENTER()OS_CRITICAL_EXIT()OS_CRITICAL_EXIT_NO_SCHED()

These macros are internal to kernel and must not be invoked by the application code. However, if you need to access critical sections in your application code, consult Chapter 13, “Resource Management” on page 209.

这些宏是内核内部的,并且不能由应用程序代码调用。不管如何,如果你需要访问应用程序代码中的临界段,请查阅第 13 章,”资源管理”页数209

4.1 Disabling interrupts 屏蔽中断

When setting OS_CFG_ISR_POST_DEFERED_EN to 0, kernel will disable interrupts before entering a critical section and re-enable them when leaving the critical section

当OS_CFG_ISR_POST_DEFERED_EN设置为0时,内核将会关闭中断在进入临界段之前,并且离开临界段的时候重新启动他们。

OS_CRITICAL_ENTER() invokes the kernel macro CPU_CRITICAL_ENTER() that, in turn, calls CPU_SR_Save(). CPU_SR_Save() is a function typically written in assembly language that saves the current interrupt disable status and then disables interrupts. The saved interrupt disable status is returned to the caller and in fact, it is stored onto the caller’s stack in a variable called “cpu_sr”.

Xxxxxx, 轮流调用 CPU_SR_Save() ,  CPU_SR_Save() 是一个通常用汇编语言编写的函数,它会保存当前中断禁止的状态,然后禁止中断。保存的中断禁止状态被返回给调用者,事实上,它会被存储在一个名为“cpu_sr”的变量的调用者的堆栈当中。

OS_CRITICAL_EXIT() and OS_CRITICAL_EXIT_NO_SCHED() both invoke the kernel macro CPU_CRITICAL_EXIT(), which maps to CPU_SR_Restore(). CPU_SR_Restore() is passed the value of the saved “cpu_sr” variable to re-establish interrupts the way they were prior to calling OS_CRITICAL_ENTER().

OS_CRITICAL_EXIT() 和OS_CRITICAL_EXIT_NO_SCHED() 两个函数实际上都是调用内核的CPU_CRITICAL_EXIT()函数, 映射到CPU_SR_Restore(). CPU_SR_Restore() 是通过之前保存的”cpu_sr”这个变量来重新构建中断,这是调用OS_CRITICAL_ENTER() 之前的方式。

The typical code for the macros is shown in Listing 4 – 1.

#define OS_CRITICAL_ENTER()         { CPU_CRITICAL_ENTER(); }#define OS_CRITICAL_EXIT()          { CPU_CRITICAL_EXIT(); }#define OS_CRITICAL_EXIT_NO_SCHED() { CPU_CRITICAL_EXIT(); }
宏的典型代码如清单4 – 1. 所示。

4-1-1 MEASURING INTERRUPT DISABLE TIME 测量中断的禁止时间

Kernel provides facilities to measure the amount of time interrupts are disabled. This is done by setting the configuration constant CPU_CFG_TIME_MEAS_INT_DIS_EN to 1 in CPU_CFG.h

内核提供了工具来测量中断被禁止的时间的总和,这是通过在CPU_CFG.h 里面的CPU_CFG_TIME_MEAS_INT_DIS_EN设置为1来完成的。

The measurement is started each time interrupts are disabled and ends when interrupts are re-enabled. The measurement keeps track of two values: a global interrupt disable time, and an interrupt disable time for each task. Therefore, it is possible to know how long a task disables interrupts, enabling the user to better optimize their code.

每当已启动的中断被禁止时 和 被禁止的中断重新启动时开始测量。这个测量始终跟踪两个值:一个是全局的中断禁止时间,一个是每个任务中断禁止的时间,因此,可以知道一个任务会被禁用多少时间,使得用户可以更好的优化他们的代码。

The per-task interrupt disable time is saved in the task’s OS_TCB during a context switch(see OSTaskSwHook()in OS_CPU_C.c and described in Chapter 8, “Context Switching” on page 147 )

每个任务中断禁止的时间被保存在task’s OS_TCB(任务控制块)在上下文选择期间。(详细在页数147第 8 章 “上下文切断” OS_CPU_C.c中的OSTaskSwHook())

The unit of measure for the measured time is in CPU_TS(timestamp) units. It is necessary to find out the resolution of the timer used to measure these timestamps. For example, if the timer used for the timestamp is incremented at 1 MHz then the resolution of CPU_TS is 1 microsecond.

测量时间的度量单位是已CPU_TS(时间戳)为单位,有必要找出用于测量这些时间戳的计时器的分辨率。举个例子,假如计时器使用的时间戳增加到了1Mhz 那么 CPU_TS的分辨率是 1 微妙。

Measuring the interrupt disable time obviously adds measurement artifacts and thus increases the amount of time the interrupts are disabled. However, as far as the measurement is concerned, measurement overhead is accounted for and the measured value represents the actual interrupt disable time as if the measurement was not present.

测量中断禁用时间显然会增加测量的工作量,从而增加中断被禁止的时间,无论如何,就测量而言,测量开销是被计算的,测量的值代表了实际中断时间,就像测量不存在一样。

Interrupt disable time is obviously greatly affected by the speed at which the processor accesses instructions and thus, the memory access speed. In this case, the hardware designer might have introduced wait states to memory accesses, which affects overall performance if the system. This may show up as unusually long interrupt disable times.

中断禁用的时间显然很大程度上受到处理器访问指令的速度和内存访问速度的影响。在这种情况下,硬件设计者可能已经将等待状态引入内存访问当中。这将影响系统的总体性能,这可能出现异常长的中断禁用时间。

4 – 2 LOCKING THE SCHEDULER 锁定调度器
When setting OS_CFG_ISR_POST_DEFERRED_EN to 1, kernel locks the scheduler before entering a critical section and unlocks the scheduler when leaving the critical section

当OS_CFG_ISR_POST_DEFERRED_EN 被设置为1时,内核会在进入临界段之前锁定调度器,在离开临界段的时候解锁调度器。

OS_CRITICAL_ENTER() simply increments OSSchedLockNestingCtr to lock the scheduler. This is the variable the scheduler uses to determine whether or not the scheduler is locked. It is locked when the value is non-zero.

OS_CRITICAL_ENTER() 只是简单的增加了OSSchedLockNestingCtr 这个值来说定了调度器,这是调度器用来确定调度器是否被锁定的变量,当值非零时,它被锁定。

OS_CRITICAL_EXIT() decrements OSSchedLockNestingCtr and when the value reaches zero, invokes the scheduler.

当OSSchedLockNestingCtr为0时,OS_CRITICAL_EXIT()会调用调度器来切换程序。

OS_CRITICAL_EXIT_NO_SCHED() also decrements OSSchedLockNestingCtr, but does not invoke the scheduler when the value reaches zero.

OS_CRITICAL_EXIT_NO_SCHED()也会减少OSSchedLockNestingCtr,但是当值达到0时,也不会启动调度器调度程序。

The code for the macros is shown in Listing 4 – 2
宏的代码如清单4-2 所示

#define OS_CRITICAL_ENTER() {                    CPU_CRITICAL_ENTER(); \                    OSSchedLockNestingCtr++; \                    CPU_CRITICAL_EXIT(); \}#define OS_CRITICAL_EXIT() {                    CPU_CRITICAL_ENTER(); \                    OSSchedLockNestingCtr--; \                    if (OSSchedLockNestingCtr == (OS_NESTING_CTR) 0 ) { \                        CPU_CRITICAL_EXIT(); \                        OSSched(); \                    }else { \                        CPU_CRITICAL_EXIT(); \                    }}#define OS_CRITICAL_EXIT_NO_SCHED() {                   CPU_CRITICAL_ENTER(); \                   OSSchedLockNestingCtr--; \                   CPU_CRITICAL_EXIT(); \}

4 – 2 – 1 MEASURING SCHEDULER LOCK TIME

Kernel provides facilities to measure the amount of time the scheduler is locked. This is done by setting the configuration constant OS_CGF_SCHED_LOCK_TIME_MEAS_EN to 1 in OS_CFG.h

内核提供了测量调度程序锁定的工具,这是通过在OS_CFG.h里面的OS_CGF_SCHED_LOCK_TIME_MEAS_EN设置为1来完成的。

The measurement is started each time scheduler is locked and ends when the scheduler is unlocked. The measurement keeps track of two values: a global scheduler lock time, and a per-task scheduler lock time. it is Therefore possible to know how long a task locks the scheduler allowing the user to better optimize code.

每当开始锁定调度器 和 被启动调度器时候开始测量。这个测量始终跟踪两个值:一个是全局的调度器锁定时间,一个是每个任务调度锁定时间,因此,可以知道任务锁定调度程序的时间,使得用户可以更好的优化他们的代码。

The per-task scheduler lock time is saved in the task’s OS_TCB during a context switch(see OSTaskSwHook() in OS_CPU_C.c and described in Chapter 8, “Context Switching” on page 147 )

每个任务调度锁定的时间被保存在task’s OS_TCB(任务控制块)在上下文选择期间。(详细在页数147第 8 章 “上下文切断” OS_CPU_C.c中的OSTaskSwHook())

The unit of measure for the measured time is in CPU_TS(timestamp) units so It is necessary to find out the resolution of the timer used to measure these timestamps. For example, if the timer used for the timestamp is incremented at 1 MHz then the resolution of CPU_TS is 1 microsecond.

测量时间的度量单位是已CPU_TS(时间戳)为单位,有必要找出用于测量这些时间戳的计时器的分辨率。举个例子,假如计时器使用的时间戳增加到了1Mhz 那么 CPU_TS的分辨率是 1 微妙。

Measuring the scheduler lock adds measurement artifacts and thus increases the amount of time the scheduler is actually locked. However, measurement overhead is accounted for and the measured value represents the actual scheduler lock time as if the measurement was not present.

测量调度锁定的时间会增加测量的工作量,从而增加了调度器实际上锁定的时间,测量开销是被计算的,测量的值代表了实际调度器锁定时间,就像测量不存在一样。

4 – 3 KERNEL FEATURES WITH LINGER CRITICAL SECTIONS

Table 4-1 shows several kernel features that have potentially longer critical sections. Knowledge of these will help the user decide whether to direct kernel to use one critical section over another.

如4-1表所示 几个内核特性,这些特性可能具有更长的临界段。这些知识将帮助用户决定是否直接引导内核使用一个临界段而不是另一个临界段

这里写图片描述


4 – 4 SUMMARY 摘要

Kernel needs to access critical sections of code, which it protects by either disabling interrupts(OS_CFG_ISR_POST_DEFERRED_EN set to 0 in OS_CFG.h), or locking the scheduler(OS_CFG_ISR_POST_DEFERRED_EN set to 1 in OS_CFG.h).

内核需要访问临界段时,可以通过禁用中断来保护(当OS_CFG_ISR_POST_DEFERRED_EN 设置为 0 时,在OS_CFG.h), 或者是锁定调度器(当OS_CFG_ISR_POST_DEFERRED_EN 设置为1时,在OS_CFG.h).

The application code must not use:

应用程序不能使用:
OS_CRITICAL_ENTER();OS_CRITICAL_EXIT();OS_CRITICAL_EXIT_NO_SCHED();

When setting CPU_CFG_TIME_MEAS_INT_DIS_EN in CPU_CFG.h, kernel measures the maximum interrupt disable time. There are two values available, one for the global maximum and one for each task.

当CPU_CFG_TIME_MEAS_INT_DIS_EN 在CPU_CFG.h里被设置时,内核测量最大的中断禁止时间,有两个可用的值,一个用于全局的最大值,另一个用于每个任务

When setting OS_CFG_SCHED_LOCK_TIME_MEAS_EN to 1 in OS_CFG.h, kernel will measure the maximum scheduler lock time.

当OS_CFG_SCHED_LOCK_TIME_MEAS_EN在OS_CFG.h里被设置为1时,内核将会测量最大的锁定调度器的时间。
原创粉丝点击