Gralloc, Treble and ION
カメラの画像など Surface を介しプロセスをまたいで流れていくメモリ (buffer) は Gralloc というアロケータで確保される。Gralloc は HAL である。
ところで Android は O ではじまった Project Treble によって多くの HAL が独立したプロセスに追い出された。Binderization という。昔の Windows の COM-fication および Mozilla でおきた反動の De-com-ificaton を思い出すがまあそれはいい。
これが意味するところは Gralloc も binderized で別プロセスに追い出されたということである。マジで?とおもったけど Systrace を睨むとそれっぽいプロセスがいるのだよな実際。無駄にかっこいいなおい・・・。Image の確保開放、微妙に遅いと思っていたがこのせいという面は否めない。
Treble, 資料を眺めると色々思わぬことが書いてある。たとえば above HAL の binder とは別の "binder context" を使って congestion を回避しているという。そしてそのためにカーネルもちょっとかわっている。Systrace で "HwBinder" というトレースがところどころにあるのはなんだろうとおもっていたけれど、それが別コンテクストで動く HAL 用の binder なのだろう。
更に HAL の Binder は binder といいつつ IDL は AIDL variant の HIDL というフォーマットで、AIDL と違い C++ もサポートしている、というか C++ がメインらしい。君たちは IDL コンパイラ二種類サポートしてくのか。それより AIDL 直してくれや・・・。
ところで Gralloc の話にもどると、このひと HAL とはいえ結局中では何をしているのだろう。というと、多くの場合は ION に落ちるらしい。例:
ION は Android がドライバ実装のため Linux に入れた shared memory の仕組み。アプリのレイヤで使う ashmen とは違い、たとえば物理メモリ上で連続した領域を確保したい、みたいなことができるという。LWN にいくつか解説がある。
- The Android ION memory allocator [LWN.net]
- Integrating the ION memory allocator [LWN.net]
- linux/drivers/staging/android/ion at master · torvalds/linux コード、は割と小さい。
ION があるならもう Gralloc は HAL じゃなくて AOSP 側で持ち、そのレイヤから直に ION に行けばいいのでは・・・という気もするけれど、Gralloc は最初の頃からあるのに対し ION は GB あたりで入ったらしいので歴史的経緯なのかもしれない。あと上でリンクした Exynos のコードをみると実装固有のフラグを Gralloc のレイヤから ION の下のデバイス固有コードに渡すようなことをしているので、Gralloc のレイヤにフックがあるのに意味はある・・・ような気もするが、基本的には Gralloc の usecase を伝えているだけなのでそれが ION に入ってればよくね?とも思う。どうせ Android 用なわけだから。あとだしの感想ですが。
ION は複数種類のヒープをサポートしている(ion.h). Linux のカーネルが普通に管理している (物理的には page にわかれている) メモリからアロケートする SYSTEM ヒープ、カーネルの起動時に reserve しておく CARVEOUT ヒープ (物理メモリは自動的に continuous になる)、そして DMA ヒープがある。
CARVEOUT はお前は昔のゲーム機か、というかんじでゲンナリするけどまあそういうの必要なこともあるでしょう。 (共存している co-processor を動かす別の OS と連携するとか。) 感心したのは DMA ヒープで、こいつは Continuous Memory Allocator 略して CMA からメモリを確保する。
- A deep dive into CMA [LWN.net]
- Fixing the contiguous memory allocator [LWN.net]
- A reworked contiguous memory allocator [LWN.net]
- The Contiguous Memory Allocator [LWN.net] <- これはパッチへのリンクで、説明が地番丁寧
CMA は名前の通り continuous な物理メモリを確保できるのだが、CARVEOUT のような雑なことはせずカーネルがもっているメモリから必要に応じてアロケートできる。正しい。しかし誰得なのだろうなと思ったら、パッチを書いていたのは Samsung の人だった。エライ。Samsung, 伊達に Android 界の頂点に立ってないなと見直した。
そしてこういうヘンなやつらもちゃんと仮想メモリにマップしないといけない Linux の VMM は大変だね。
ところで Gralloc がメモリを ION から確保するということは、そいつらは userland から普通に map できるということである。つまり GPU に渡すメモリを CPU から触れるのでは? SGI unified memory architecture なのでは? とおもったら O から NDK に AHarewareBuffer という API がたされており、これがまさにそういうクラスっぽい。(そして古いバージョンでもplatform の中のコードを無理やり触っている人たちがいたらしい) べんり! まあ CPU 遅いのでできることそんなになさそうだけど。
なお ION は雑すぎて脆弱だよと主張する ION Hazard という論文がある。Android PoV から ION を理解するのにはこの中の説明が一番わかりやすくてよかった。