ゲートキーパータスクを使用して共有リソースにアクセスする設計に取り組んでいます。私が今持っている基本的な設計は、ゲートキーパータスクが受信している単一のキューと、それに要求を入れる複数のタスクです。
これはメモリが制限されたシステムであり、FreeRTOS(Cortex M3ポート)を使用しています。
問題は次のとおりです。これらの要求を非同期的に処理するのはかなり簡単です。要求元のタスクは要求をキューに入れ、ビジネス、ポーリング、処理、または他のイベントの待機を行います。これらのリクエストを同期的に処理するには、リクエストが処理されると、ゲートキーパーがそのリクエストを呼び出したタスクをウェイクアップできるように、リクエストするタスクがブロックするメカニズムが必要です。
私が考えることができる最も簡単な設計は、各リクエストにセマフォを含めることですが、メモリの制限とFreeRTOSのセマフォのサイズがかなり大きいことを考えると、これは実用的ではありません。
私が思いついたのは、タスクの一時停止とタスクの再開機能を使用してタスクを手動でブロックし、要求が完了したときにタスクを再開できるゲートキーパーにハンドルを渡すことです。ただし、サスペンド/レジュームにはいくつかの問題があり、私はそれらを避けたいと思っています。1回の再開呼び出しは、他の呼び出しによって何度中断されてもタスクをウェイクアップし、これにより望ましくない動作が発生する可能性があります。
一時停止/再開方法を示すためのいくつかの単純な疑似C。
void gatekeeper_blocking_request(void)
{
put_request_in_queue(request);
task_suspend(this_task);
}
void gatekeeper_request_complete_callback(request)
{
task_resume(request->task);
}
当面使用する予定の回避策は、非同期呼び出しを使用し、各要求タスクに完全にブロッキングを実装することです。ゲートキーパーは、操作が完了すると、提供されたコールバックを実行します。その後、タスクのメインキューや特定のセマフォ、または必要なものにポストできます。リクエストのブロック呼び出しを行うことは本質的に便利な機能であるため、各リクエストタスクはこれを実装する必要はありません。
タスク固有のブロッキングを示すための疑似Cですが、これは各タスクに実装する必要があります。
void requesting_task(void)
{
while(1)
{
gatekeeper_async_request(callback);
pend_on_sempahore(sem);
}
}
void callback(request)
{
post_to_semaphore(sem);
}
おそらく最善の解決策は、ゲートキーパーとAPIにブロッキングを実装せず、各タスクにそれを処理させることです。ただし、これにより各タスクのフローが複雑になり、回避できると期待していました。ほとんどの場合、すべての呼び出しは、操作が終了するまでブロックする必要があります。
私が見逃しているいくつかの構造、または私がグーグルできるこのタイプの問題のより良い用語はありますか?私の検索では、このようなものは見つかりませんでした。
追記-ゲートキーパータスクの2つの理由:
大きなスタックスペースが必要です。この要件を各タスクに追加するのではなく、ゲートキーパーは、必要なすべてのメモリを備えた単一のスタックを持つことができます。
リソースはCPUで常にアクセスできるとは限りません。CPU内のタスクだけでなく、CPU外のタスクも同期しています。