Should 64bit Compare&Swap (CAS) work on a 32bit machine? (or 64bit machine?)

送分小仙女□ 提交于 2020-01-14 03:59:12

问题


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’.


回答1:


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.




回答2:


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)




回答3:


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.



来源:https://stackoverflow.com/questions/9254082/should-64bit-compareswap-cas-work-on-a-32bit-machine-or-64bit-machine

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!