借り初めのひみつきち

仮ブログです。

今週の MYOS

今週というタイトルなのに最後の更新何週間前だったっけ?という最近の MYOS 界隈のトピックです。

スケジューラキュー

一般にマルチタスク OS のスケジューラには実行待機中のスレッドを管理するためのキューがあります。 このキューは全てのプロセッサコアから同時に読み書きする可能性があるため非常に高度な排他制御が必要になります。

MYOS の開発初期に最も悩んだのもこのスケジューラキューの実装で、最終的に一旦自前実装を諦めて既存のわりと定評のあるらしい外部ライブラリを使うことにしました。 数ヶ月前はこれで安定して動いていたと思うのですが、最近また動作が怪しくなってきました。 しばらく動作しているとキューからデータを引き出す部分で止まって無限ループしているようです。

ロックフリーアルゴリズムというのはアトミック操作の組み合わせでデータを保証します。 当然書き込みもいくつかのアトミック操作の組み合わせを行いますが、稀にこれからデータを書き込む印をつけたまま実際の書き込みが終わる前にプリエンプションが実行され、スケジューラーが次に実行するスレッドを決めるためにキューを読み取る際に書き込み完了マークがつくまで待ち続ける、しかしそのスレッドはすでにプリエンプションされているので書き込みは永遠に完了しないという無限ループを発見しました。

キューの出し入れを割り込み禁止にすることで、キューに関するほとんどの問題は解決しました。

クリティカルな操作をするときは割り込みを禁止しましょう。

以前より安定してきたので自作のキューも使い始めてますが、やはりまだ時々止まってしまう現象を確認していて詳細不明です。

フォントレンダラと直線アルゴリズム

MYOS は現在 Hershey という簡易的なベクタフォントに対応しています。 このフォントは頂点のリストだけが提供されるので頂点の間に直線を描画するだけで簡単に利用できます。

ベクタフォントの常として、ある程度のサイズを下回るサイズで描画しようとするとあまり綺麗に描画できなくなります。 そこで今までの実装はサイズが倍のバッファに拡大描画した後で縮小して画面に描画していました。 しかし、フォントによってはあまり綺麗に描画できていませんでした。

これまで直線の描画はブレゼンハムと呼ばれる有名なアルゴリズムを利用していました。 ブレゼンハムのアルゴリズムは X が1増加するときに Y が 1 変化するかたまは変化しないのどちらかを判別して描画していくアルゴリズムで、高速に描画できる代わりに座標の変化が整数の近似値で丸められるので射線がガタガタに描画されます。

元々ガタガタの線を拡大縮小しても綺麗に描画できるはずがありません。そこで座標を小数で扱って射線も滑らかに描画できるアルゴリズムに変更しました。

以前より描画結果が良好になりました。

角丸ウィンドウ

MYOS は、その先祖となった moe の時代から角丸の矩形を描画する機能を持っていました。 そして、マウスカーソルのように矩形ではない図形を重ね合わせる機能も元々持っていました。 角丸ウィンドウを実現できそうな気がしますが、ひとつ問題がありました。影です。

MYOS のウィンドウの影は内部的にはウィンドウの矩形の周りに当たり判定のない半透明の枠線として描画する方法で実現していました。 処理が単純で高速ですが、この方法では矩形以外の影を描画できません。

そこでウィンドウ本体と別のビットマップを用意し、ウィンドウ本体のビットマップの透明度を基準にぼかしをかけて影を生成するように変更しました。

影の形が自由になったのでウィンドウの形を矩形に限定しなくても描画できるようになりました。

f:id:neriring16:20210711155418p:plain

ウィンドウの自由度が上がったので、角丸ついでにタイトルバーのデザインも少し変更してみました。

いかがでしたか?

これからも MYOS の活躍にご期待ください。