64 位比较和交换 (CAS) 应该在 32 位计算机上工作吗? (或者64位机器?)

发布于 2025-01-04 12:32:07 字数 1522 浏览 2 评论 0原文

所以我读到,在 32 位机器中,可以使用 CAS 操作与对齐的 64 位块。 类似地,在 64 位机器中,可以使用对齐 128 位块的 CAS 操作。

我使用的是 32 位机器,因此我尝试了以下操作:

// sizeof(long long) is 8 bytes, so 64 bits
long long y = 12;
long long z = 12;
long long x = 99;
__sync_bool_compare_and_swap(&y, z, x);

CAS 成功将 y 的值更改为 99

但后来我尝试使用 char array[8];(其大小为 64 位)而不是 long long。我确实这么做了:

char full[8] = {'0', '1', '2', '3', '4', '5', '6', '7'}; 
char full2[8] = {'0', '1', '2', '3', '4', '5', '6', '7'};   
char full3[8] = {'5', '8', '9', 'G', 'X', '5', '6', 'U'};
__sync_bool_compare_and_swap(full, full2, full3);  

但在这种情况下,尽管 fullfull2 具有完全相同的数据,但 CAS 失败了。 (我还检查了 fullfull2 是否正确对齐)

所以第一次看起来 CAS 可以用于 64 位,但是第二次好像不行了。有什么想法吗?

编辑

(64位机器怎么样?)

好吧,问题是我在我的CAS中使用了char *并且这些仅被检查。因此,解决方案是转换为 long longuint64_t,它们是 64 位值。

但是当我需要使用128位值时,对于64位机器该怎么办呢? long long 在 64 位机器中仍然是 64 位,而 uint128_t 在 C 中似乎不存在。那么我应该转换为哪种类型? < code>double long 在我的 64 位机器中似乎是 128 位,但是在执行以下操作时:

  double long y = 32432143243214;
  double long z = 32432143243214;

  int x = __sync_bool_compare_and_swap(&y, z, 1234321990);

我收到此编译错误 错误:“__sync_bool_compare_and_swap”的参数 1 的类型不兼容

So I read that in a 32bit machine, one can use the CAS operation with aligned 64bit blocks.
Similarly, in a 64bit machine, one can use the CAS operation with aligned 128bit blocks.

I'm using a 32bit machine so I tried the following:

// sizeof(long long) is 8 bytes, so 64 bits
long long y = 12;
long long z = 12;
long long x = 99;
__sync_bool_compare_and_swap(&y, z, x);

and the CAS succeeded changing the value of y to 99.

But then I tried using a char array[8];(which size is 64 bits) instead of a long long. And I do:

char full[8] = {'0', '1', '2', '3', '4', '5', '6', '7'}; 
char full2[8] = {'0', '1', '2', '3', '4', '5', '6', '7'};   
char full3[8] = {'5', '8', '9', 'G', 'X', '5', '6', 'U'};
__sync_bool_compare_and_swap(full, full2, full3);  

But in this case, the CAS fails although full and full2 have exactly the same data. (I also checked that full and full2 where correctly alligned)

So the first time it seems that a CAS can be used to 64bit, but the second time it seems it can't. Any ideas why?

EDIT

(How about 64bit machines?)

Ok, so the problem was that I was using char * in my CAS and these were only checked. So the solution was to cast to long long or to uint64_t which are 64bit values.

But what should I do with a 64bit machine when I need to use 128bit value? long long is still 64bit in a 64bit machine and uint128_t doesn't seem to exist in C. So to which type should I cast? double long seems to be 128bit in my 64bit machine, but when doing the following:

  double long y = 32432143243214;
  double long z = 32432143243214;

  int x = __sync_bool_compare_and_swap(&y, z, 1234321990);

I get this compile error
error: incompatible type for argument 1 of ‘__sync_bool_compare_and_swap’.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

青巷忧颜 2025-01-11 12:32:07

您应该传递 full2 和 full3 的值,而不是指向它的指针。另外,您应该注意对齐。

__sync_bool_compare_and_swap((long long*)full,*(long long*)full2,*(long long*)full3);

(当然,这不是可移植的。如果你想要可移植性,请使用uint64_t而不是long long

You should pass the value of full2 and full3, not a pointer to it. Also, you should be care about the alignment.

__sync_bool_compare_and_swap((long long*)full,*(long long*)full2,*(long long*)full3);

(Of course, this is not portable. If you want portability, use uint64_t instead of long long)

初相遇 2025-01-11 12:32:07

看起来您忘记取消引用指针并进行强制转换。

我测试过,这是唯一正确的组合:

__sync_bool_compare_and_swap((long long*)full, *(long long *)full2, *(long long *)full3);

您需要强制转换第一个参数,否则它只会交换第一个字符。

关于处理 128 位双长,这是来自 gcc 4.1.2 文档

英特尔文档中给出的定义仅允许
使用 int、long、long long 类型及其无符号类型
同行。
GCC 将允许任何整数标量或指针类型,即 1、2、4 或
长度为 8 个字节。

所以看来你不能使用这个函数来处理这种情况。

Looks like you forgot to deref your pointers and cast.

I tested and this is the only combination that is correct:

__sync_bool_compare_and_swap((long long*)full, *(long long *)full2, *(long long *)full3);

You need to cast the first param or it will only swap the first char.

Regarding handling 128-bit double long, this is from the gcc 4.1.2 docs.

The definition given in the Intel documentation allows only for the
use of the types int, long, long long as well as their unsigned
counterparts.
GCC will allow any integral scalar or pointer type that is 1, 2, 4 or
8 bytes in length.

So it would seem you cannot use this function to handle that case.

淡淡的优雅 2025-01-11 12:32:07

您正在将 char * 传递给 __sync_bool_compare_and_swap。假设您的 char 数组(全部三个!)已正确对齐到 64 位(如果它们按照您显示的方式分配,则可能不是 - 使用 malloc!),尝试转换为 < code>(long long *) 在传递给 __sync_bool_compare_and_swap 之前。如果失败,请使用内联汇编器并直接调用CMPXCHG8B

You are passing a char * to __sync_bool_compare_and_swap. Assuming your char arrays (all three of them!) are properly aligned to 64 bits (if they're allocated in the way you show, they may not be - use malloc!), try casting to (long long *) before passing to __sync_bool_compare_and_swap. Failing that, use inline assembler and invoke CMPXCHG8B directly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文