avr-libcにおけるATOMIC_BLOCK
avr-libc の中に <util/atomic.h> というものがある。僕の最初の反応は「AVRはシングルコアのはずなのに、なぜatomicが必要なんだ?」というものだった。そこで思わずドキュメントを確認してみた。
The macros in this header file deal with code blocks that are guaranteed to be excuted Atomically or Non-Atmomically. The term “Atomic” in this context refers to the unability of the respective code to be interrupted.
マイクロコントローラであっても様々な割り込み(interrupt)が存在するため、コードの実行が途中で中断される可能性がある。atomicを使うことで、中に囲まれたコードブロックが割り込みの影響を受けない(一時的に割り込みを無効化する)ことを保証できる。
ATOMIC_BLOCK(ATOMIC_FORCEON) {
// do something critical
}
感覚的には cli() と sei() の組み合わせのように見えるが、ドキュメントの説明によると他にも色々と行っているようだ。内部の実装は以下のようになっている:
#define ATOMIC_BLOCK(type) for ( type, __ToDo = __iCliRetVal(); \
__ToDo ; __ToDo = 0 )
type を引数として受け取ることができ、渡せる引数には ATOMIC_RESTORESTATE と ATOMIC_FORCEON がある。
#define ATOMIC_RESTORESTATE uint8_t sreg_save \
__attribute__((__cleanup__(__iRestore))) = SREG
見たところ sei のような効果だが、面白いのは __attribute__ の使い方だ。GCCでは、__attribute__ を使って変数や関数をどのように配置・管理するかを指定できる。この挙動は libc の実装で定義されており、例えばAVRではこのように書くことができる:
#include <avr/pgmspace.h>
const int my_var[2] PROGMEM = { 1, 2 };
ここでの PROGMEM は、実際には __attribute__ の1つだ:
#ifndef __ATTR_PROGMEM__
#define __ATTR_PROGMEM__ __attribute__((__progmem__))
#endif
通常、変数はメモリ(RAM)に格納されるが、マイクロコントローラではメモリが非常に少ないことが多い。しかし一般的なコンピュータとは異なり、マイクロコントローラのコードは通常、事前にコンパイルされてプログラムメモリ(フラッシュメモリ)に直接書き込まれる。コードの量がそれほど多くなければ、フラッシュメモリのほうに余裕が残ることが多い。そんな時、PROGMEM を使うことで変数をフラッシュメモリ内に配置し、メモリの消費量を抑えることができる。読み出し時には pgm_read_word を使って変数を読み出す。
話を ATOMIC_BLOCK に戻すと、これをすべて展開したコードは次のようになる:
for (uint8_t sreg_save __attribute__((__cleanup__(__iRestore))) = 0; __ToDo = __iCliRetVal(); __ToDo ; __ToDo = 0) {
// do something critical
}
これにより、コードの実行が割り込みの影響を絶対に受けないように保証している。for loop を使うこのアプローチはなかなか見事で、こんな応用ができるとは僕もまったく思いつかなかった。
関連記事
- 測定が目標になるとき:窓税からPull Request数まで かつて僕は小さなツールを自作し、四半期で自分がどれだけPRに貢献したか、レビューコメントをどれだけ残したか、チケットをどれだけ消化したかを集計して、上司にアウトプットを証明しようとしたことがある。上司は淡々と、評価はアウトプットだけで見るものではないと言った。数年後、僕はようやく理解した――測定が目標になるとき、それはもはや良い測定ではなくなるのだ。英国の窓税、ハノイのネズミ駆除の報奨金から、現代のPR数による開発者評価に至るまで、そのメカニズムはまったく同じだ。
- Cloudflare Images を画像ストレージ・変換ソリューションとして使う ウェブページに画像を1枚置くのはフロントエンドにとって最も簡単なことだが、リサイズや各種フォーマットの生成、さらにはトラフィックの負荷に耐えることまで完璧にやろうとすると、実際には一つの包括的なソリューションが必要になる。僕はその後、すべて Cloudflare Images に任せるようになり、オリジナル画像1枚だけを渡すようにしている。
- もう AWS Access Key を使うのはやめよう Access Key は AWS において見落とされがちなセキュリティリスクだ。OIDC と IAM Role を組み合わせることで、GitHub Actions にシークレットを一切保持させることなく、安全に AWS リソースを操作できるようにする。
- データベース主キー:AUTO_INCREMENT、UUID、そしてUUIDv7 バックエンド開発で度々直面する主キーの決定。auto incrementを使うべきか、それともUUIDか?衝突への懸念は?UUIDv7とcreated_at + インデックスの性能差はどれほどか?実際に2,000万件のデータで検証したベンチマークと設計上の意思決定を解説する。