タイトルが弱気だが、致し方ない。
何がしたかったかというと、pthread_create()で動かしているスレッドでwhile()させてぐるぐる動かしている状態を、外部から止めたかったのだ。
スレッドで、whileで、変数監視となると、volatileになる。
普段はグローバル変数で監視させていたのだが、今回はスレッドをぽこぽこ作るようにしていたので、各スレッドが使う変数を構造体でまとめて初期値で与えつつ、そのままスレッドと共有する領域として使おうという計画だ。
おじさんはね、OSを使ったプログラムに慣れていないので、他に方法が思いつかなかったのだ。
その構造体の中に、ループを制御するための変数を持とうと思ったが、ちょっと迷った。
volatileって、構造体のメンバに指定しても反映してくれるのだろうか?
こういうときは、環境依存になってもよいから実験するに限る。
#include <stdio.h>
struct vol {
int abc;
volatile int def;
} volvol;
int main(void)
{
while (volvol.def) {
;
}
return 0;
}
$ gcc --version
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
こんな環境で試した。
なお、Ubuntuは16.04で、VirtualBox上で動かしている。
コンパイルはこのようにして、O2で最適化してアセンブラ出力させた。
$ gcc -O2 -o vol.S -S vol.c
まず、volatileありの場合。
.file "vol.c"
.section .text.unlikely,"ax",@progbits
.LCOLDB0:
.section .text.startup,"ax",@progbits
.LHOTB0:
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB23:
.cfi_startproc
.p2align 4,,10
.p2align 3
.L2:
movl volvol+4(%rip), %eax
testl %eax, %eax
jne .L2
rep ret
.cfi_endproc
.LFE23:
.size main, .-main
.section .text.unlikely
.LCOLDE0:
.section .text.startup
.LHOTE0:
.comm volvol,8,8
.ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609"
.section .note.GNU-stack,"",@progbits
ふーん。
次、volatile無しの場合。
.file "vol.c"
.section .text.unlikely,"ax",@progbits
.LCOLDB0:
.section .text.startup,"ax",@progbits
.LHOTB0:
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB23:
.cfi_startproc
movl volvol+4(%rip), %eax
.p2align 4,,10
.p2align 3
.L2:
testl %eax, %eax
jne .L2
rep ret
.cfi_endproc
.LFE23:
.size main, .-main
.section .text.unlikely
.LCOLDE0:
.section .text.startup
.LHOTE0:
.comm volvol,8,8
.ident "GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609"
.section .note.GNU-stack,"",@progbits
差分は、ここ。
左がvolatileありで、右がvolatileなしだ。

L2ラベルでループしていて、volatileありはmovlがループ内に、volatile無しはmovlがループ外になった。
効いてる! 効いてるんだ!!
まあ、そもそもなんでvolatileが効かないかもしれないと思ったのか、という気もしてくる。
単に不安になっただけだ。
そういうことってあるだろう?
そういえば、gccとかって中間言語に吐き出してからリンカに掛けるとかだったから、アセンブラで安心するのは早いかもしれん。。。
いや、さすがにそこまでは疑わなくてもよいか。