32位系统中原子操作64字节数据方式

static inline void __set_64bit (unsigned long long * ptr,
		unsigned int low, unsigned int high)
{
	__asm__ __volatile__ (
		"\n1:\t"
		"movl (%0), %%eax\n\t"
		"movl 4(%0), %%edx\n\t"
		"lock cmpxchg8b (%0)\n\t"
		"jnz 1b"
		: /* no outputs */
		:	"D"(ptr),
			"b"(low),
			"c"(high)
		:	"ax","dx","memory");
}

static inline void __set_64bit_constant (unsigned long long *ptr,
						 unsigned long long value)
{
	__set_64bit(ptr,(unsigned int)(value), (unsigned int)((value)>>32ULL));
}
#define ll_low(x)	*(((unsigned int*)&(x))+0)
#define ll_high(x)	*(((unsigned int*)&(x))+1)

static inline void __set_64bit_var (unsigned long long *ptr,
			 unsigned long long value)
{
	__set_64bit(ptr,ll_low(value), ll_high(value));
}

#define set_64bit(ptr,value) \
(__builtin_constant_p(value) ? \
 __set_64bit_constant(ptr, value) : \
 __set_64bit_var(ptr, value) )

__builtin_constant_p 是 GCC(GNU 编译器集合)中的一个内建函数,用于在编译时确定一个表达式是否为常量表达式。这个函数对于代码优化非常有用,因为编译器可以基于表达式是否为常量做出优化决策。

语法

int __builtin_constant_p(exp)

  • exp 是要被评估的表达式。

描述

  • 如果参数 exp 在编译时被认为是一个常量表达式,则该函数返回非零值。
  • 否则,返回零。

用法

该函数通常在宏中使用,根据表达式是否为常量来优化代码。例如,可以用来选择函数的不同实现,一个用于常量表达式,另一个用于变量表达式。

示例

#define my_max(a, b) (__builtin_constant_p(a) && __builtin_constant_p(b) ? ((a) > (b) ? (a) : (b)) : runtime_max(a, b))

int runtime_max(int a, int b) {
    return (a > b) ? a : b;
}

int main() {
    int x = 5;
    int y = 10;
    int z = my_max(x, y);        // 使用 runtime_max
    int w = my_max(20, 15);      // 使用编译时最大值计算
}

在这个例子中,宏 my_max 检查 ab 是否都是编译时常量。如果是,它使用编译时的 ? : 运算符来确定最大值。如果不是常量,则调用 runtime_max 函数在运行时确定最大值。

注意事项

  • 该函数是 GCC 特有的,其他编译器可能不支持。
  • 它通常用于低级编程,如系统库和嵌入式系统中,在这些场合性能优化非常关键。

在这段代码中,使用 __builtin_constant_p 来区分值是否为常量的目的是为了优化代码性能。具体原因如下:

优化常量表达式

如果 value 是一个常量表达式,编译器在编译时就可以确定它的值。因此,可以直接将 value 拆分成低32位和高32位,并传递给 __set_64bit 函数。这避免了在运行时进行拆分操作,从而提高了效率。

__set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) )

在这种情况下,编译器会在编译时计算出低32位和高32位,并直接生成优化后的代码

处理非常量表达式

如果 value 不是常量表达式,则需要在运行时进行拆分。这时,使用 ll_lowll_high 宏来获取 value 的低32位和高32位。

__set_64bit(ptr, ll_low(value), ll_high(value))

这段代码会在运行时通过指针操作从 value 中提取低32位和高32位。

内联汇编函数使用 cmpxchg8b 指令来原子性地设置64位值。它首先将指针 ptr 指向的内存内容加载到 eaxedx 寄存器,然后尝试用 lowhigh 的组合值来更新它。如果失败(即 cmpxchg8b 不成功),则循环重试。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值