eventfdとpoll,epoll。そしてepollの謎。
Linux、Androidでのスレッド同期処理に何を利用しますか?
1:Nの同期時です。
細かい資源数の管理は不要で、最低1以上スレッドを起床、待ちを行うための同期。
私はパフォーマンスを考慮する際、Win32のEventと同じような処理を行うために、eventfdとpollを利用していました。
(条件変数はミューテックスを使うので遅いし、セマフォもちょっと違う)
しかし。
Win32でいうWaitForSingleObject代わりに、poll,ppollを利用していましたが落とし穴がありました。
これ、ビジーループじゃない?
たとえば利用目的としては、論理コア数分のスレッドを作成し、それらが同じeventfdに対してwaitします。
なにか処理を行いたいときに処理をリストに乗せてeventfdをwrite(Signal)。
これで効率的にスレッドによるジョブ処理が、Windowsでは行えていました。
LinuxではプロセスCPU負荷が100%でした。
ネットの海を漁ると、epollはカーネルが待ってくれるという。
これだ!
結果を言えば、”一応” 解決しました。
github.com
上記リポジトリにテストコードがあります。
Readmeにテスト結果を貼ってあるのですが、待ちスレッドのCPUがビジーにならず一番早い結果になっていると思います。
他に方法があれば教えてほしいです。
しかし、今の所epollに謎が残っています。
//最初にライトリードしておかないと、EPOLLOUTが発生してしまう eventfd_t v; eventfd_write(evt_, 1); eventfd_read(evt_, &v);
受けたいイベントはEPOLLINだけなのです。
しかし、最初にこのおまじないをしておかないとEPOLLOUTを受信してしまい、EINTRエラーが発生してしまうのです。
これについては未だわかりません。
なお、waitで、EINTRのエラーは許容しループしています。
これは、この問題のためではなく、デバッガーでブレイクを行った際に発生する割り込みに反応してしまうためです。