在arm系统中,对cpu核的设计。使用了位技术变量来代表每个cpu的使用情况。
但是这里考虑到多核对同一变量的设置,因为有了多核访问,于是乎就需要防止冲突的机制。真样产生了特殊情况的操作位接口--> macro bitop, name, instr。
使用汇编的形式来完成。主要的技术,是arm arch6中的strex, ldrex。
STREX指令的英文解释如下:
STREX (Store Register Exclusive) performs a conditional store to memory. The store only occurs if the
executing processor has exclusive access to the memory addressed.
也就是说,这条存储指令具有cpu核的排它性。只有cpu具有独立访问该memor addressed的时候,才可以存储。否则,cpu存储指令失败。接下来就看看具体的使用方式。
语法如下:
Syntax
STREX{<cond>} <Rd>, <Rm>, [<Rn>]
where:
<cond> Is the condition under which the instruction is executed. The conditions are defined in The
condition field on page A3-3. If <cond> is omitted, the AL (always) condition is used.
<Rd> Specifies the destination register for the returned status value. The value returned is:
0
if the operation updates memory
1
if the operation fails to update memory.
<Rm> Specifies the register containing the word to be stored to memory.
<Rn> Specifies the register containing the address.
Rd是一个返回该存储状态寄存器,这里可以知道这次存储的状况。
Rm保留了需要存储到memory的值。
Rn 指定了将Rm值保存到memory的地址。
LDREX指令的英文解释如下:
LDREX (Load Register Exclusive) loads a register from memory, and:
• if the address has the Shared memory attribute, marks the physical address as exclusive access for the
executing processor in a shared monitor
• causes the executing processor to indicate an active inclusive access in the local monitor.
语法如下:
LDREX{<cond>} <Rd>, [<Rn>]
where:
<cond> Is the condition under which the instruction is executed. The conditions are defined in The
condition field on page A3-3. If <cond> is omitted, the AL (always) condition is used.
<Rd> Specifies the destination register for the memory word addressed by <Rd>.
<Rn> Specifies the register containing the address.
操作如下:
MemoryAccess(B-bit, E-bit) if ConditionPassed(cond) then processor_id = ExecutingProcessor() Rd = Memory[Rn,4] physical_address = TLB(Rn) if Shared(Rn) == 1 then MarkExclusiveGlobal(physical_address,processor_id,4) MarkExclusiveLocal(physical_address,processor_id,4) /* See Summary of operation on page A2-49 */
在ARM手册中有如下说明使用STREX与LDREX的范围:
Use STREX in combination with LDREX to implement inter-process communication in multiprocessor and
shared memory systems
Use LDREX in combination with STREX to implement inter-process communication in shared memory
multiprocessor systems. For more information see Synchronization primitives on page A2-44. The
mechanism can also be used locally to ensure that an atomic load-store sequence occurs with no intervening
context switch.
指令总结:
1,这条指令是用于多核处理器中,用于处理多核访问共享内存的排他性而设计的,单核最好不要使用。
因为比一般的存储指令要耗时。
从STREX指令的伪操作可以猜测出:
MemoryAccess(B-bit, E-bit) processor_id = ExecutingProcessor() if ConditionPassed(cond) then if (CP15_reg1_Ubit == 0) then if address[0] == 0b0 then Memory[address,2] = Rd[15:0] else Memory[address,2] = UNPREDICTABLE else /* CP15_reg1_Ubit ==1 */ Memory[address,2] = Rd[15:0] if Shared(address) then /* ARMv6 */ physical_address = TLB(address) ClearExclusiveByAddress(physical_address,processor_id
2,LDREX与STREX要一起共同使用构成同步原语。
有了这些知识点的普及, 我们在来分析bitop这个宏汇编是如何实现设置一个long数组中的某个位。
bitop宏代码如下:
.macro bitop, name, instr ENTRY( \name ) UNWIND( .fnstart ) ands ip, r1, #3 strneb r1, [ip] @ assert word-aligned mov r2, #1 and r3, r0, #31 @ Get bit offset mov r0, r0, lsr #5 add r1, r1, r0, lsl #2 @ Get word offset mov r3, r2, lsl r3 1: ldrex r2, [r1] \instr r2, r2, r3 strex r0, r2, [r1] cmp r0, #0 bne 1b bx lr UNWIND( .fnend ) ENDPROC(\name ) .endm
我们使用实例,
set_bit(cpumask_check(cpu), cpumask_bits(dstp));来分析该汇编代码。
化间成:
set_bit(int cpu, long * (maskp)->bits);
所以对于汇编来说:bitop _set_bit, orr 展开前。
r0 = cpu;
r1 = long型数据的首地址,用于存放位状态的存储器。
instr = orr指令。
第一模块: 内存对齐检测
ands ip, r1, #3
strneb r1, [ip] @ assert word-aligned
主要看一看long型的数据首地址是否位word-aligned, 如果不对齐,去访问0地址空间,引起NULL异常。
第二模块:将r0与32位进行mod操作,获取位偏移量,和long数组的偏移量。
mov r2, #1
and r3, r0, #31 @ Get bit offset
mov r0, r0, lsr #5
add r1, r1, r0, lsl #2 @ Get word offset
mov r3, r2, lsl r3
1,将r2 = = 1 (mov r2, #1)
2,%操作,保留r0中32位中的余数到r3寄存器中,也就是位的偏移量。(and r3, r0, #31)
3,获得参数中parm0中的word偏移量(mov r0, r0, lsr #5),这个时候,r0为原始parm0中的long数组偏移量。
4,将指针转到parm1,long数组中的目标long数据地址。(add r1, r1, r0, lsl #2),r1存放的是param1中相应parm0位的整数偏移量。
5,r3是param0中具体某个long数据的偏移量设置成1(mov r3, r2, lsl r3)
第三模块:orr操作,并且保存结果到memory中。
1: ldrex r2, [r1]
\instr r2, r2, r3
strex r0, r2, [r1]
cmp r0, #0
bne 1b
1,使用多核同步原语 ldrex, 获取r1地址中的数据。保存到r2中。(ldrex r2, [r1])
2,使用orr,或操作, 将保存在r3中的设置位与r1地址中的数据进行or操作,完成指定位的操作。(\instr r2, r2, r3)
3,通过多核同步原语将r2中的新值存储到r1指定的地址。
4,判断该多核存储操作是否完成,如果完成,返回,否则重复进行。
到这里, 就完成了arm set_bit的汇编代码分析。 可以看到,这里使用了ldrex与strex同步原语。
避免了多核之间的数据不同步问题。
(该博客是原创,转载请注明原创地址。 谢谢!)
相关推荐
在Linux某种特殊情况下 ping命令报错cat_set_proc 该文档源码层级分析核心原因 帮忙学习Linux权限、用户等
DC工具中set_dont_touch和set_size_only的区别
Oracle性能分析——使用set_autotrace_on和set_timing_on来分析select语句的性能.doc
/sbin/set_irq_affinity eth1 可以进行中断绑定指定的cpu,提高网卡收包效率 把下面“eth1” 修改成对应的网卡名称 irq=$(cat /proc/interrupts | grep eth1 | cut -d':' -f 1); echo $irq for i in $irq ; do sudo...
TMS320C54x_DSP_Reference_Set_Volume_1_CPU_and_Peripherals.pdf
嵌入式系统关于串口传输、触摸屏、定时器、控制器、中断处理、音频控制等实验代码
Linux Kernel module which implements the set match and SET target for netfilter/iptables.
此文档是在linux环境下,网卡绑定的文档,希望能给大家帮助
Daniel Jslin教授分析linux kernel 中的start_kernel详细过程。by the way.可以关注我在csdn上关于linux kernel的课程https://edu.csdn.net/course/detail/9089
同步提取变换时频分析,大家可以试一试试一试
在Linux Ad-hoc mode下设定aodv-uu,非常经典的
#define PORTA_BIT SET_ADDRESS(PORTA) #endif #ifdef PORTB #define PORTB_BIT SET_ADDRESS(PORTB) #endif #ifdef PORTC #define PORTC_BIT SET_ADDRESS(PORTC) #endif #ifdef PORTD #define PORTD_BIT SET_...
Eclipse IDE for RCP and RAP Developers(eclipse-rcp-2022-06-R-linux-gtk-x86_64.tar.gz) 适用于Linux x86_64: A complete set of tools for developers who want to create Eclipse plug-ins, Rich Client ...
本程序是基于51单片机A7105的测试程序,其发送数据是一组流水灯数组,接收那边收到数据并用LED灯显示出来。本程序来自单片机教程网:http://www.ipbb.cn欢迎大家学习,交流
custom_cpu_widget::custom_cpu_widget(QWidget *parent) : QWidget(parent) ...void custom_cpu_widget::cpu_set_widget_level(int level) { this->cpu_used_level = level; this->repaint(); }
linux编程_弹球游戏_bounce 包含三个文件: bounce.c set_ticker.c bounce.h
mysql链接建立之后,通过如下方式设置编码: 复制代码 代码如下: mysql_query(“SET character_set_connection=” . $GLOBALS[‘charset’] . “,character_set_results=” . $GLOBALS[‘charset’] . “,character_...
param set linux_cmd_line "console=ttySAC0 root=/dev/nfs nfsroot=192.168.1.100:/opt/rootfs_qtopia_qt4 ip=192.168.1.101:192.168.1.100:192.168.1.111:255.255.255.0:sbc2440.arm9.net:eth0:off
Set_Bit(Hd7279_Data); Long_Delay(); for(i=0;i;i++) { Set_Bit(Hd7279_Clk); Short_Delay(); Data_In=Data_In; if(Hd7279_Data) Data_In=Data_In|0x01; Clear_Bit(Hd7279_Clk); Short_Delay(); } ...
瑞芯微RK3399处理器GPU和CPU性能方法参考...echo "800000000" >/sys/devices/platform/ff9a0000.gpu/devfreq/ff9a0000.gpu/userspace/set_freq cat /sys/devices/platform/ff9a0000.gpu/devfreq/ff9a0000.gpu/cur_freq