2

x86マシンでは、inc、addlなどの命令はアトミックではなく、SMP環境では、ロックプレフィックスなしでそれらを使用することは安全ではありません。ただし、UP環境では、inc、addl、およびその他の簡単な命令が中断されないため、安全です。

私の問題は、次のような経営幹部レベルのステートメントが与えられた場合です

x = x + 1;

Cコンパイラが常に次のようなUPセーフな命令を使用するという保証はありますか?

incl %eax

しかし、UP環境でも、スレッドセーフでない命令(コンテキストスイッチによって中断される可能性のあるいくつかの命令にCステートメントを実装するなど)はありませんか?

4

8 に答える 8

6

いいえ。

「volatile」を使用すると、コンパイラーがxを一時レジスターに保持するのを防ぐことができます。ほとんどのターゲットでは、これは実際に意図した効果をもたらします。しかし、それは保証されていません。

安全を確保するために、インラインasmを使用するか、移植性を維持する必要がある場合は、増分をミューテックスでカプセル化する必要があります。

于 2009-09-18T10:12:02.953 に答える
4

There is absolutely no guarantee that "x - x + 1" will compile to interrupt-safe instructions on any platform, including x86. It may well be that it is safe for a specific compiler and specific processor architecture but it's not mandated in the standards at all and the standard is the only guarantee you get.

You can't consider anything to be safe based on what you think it will compile down to. Even if a specific compiler/architecture states that it is, relying on it is very bad since it reduces portability. Other compilers, architectures or even later versions on the same compiler and architecture can break your code quite easily.

It's quite feasible that x = x + 1 could compile to an arbitrary sequence such as:

load r0,[x]  ; load memory into reg 0
incr r0      ; increment reg 0
stor [x],r0  ; store reg 0 back to memory

on a CPU that has no memory-increment instructions. Or it may be smart and compile it into:

lock         ; disable task switching (interrupts)
load r0,[x]  ; load memory into reg 0
incr r0      ; increment reg 0
stor [x],r0  ; store reg 0 back to memory
unlock       ; enable task switching (interrupts)

where lock disables and unlock enables interrupts. But, even then, this may not be thread-safe in an architecture that has more than one of these CPUs sharing memory (the lock may only disable interrupts for one CPU), as you've already stated.

The language itself (or libraries for it, if it's not built into the language) will provide thread-safe constructs and you should use those rather than depend on your understanding (or possibly misunderstanding) of what machine code will be generated.

Things like Java synchronized and pthread_mutex_lock() (available to C under some OS') are what you want to look into.

于 2009-09-18T12:21:00.190 に答える
4

GLibを使用する場合、intおよびポインターのアトミック操作用のマクロがあります。

http://library.gnome.org/devel/glib/stable/glib-Atomic-Operations.html

于 2009-09-18T10:25:18.600 に答える
4

GCCの最近のバージョンには、あなたが望むことを正確に実行するための__sync_xxx組み込み関数があります。

書く代わりに:

x + = 1;

これを書く:

__sync_fetch_and_add(&x、1);

そしてgccは、これがアトミックオペコードにコンパイルされることを確認します。これは現在、最も重要なアーチでサポートされています。

http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html

これは元々、ia64でのIntel for Cの推奨事項に基づいていますが、他の多くのアーチでもgccを実行する方法が見つかりました。だからそれは少しでもポータブルです。

于 2009-09-18T21:21:40.543 に答える
1

Cコンパイラが常にUPセーフな命令を使用するという保証はありますか?

C規格にはありません。ただし、コンパイラ/標準ライブラリは、特別な型または特定の保証を提供する場合があります。

このgccドキュメントは、必要なものに沿っている可能性があります。

于 2009-09-18T10:20:11.357 に答える
0

SMPを対象としたライブラリに頼るか、独自のインラインアセンブラコードをロールする必要があると思います。

于 2009-09-18T10:08:25.160 に答える
0

ACコンパイラはx = x + 1、いくつかの命令のようにステートメントを実装する場合があります。registerキーワードを使用して、メモリの代わりにレジスタを使用するようにコンパイラにヒントを与えることができますが、コンパイラは
それを自由に無視できます。

WindowsのInterlockedIncrement関数のようなOSロック固有のルーチンを使用することをお勧めします。

于 2009-09-18T10:16:59.223 に答える
0

とにかく、x86だけを心配するのは、恐ろしく移植性のないコーディングです。これは、それ自体がプロジェクトであることが判明した、一見小さなコーディングタスクの1つです。幅広いプラットフォームでこの種の問題を解決する既存のライブラリプロジェクトを見つけて使用します。kaizer.seによると、GLibは1つのようです。

于 2009-09-18T10:27:57.190 に答える