zoukankan      html  css  js  c++  java
  • `ll/sc` 指令在`linux`中的软件实现

    load-linkstore-conditional (LL/SC)是一对用于并发同步访问内存的CPU指令。Load-link返回内存位置处的当前值,随后的store-conditional在该内存位置处保存新值(如果从load-link后没有被修改)。这被用于实现无锁算法read-modify-write原子操作。

    linux<asm/atomic.h><asm/system.h><asm/cmpxchg.h><asm/bitops.h><asm/local.h>中实现了多种基本的原子操作,以最简单的atomic_add来举例:

    /*
     * atomic_add - add integer to atomic variable
     * @i: integer value to add
     * @v: pointer of type atomic_t
     *
     * Atomically adds @i to @v.
     */
    static __inline__ void atomic_add(int i, atomic_t * v)
    {
    	if (kernel_uses_llsc && R10000_LLSC_WAR) {
    		int temp;
    
    		__asm__ __volatile__(
    		"	.set	mips3					
    "
    		"1:	ll	%0, %1		# atomic_add		
    "
    		"	addu	%0, %2					
    "
    		"	sc	%0, %1					
    "
    		"	beqzl	%0, 1b					
    "
    		"	.set	mips0					
    "
    		: "=&r" (temp), "=m" (v->counter)
    		: "Ir" (i), "m" (v->counter));
    	} else if (kernel_uses_llsc) {
    		int temp;
    
    		__asm__ __volatile__(
    		"	.set	mips3					
    "
    		"1:	ll	%0, %1		# atomic_add		
    "
    		"	addu	%0, %2					
    "
    		"	sc	%0, %1					
    "
    		"	beqz	%0, 2f					
    "
    		"	.subsection 2					
    "
    		"2:	b	1b					
    "
    		"	.previous					
    "
    		"	.set	mips0					
    "
    		: "=&r" (temp), "=m" (v->counter)
    		: "Ir" (i), "m" (v->counter));
    	} else {
    		unsigned long flags;
    
    		raw_local_irq_save(flags);
    		v->counter += i;
    		raw_local_irq_restore(flags);
    	}
    }
    
    

    其中,kernel_uses_llsc是一个宏定义,当定义为0时就需要软件实现。raw_local_irq_saveraw_local_irq_restore函数定义在<linux/irqflags.h>,对于不同的mips cpu有不同的实现,最简单的实现如下:

    	.macro irq_enable_hazard; _ssnop; _ssnop; _ssnop;; .endm
    	.macro irq_disable_hazard; nop; nop; nop; .endm
    
    		.macro	raw_local_irq_save result			
    	.set	push						
    	.set	reorder						
    	.set	noat						
    	mfc0	
    esult, $12					
    	ori	$1, 
    esult, 0x1f				
    	xori	$1, 0x1f					
    	.set	noreorder					
    	mtc0	$1, $12						
    	irq_disable_hazard					
    	.set	pop						
    	.endm							
    
    		.macro	raw_local_irq_restore flags			
    	.set	push						
    	.set	noreorder					
    	.set	noat						
    	mfc0	$1, $12						
    	andi	flags, 1					
    	ori	$1, 0x1f					
    	xori	$1, 0x1f					
    	or	flags, $1					
    	mtc0	flags, $12					
    	irq_disable_hazard					
    	.set	pop						
    	.endm							
    

    raw_local_irq_saveraw_local_irq_restore被实现为两个mips的宏定义,raw_local_irq_savecp0status寄存器进行修改,让cpu进入kernek modeERLEXL0,同时禁止中断,从而保证了原子性。raw_local_irq_restore将中断使能打开。

  • 相关阅读:
    Java邮件开发(JavaMail)
    SQL删除所有表和数据
    Hyper-V由于虚拟机监控程序未运行
    .NET CORE IIS PUT和DELETE请求失败 405
    ReSharper 快捷键调试
    hyper-v提示监控未运行
    c#定义Ilist集合
    WindowsFormsApp1设置开机自启动
    SQL查询总数和分页数
    EF执行SQL语句
  • 原文地址:https://www.cnblogs.com/PowerofChoas/p/11247281.html
Copyright © 2011-2022 走看看