3

Linux、Xenomai、および RTAI の PREEMPT_RT パッチのベンチマークを論文で行うために、ExpressLogic からリアルタイムの Thread_Metric を POSIX に移植しようとしています。これらは、ベンチマークが機能するために実装する必要がある次の関数を含む C ソース ファイルを提供します。

void   tm_initialize(void (*test_initialization_function)(void));
int    tm_thread_create(int thread_id, int priority, void (*entry_function)(void));
int    tm_thread_resume(int thread_id);
int    tm_thread_suspend(int thread_id);
void   tm_thread_relinquish(void);
void   tm_thread_sleep(int seconds);
int    tm_queue_create(int queue_id);
int    tm_queue_send(int queue_id, unsigned long *message_ptr);
int    tm_queue_receive(int queue_id, unsigned long *message_ptr);
int    tm_semaphore_create(int semaphore_id);
int    tm_semaphore_get(int semaphore_id);
int    tm_semaphore_put(int semaphore_id);
int    tm_memory_pool_create(int pool_id);
int    tm_memory_pool_allocate(int pool_id, unsigned char **memory_ptr);
int    tm_memory_pool_deallocate(int pool_id, unsigned char *memory_ptr);

現在、pthread を入力として受け取る tm_thread_suspend および tm_thread_resume 関数を実装しようとしています。pthread_mutex_lock および pthread_cond_wait ルーチンを使用して pthread を一時停止できることは知っていますが、これらはスレッドの start_function から呼び出す必要があります。私はこの種のものに不慣れで、頭を悩ませています。どんな助けでも大歓迎です。

4

4 に答える 4

3

pthread_suspendそれが利用可能であれば、本当に行く方法のようです。このソリューションは、価値があるよりも汚れている可能性があります。スレッドごとにsemaphore. 各スレッドがシグナルをリッスンするようにします。シグナル ハンドラーdownでは、関連するセマフォに対して単純に a を実行します。

したがってstop、スレッドが必要な場合は、シグナルを送信するだけで (おそらくリアルタイムシグナルを使用するのが最適です)、ハンドラーで停止します。デフォルトでは、ハンドラーは自身をマスクします (つまり、処理が完了する前に同じシグナルを受信して​​も、再度呼び出されることはありません)。スレッドを再開したい場合はup、セマフォで単に実行します。

警告:

  • @bmarguliesが提案したものを使用してください。できれば、より良い(より安全で、よりクリーンで、より効率的です)
  • セマフォの代わりにミューテックスを使用することもできます
  • 信号を扱うのは厄介な仕事です。乗船する前に、必ず(再)読んでください
    • 非同期信号の安全性
    • スレッドとシグナル
    • システムコールの中断と再開 ( SA_RESTART)
  • async-signal は安全ではないと確信していますが、使用しないsem_wait(3)限り安全です(理由がないわけではありません)。SA_NODEFER

残念ながら、これに関する素晴らしい無料のドキュメントは見つかりません。それでも、優れているかどうかにかかわらず、無料のドキュメントがたくさんあります。

編集

@R ..で提案されているasync-signal-safeように、( unsafe の代わりに)使用できるブロック機能がありますsem_wait安全に使用できる関数のリストを次に示します。

于 2011-04-20T22:27:56.447 に答える
1

pthreadの一部の実装には、これらの関数があります。http://www.unix.com/man-page/all/3t/pthread_suspend/ただし、Linuxカーネルはそれらをサポートしていない可能性があります。

于 2011-04-20T22:03:17.180 に答える
1

次の2つの信号を使用して、これを完全に移植可能に行うことができます(async-signal-unsafe関数に関するすべての問題を回避します)。

「スレッドサスペンド」シグナルハンドラーはpselect、2番目のシグナルのブロックをアトミックに解除し、無期限にスリープするために使用します。2番目のシグナルはを終了しpselect、シグナルハンドラーを返します。

また、非同期信号セーフインターフェイスを使用するソリューションは他にもたくさんあります。基本的には、ユーザースペースの同期プリミティブではなく、ファイル記述子を処理してブロックするものです。たとえばread、パイプからシグナルハンドラーを取得し、パイプに1バイトを書き込んでスレッドを再開すると、機能します。

于 2011-04-20T22:54:17.470 に答える
0

これを行う方法は、sigwait() と pthread_kill を使用することです。

// グローバル変数

int _fSigSet; 

pthread_create を呼び出す前に、シグナル マスクを設定します。すべてのスレッドがマスクを継承します。私が推測するスレッド関数でマスクを設定できます。使用するコードは次のとおりです。

sigemptyset(&_fSigSet);
sigaddset(&_fSigSet, SIGUSR1);
sigaddset(&_fSigSet, SIGSEGV);
pthread_sigmask(SIG_BLOCK, &_fSigSet, NULL);
... 
pthread_create(&Thread, NULL, ThreadProc, NULL);
...

中断する:

int nSig;  // signal you get if you care.
sigwait(&_fSigSet, &nSig);  // thread is suspended here waiting for signal.

再開します:

pthread_kill(&Thread, SIGUSR1);

何らかの理由で SIGUSR1 を使用できない場合は、すべてのシグナルが機能するわけではないことに注意してください。何か間違ったことをしているかもしれませんが、SIGCONT は機能しません。

この方法でスレッドを一時停止するベンチマークを行ったところ、この方法はミューテックスと条件変数を使用するよりも 5 倍高速でした。

この手法を使用したコードを次に示します。

于 2011-04-25T23:41:29.177 に答える