当前位置:网站首页>Interrupt sharing variables with other functions and protection of critical resources
Interrupt sharing variables with other functions and protection of critical resources
2022-07-01 08:43:00 【Craftsman in Jianghu】
volatile
volatile Conceptual function
volatile( English translation : Changeable ) Is a feature modifier keyword , Prevent compiler Modify the variable related code Optimize , Read the value of the variable again every time you use , Instead of using the backup in the register .
volatile The literal meaning is not easy to understand , In fact, it reminds the compiler that this variable is mutable , Don't optimize it !
XBYTE[2]=0x55;
XBYTE[2]=0x56;
XBYTE[2]=0x57;
XBYTE[2]=0x58;
For external hardware , The above four statements represent different operations , There are four different movements , But the compiler optimizes these four statements , Think that there is only XBYTE[2]=0x58( Ignore the first three statements , Only one machine code is generated ). If you type volatile, Then the compiler will compile one by one and generate the corresponding machine code ( Generate four codes ).
Use... When declaring variables volatile Several cases of embellishment
The following situations need to be declared with volatile Keyword modifies it :
1)、 Hardware registers for parallel devices ( Such as : Status register )
2)、 A non automatic variable that will be accessed in an interrupt service subroutine (Non-automatic variables)
3)、 A variable shared by several tasks in a multithreaded application
Really understand volatile Total importance .
1、 A parameter can be either const It can also be volatile Do you ? Explain why .
answer : Yes .
For example, a read-only status register .
volatile Don't let the compiler optimize it .const Is not to let the program modify it .
2、 A pointer can be volatile Do you ? Explain why .
answer : Yes .
For example, when an interrupt service subroutine modifies a to point to a buffer The pointer of .
3、 The following function is used to calculate the square of an integer , Can it achieve the desired design objectives ? If not , Try to answer any questions :
int square(volatile int *ptr)
{
return ((*ptr) * (*ptr));
}
answer : You can't . This code is intended to return ptr The square of the value pointed to , but *ptr Point to one volatile Type parameter , The compiler will produce code similar to the following :
int square(volatile int* &ptr) // Here the parameter should be declared as a reference , Otherwise, only copies will be used in the function body , External cannot be changed
{
int a = *ptr;
int b = *ptr;
return a*b;
}
because *ptr The value of may change between two fetching statements , therefore a and b It could be different . result , This code may not return the square value you expect ! The correct code is as follows :
int square(volatile int*ptr)
{
int a = *ptr;
return a*a;
}
volatile Used in the following places :
1)、 The variables modified in interrupt service program for other programs to detect need to add volatile;
2)、 In a multitasking environment, the shared flag among tasks should be marked with volatile;
3)、 Memory mapped Hardware register Usually add volatile explain , Because every time you read and write it, it may have a different meaning ;
In the above cases, the integrity of data should also be considered ( For example, the mark is interrupted and rewritten in the middle of reading ),volatile It's not atomic , Therefore, we should consider the access conflict of critical resources .
1) It can be realized by closing the middle of the line , Or other methods ;
2) Task scheduling can be disabled in , Or other methods ;
3) We can only rely on the good design of hardware .
A critical region 、 Critical resources
A critical region : It refers to a program segment that accesses common resources . Shared resources are called Critical resources .
Critical resources : It cannot be used by multiple threads at the same time ( Such as multitasking , For example, interrupt the service program ) Access features , Only one thread can be used at a time . for example : Shared device or memory . The printer ; Interrupt service program and other programs 、 Interruptions and tasks 、 Task and task shared variables, etc .
Atomic manipulation 、 Atomicity 、 atom
atom : It refers to the basic particles that can not be subdivided in chemical reaction . This is a concept in physical chemistry , The fundamental property of atoms is indivisibility .
Atomicity : The indivisibility of a transaction , All operations of a transaction are either executed without interruption , Or none of them have been implemented .
Atomic manipulation : It refers to a series of operations that cannot be interrupted . It can be a one-step operation , It can also be a multi-step operation . Atomic operations depend on the underlying system CPU Realization . Atomic operation is closely related to the critical region , It can be said that atomic operation is the demand caused by the critical region .
Protection of critical resources
The core of critical resource protection is to Critical resource competition , Let it not be destroyed . In order not to be destroyed , Then let's Critical resources can only be used by one thread at a time . Those who can achieve this effect will immediately think of the switch interruption , Start and stop the dispatcher .
Like in FreeRTO The implementation of critical section is realized by switch interrupt .
function | API function | explain |
---|---|---|
Enter the critical area | taskENTER_CRITICAL() | |
taskENTER_CRITICAL_FROM_ISR() | Used to interrupt | |
Exit critical region | taskEXIT_CRITICAL() | |
taskEXIT_CRITICAL_FROM_ISR() | Used to interrupt |
Protection of critical resources – Atomic manipulation
If you visit = Critical resource itself is an atomic operation ( For example, an instruction can access and complete ), In this way, there is no need to deal with the switch interrupt . Like the early CPU The assembly of an instruction is an atomic operation , But then the instructions changed , such as X86 Block operation of 、SIMD Such instructions are no longer atomic operations . Therefore, even in a single core microprocessor, every assembly instruction cannot be regarded as an atomic operation , The only sure thing is atomic , I'm afraid there are only read and write registers .
stay linux The kernel provides a series of functions to implement atomic operations in the kernel , These functions fall into two categories , Perform atomic operations on bitwise and integer variables respectively . What they have in common is that the operation is atomic in any case , Kernel code can safely call them without interruption . Both bit and integer variable atomic operations depend on the underlying CPU Atomic operation implementation of , So all these functions are related to CPU Is closely related to the architecture of .
Protection of critical resources – lock
stay linux in , The functions to realize file locking are lock and fcntl, among lock Used to apply a suggestive lock to a file , and fcntl You can not only apply a suggestive lock , A forced lock can also be applied . meanwhile ,fcntl It can also lock the Moyi records of documents , That is, the record lock . Record locks are divided into read locks ( Shared lock ) And write lock ( Repulsive lock ).
spinlocks , It's a kind of lock , Spin lock is a kind of lock introduced to prevent multiprocessor concurrency , It is widely used in interrupt processing and other parts of the kernel ( For a single processor , To prevent concurrency in interrupt processing, we can simply turn off the interrupt , You don't need a spin lock ).
Spin locks can only be held by one kernel task at most , If a kernel task is trying to request one that has been contested ( Has been held ) The spin lock of , Then the task will be busy all the time —— rotate —— Wait for the lock to be available again . If it's not disputed , The kernel task that requests it can immediately get it and continue . Spin locking can prevent more than one kernel task from entering the critical region at any time , Therefore, this kind of lock can effectively avoid kernel tasks running concurrently on multiprocessors competing for shared resources . in fact , The original intention of spin lock is : Lightweight locking in the short term . A contested spin lock causes the requesting thread to spin while waiting for the lock to be available again ( A waste of processor time ), So spin locks should not be held for too long . If you need to lock for a long time , It is best to use semaphore .
The basic form of spin lock is as follows :
spin_lock(&mr_lock);
// A critical region
spin_unlock(&mr_lock);
Because spinlocks can only be held by up to one kernel task at a time , Therefore, only one thread is allowed to exist in the critical zone at a time . This well meets the locking service required by symmetric multiprocessing machines . On a single processor , Spin lock is just a switch to set kernel preemption . If kernel preemption does not exist , Then the spin lock will be completely removed from the kernel at compile time .
To put it simply , Spin lock in the kernel is mainly used to prevent concurrent access to critical areas in multiprocessors , Prevent competition caused by kernel preemption . In addition, spin lock does not allow task sleep ( Task sleep with spin lock will cause self deadlock —— Because sleep may cause kernel tasks holding locks to be rescheduled , And apply for the lock you have already held again ), It can be used in interrupt context .
Deadlock : Suppose there are one or more kernel tasks and one or more resources , Each kernel is waiting for one of these resources , But all the resources have been occupied . This will happen. All kernel tasks are waiting for each other , But they will never release the resources they already possess , So no kernel task can get the required resources , Can't continue to run , This means that a deadlock has occurred . Self - destructiveness means that you own a certain resource , Then I apply for the resources I have possessed , Obviously, it is impossible to obtain this resource again , So it's self binding
The realization of critical resource protection of bare metal single chip microcomputer
The protection of critical resources is liunx、RTOS There are encapsulated in the system API function , There is no single-chip bare metal API, It needs to be handled by users themselves . But the principle and method are the same .
Realization of critical section switch interrupt
(1) The first method : Directly use the statement to open or close interrupts to control .
The process : Close the interrupt –>> Critical resources –>> Open the interrupt
#define INT_DIS() disable_interrupt() // Turn off interrupt
#define INT_EN() enable_interrupt() // Turn on interrupt
advantage : Simple , Fast execution ( There's only one command ), It has outstanding advantages in occasions where critical protection operation is frequent .
shortcoming : Critical areas cannot be nested , There are hidden dangers in the nesting of critical areas . If in A The critical code area of the function calls another function B,B There are also critical code areas in functions , from B When function returns , The interrupt is turned on . This will result in A Function subsequent code loses critical protection .
Example : Prohibit interrupt methods to protect critical resources
Great circulation ( backstage )
INT_DIS() // Disable timed interrupts
Access critical resources ;
INT_EN() // Enable allow timed interrupts
Timer interrupt ( The front desk )
Manipulate global variables A;
(2) The second method : Embedded generic approach
Before switching off, push the register where the total interrupt allows the control bit status onto the stack and save it , Then turn off the interrupt protection critical area code , Then decide whether to turn on the interrupt according to the control word saved in the stack . After the critical code is executed , The interrupt permissive state will be restored to the state before entering the critical zone .
(3) The third method :
Save the state of the general interrupt permission control bit into a variable before switching off , Then turn off the interrupt protection critical code , Then decide whether to resume the interrupt according to the saved control word . It can also restore the interrupt allowable state before entering when exiting the critical zone .
The process : The interrupt status is stored in the variable –>> Close the interrupt –>> Global variables A–>> Enable interrupt according to interrupt status
shortcoming : Each critical code segment consumes an additional two bytes of storage space .
void EnterCritical(unsigned int *pSRVal)
{
*pSRVal = _get_SR_register(); // Save interrupt state
INT_DIS(); // No interruptions , Enter the critical area . Here we have to consider : What is the state before entering the critical zone , If it is forbidden to interrupt ?
}
void ExitCritical(unsigned int * pSRVal)
{
if(*pSRVal & GIE) // Judge the state before entering the critical zone , If it is an enable interrupt state , Then start interrupt .
{
INT_EN();
}
}
void Function_A(void)
{
unsigned int GIE_Val;
....
EnterCritical(&GIE_Val); // Enter the critical code area , Save the current interrupt status in GIE_Val variable ;
......
...... // Critical area code
ExitCritical(&GIE_Val); // Exit critical region , And according to GIE_Val The variable determines whether to interrupt ;
.....
}
(4) The fourth method : Use software to simulate stack behavior .
Count the number of times to enter the critical code and the number of times to exit the critical code , If there is a calling relationship between critical codes , Only interrupt and switch the outermost critical code area .
The process : Similar to the third method , But interrupts only operate on the outermost layer
unsigned char criticalNesting = 0;
unsigned int interruptStatusValue = 0;
void EnterCritical(void)
{
if(criticalNesting == 0) // Only operate on the outermost layer
{
interruptStatusValue = _get_SR_register(); // Save interrupt state
INT_DIS(); // No interruptions , Enter the critical area . Here we have to consider : What is the state before entering the critical zone , If it is forbidden to interrupt ?
}
criticalNesting++; // Global variables , Is the nested count of critical segments
}
void ExitCritical(void)
{
criticalNesting--;
if(criticalNesting == 0) // Only operate on the outermost layer .
{
if(interruptStatusValue & GIE) // Judge the state before entering the critical zone , If it is an enable interrupt state , Then start interrupt .
{
INT_EN();
}
}
}
Operating critical resource copies
sometimes , If the process of accessing critical resources is relatively long , You can make a copy of a critical resource , Data processed with a copy as a module .
So above ‘ The first method ’ As an example to illustrate the implementation method :
Close the interrupt –>> Accessing global variables A–>> Copy copy a–>> Open the interrupt ->> Operate on replica copies a
lock
If critical resources are more complex , If you use copy, it is also a resource consuming problem , This situation can be solved by making a lock !
Let's say 51 Take the front and back platform program architecture of bare metal kernel as an example : Timers share critical resources with large loops .
Example : Lock to protect critical resources
Great circulation ( backstage )
ET0 = 0; // Disable timed interrupts
Lock = 1;
ET0 = 1; // Enable allow timed interrupts
Access critical resources ;
ET0 = 0; // Disable timed interrupts
Lock = 0;
ET0 = 1; // Enable allow timed interrupts
Timer interrupt ( The front desk )
if(lock == 0)
{
Operating critical resources ;
}
else
{
;
}
if Lock = 1;
And Lock = 0;
The corresponding assembly instruction is an atomic operation, which can protect this lock without switch interrupt
Example : Lock to protect critical resources
Great circulation ( backstage )
Lock = 1; // If the corresponding assembly instruction of this statement is an atomic operation, the lock can be protected without switch interrupt
Access critical resources ;
Lock = 0; // If the corresponding assembly instruction of this statement is an atomic operation, the lock can be protected without switch interrupt
Timer interrupt ( The front desk )
if(lock ==0)
{
Operating critical resources ;
}
else
{
;
}
51 MCU realizes mutually exclusive signals to realize critical resource protection
for instance : If A Thread variables a As a temporary storage area , If an interrupt occurs halfway through the operation , This variable is also used in interrupts , When the interrupt returns , Variable a The content in has been destroyed , process A I don't know that , So we get the wrong running result .
The way to avoid seems simple : Take a variable as a flag , by 0 Time means no shared resources are used , by 1 When, it means that . Check the sign before use , by 1 Wait for time , by 0 Time set 1, And use resources , Put the sign back after use 0, So the problem of resource conflict is solved .
Is it? ? The problem shifted ---- When you check the variables , Found that it was 0, I'm going to put it in 1 when , The process is interrupted , Then other processes will still use the resource impolitely , The hell is in multitasking systems , When CPU When control comes back , The process that just used this resource has not used up this resource , So something went wrong .
You can see it , There must be one such instruction : First check a variable , When it's for 0 Time set 1 And jump , And this series of processes should not be interrupted , Instructions with this ability are called " Atomic operation instructions ".
because 51 There is no such directive , That's why many people upstairs say they want to shut down and interrupt . in fact , This method of switching off is also used in our desktop system ! LINUX A lot of off interrupts are used .
although 51 There is no such instruction as above , But there is another instruction :DJNZ— Subtract first and then check , And jump to... According to the comparison results , And this is enough to complete the critical zone operation . To initialize the system, you must set s Set the initial value as 1.
mutex_loop:
DJNZ s, mutex_wait ; First the s reduce 1, To determine s Is it 0, Not for 0 Jump to the mutex_wait To execute , Otherwise, execute in sequence .
.... Shared resource operation code ( That's the critical area )
INC s
RET
mutex_wait:
INC s
JMP mutex_loop
The above code is in any case ( Flying doesn't count , ha-ha ) It will not happen that two processes enter the critical zone at the same time .
You must think of , If the above code is written as a ⼦ Program , Then it can be used as a standard function for C Called , congratulations , This is the standard semaphore .
summary
1、volatile Interrupting global variables only ensures visibility , There is no guarantee of atomicity . Always understand that interrupt global variables are critical resources , Shared access needs protection .
2、 When accessing critical resources, you should pay attention to the problem of access nesting .
边栏推荐
- Internet of things technology is widely used to promote intelligent water automation management
- Do you know how data is stored? (C integer and floating point)
- Computer tips
- Introduction to R language
- IT 技术电子书 收藏
- Foundation: 3 Opencv getting started images and videos
- NFT监管要点和海外政策
- [深度剖析C语言] —— 数据在内存中的存储
- Intelligent water supply system solution
- 电脑小技巧
猜你喜欢
Mavros sends a custom topic message to Px4
Introduction to R language
Nacos - 配置管理
Foundation: 2 The essence of image
Glitch free clock switching technology
"Analysis of 43 cases of MATLAB neural network": Chapter 30 design of combined classifier based on random forest idea - breast cancer diagnosis
Agrometeorological environment monitoring system
C语言指针的进阶(上篇)
[detailed explanation of Huawei machine test] judgment string subsequence [2022 Q1 Q2 | 200 points]
【无标题】
随机推荐
MATLAB小技巧(16)矩阵特征向量特征值求解一致性验证--层次分析
《单片机原理与应用》——并行IO口原理
MAVROS发送自定义话题消息给PX4
Do you know how data is stored? (C integer and floating point)
Glitch free clock switching technology
factory type_id::create过程解析
公网集群对讲+GPS可视追踪|助力物流行业智能化管理调度
Matlab tips (16) consistency verification of matrix eigenvector eigenvalue solution -- analytic hierarchy process
15Mo3 German standard steel plate 15Mo3 chemical composition 15Mo3 mechanical property analysis of Wuyang Steel Works
I would like to know the process of stock registration and account opening by mobile phone? In addition, is it safe to open a mobile account?
集团公司固定资产管理的痛点和解决方案
【C】 Summary of wrong questions in winter vacation
一文纵览主流 NFT 市场平台版税、服务费设计
3、Modbus通讯协议详解
What is the material of 16mo3 steel plate? What is the difference between 16mo3 and Q345R?
目标检测的yolov3、4、5、6总结
大型工厂设备管理痛点和解决方案
内存大小端
如何做好固定资产管理?易点易动提供智能化方案
《MATLAB 神经网络43个案例分析》:第30章 基于随机森林思想的组合分类器设计——乳腺癌诊断