set_bit(nr , p) 详解.

//kernel中的定义如下
#define set_bit(nr,p)			ATOMIC_BITOP_LE(set_bit,nr,p)

//__builtin_constant_p是gcc提供的内建函数,其目的是判断入参nr是否在编译阶段可以确定
//其值,如果在编译阶段可以确定值,则返回true,否则返回false
#define	ATOMIC_BITOP_LE(name,nr,p)		\
	(__builtin_constant_p(nr) ?		\
	 ____atomic_##name(nr, p) :		\
	 _##name##_le(nr,p))

//宏展开,则可以看到定义的是 ____atomic_set_bit
//bit的值是可以大于31的,是从 *p地址开始算,第 bit 位,下面详解
static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p)
{
	unsigned long flags;
	unsigned long mask = 1UL << (bit & 31);	//这里是取低5位(0~31),相当于 %32
	
	p += bit >> 5;	//相当于 除以32; 这句话的意思就是如果bit值大于31时,地址向后移动 bit/32 个,因为p是 unsigned long * , 所以这里地址加的是 bit/32

	raw_local_irq_save(flags);
	*p |= mask;	//给指定的 unsigned long 或上 mask,就是给对应的位置位
	raw_local_irq_restore(flags);
}

//r0:bit   r1: *p
//上面的是以32位来置位的,下面是以8位来置位的
ENTRY(_set_bit_le)
		and	r2, r0, #7			//r2 = r0 & 7; 同上面取第3位(0~7),相当于 %7
		mov	r3, #1				//r3 = 1
		mov	r3, r3, lsl r2		//r3 = 1 << r2; 到这里,按上面的写法是: r3 = 1 << (bit & 7),r3相当于mask
		save_and_disable_irqs ip, r2
		ldrb	r2, [r1, r0, lsr #3]	//r2 =  [r1 + (bit >> 3)]; 这句话类似  r2= *(p + bit >> 5), 只取8位
		orr	r2, r2, r3		// r2 = r2 | r3; r3相当于上面的mask
		strb	r2, [r1, r0, lsr #3]	//把或好的值放回源地址
		restore_irqs ip
		RETINSTR(mov,pc,lr)	//返回

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值