以下のユーザーレベルのコード スニペットを作成して、atomicinc
とxchg
(Linux コードを参照) という 2 つのサブ関数をテストしました。私が必要としているのは、32 ビット整数に対して操作を実行することだけです。そのため、明示的に を使用していますint32_t
。global_counter
異なるスレッドで競合すると思いますが、tmp_counter
問題ありません。
#include <stdio.h>
#include <stdint.h>
int32_t global_counter = 10;
/* Increment the value pointed by ptr */
void atomic_inc(int32_t *ptr)
{
__asm__("incl %0;\n"
: "+m"(*ptr));
}
/*
* Atomically exchange the val with *ptr.
* Return the value previously stored in *ptr before the exchange
*/
int32_t atomic_xchg(uint32_t *ptr, uint32_t val)
{
uint32_t tmp = val;
__asm__(
"xchgl %0, %1;\n"
: "=r"(tmp), "+m"(*ptr)
: "0"(tmp)
:"memory");
return tmp;
}
int main()
{
int32_t tmp_counter = 0;
printf("Init global=%d, tmp=%d\n", global_counter, tmp_counter);
atomic_inc(&tmp_counter);
atomic_inc(&global_counter);
printf("After inc, global=%d, tmp=%d\n", global_counter, tmp_counter);
tmp_counter = atomic_xchg(&global_counter, tmp_counter);
printf("After xchg, global=%d, tmp=%d\n", global_counter, tmp_counter);
return 0;
}
私の2つの質問は次のとおりです。
- これら 2 つのサブ関数は適切に記述されていますか?
- これを 32 ビットまたは 64 ビットのプラットフォームでコンパイルした場合、これは同じように動作しますか? たとえば、ポインター アドレスの長さが異なる可能性があります。または、オペランドと競合する可能性が
incl
ありますか?xchgl