//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) //返回