google-code-prettify

ラベル pthreads の投稿を表示しています。 すべての投稿を表示
ラベル pthreads の投稿を表示しています。 すべての投稿を表示

2010-01-02

pthreadのbacktraceでの不思議な現象

Debian lennyのgdbでbacktraceが正しく表示されないことがある。

うーむ。さっぱり原因が分からない。
どなたか分かる方、教えてください。

以下、再現させるためのプログラム。
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>


static void *print_thread(void *arg)
{
for (;;) {
printf("print thread\n");
}
}

int main(void)
{
pthread_t th;

pthread_create(&th, 0, print_thread, 0);


for (;;) {
printf("main\n");
}

return 0;
}

このプログラムをgdbで実行すると、"main\n"と"print thread\n"が表示される.
途中でCtrl-Cでプログラムを停止させてbacktraceを表示すると、stackが正しく表示されない。
(gdb) thr 1
[Switching to thread 1 (Thread 0xb7e576b0 (LWP 12994))]#0 0xb7fdc424 in __kernel_vsyscall ()
(gdb) bt
#0 0xb7fdc424 in __kernel_vsyscall ()
#1 0xb7f46b53 in ?? () from /lib/i686/cmov/libc.so.6
#2 0xb7eb87b3 in ?? () from /lib/i686/cmov/libc.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb) thr 2
[Switching to thread 2 (Thread 0xb7e56b90 (LWP 12997))]#0 0xb7fdc424 in __kernel_vsyscall ()
(gdb) bt
#0 0xb7fdc424 in __kernel_vsyscall ()
#1 0xb7f2828b in write () from /lib/i686/cmov/libc.so.6
#2 0xb7ec1d6c in _IO_file_write () from /lib/i686/cmov/libc.so.6
#3 0xb7ec2ee7 in _IO_do_write () from /lib/i686/cmov/libc.so.6
#4 0xb7ec2895 in _IO_file_overflow () from /lib/i686/cmov/libc.so.6
#5 0xb7ec5713 in __overflow () from /lib/i686/cmov/libc.so.6
#6 0xb7eb8746 in puts () from /lib/i686/cmov/libc.so.6
#7 0x08048456 in print_thread (arg=0x0) at a.c:12
#8 0xb7fb94c0 in start_thread () from /lib/i686/cmov/libpthread.so.0
#9 0xb7f386de in clone () from /lib/i686/cmov/libc.so.6

thread 1のbacktraceが、corruptと表示される。

2009-03-27

debian etchでpthreadのデバッグができない

debian etchでpthreadを使ったプログラムのデバッグをしようとしているが、うまくいかない。
同じくetchの別のPCだと動くのだが…。

gdbでプログラムをロードすると、
gdb: Failed to read a valid object file image from memory
と出る。
これは、kernelのバグのようで、kernelをetchnhalfの2.6.24にする事で解決。

ちなみに、etch-n-halfとは、「etch使っているけど、xxxだけ新しいの使いたいよ」という人のための追加パッケージ。

次は、
thread_db_get_info: cannot get thread info: generic error
が出て、これが解決できない。

別のetch PCで問題なく動作しているのも謎。

2008-12-26

スレッドを確実にsuspendする

Solarisのスレッドには、thr_suspend()という関数がある。この関数は、
他のスレッドをsuspendし、thr_suspend()からリターンした時には、ターゲットとなるスレッドが停止している事が保証されている。
という関数である。

pthreadでスレッドAから別のスレッドBをsuspendするには、
pthread_kill(B, SIGSTOP)
を使えば良いのだが、pthread_killからリターンした時点では、スレッドBは停止していない可能性がある。

pthreadでthr_suspend()と同じ機能を実現しようと思ったら、以下のようにすると良い。

1. スレッドBのSIGUSR1のシグナルハンドラを登録しておく。
2. スレッドAは、pthread_kill(B, SIGUSR1)をする。
3. スレッドAは、sem_wait()でセマフォ待ちをする。
4. スレッドBのSIGUSR1のシグナルハンドラで、sem_post()して、スレッドAを起こす。

ポイントは、4。
シグナルハンドラからは非同期シグナルセーフ関数しか呼んではいけないが、sem_post()は非同期シグナルセーフ関数なので、スレッド間の同期を取るのに使う事ができる。

参考:

2008-10-28

私のPthreadsの勉強方法

私がPthreadsを勉強した方法。この方法で、Pthreadsの初級者レベルは脱したと思う。

1. man ptheradを読む。
どんなAPIがあるのかを理解する。自分でthreadを作ったり、condとmutexを使ってみる。

2. POSIX Threads: Semi-FAQを読む。
わからない所はmanで調べる。

3. pthreads本を読む。

説明がまわりくどいが、役立つ情報がいろいろ書いてある。(特に後半)

4. pthreadsライブラリの実装を見る
私の場合は、NetBSDのsrc/lib/libpthreadのソースを読んだ。
NetBSDのpthreadのソースは読みやすかったが、Linuxのpthreadsのソースも読みやすいかはわからない。

あと役に立ちそうなサイト。
memologue
sig.txt

2008-10-22

ITRONのAPIは初心者に優しく、pthreadsのAPIは上級者に優しい

スレッド間(ITRONの用語では、タスク間)の通信を行う場合のITRONのAPIとpthreadsのAPIを比べると、
・ITRONの通信APIは、初心者に優しい
・pthreadsの通信APIは、上級者に優しい
と思う。

■ITRONとptheadsにはどんなAPIがあるか

ITRONのAPIには、多数の通信用の関数が用意されている。
・wai_sem()/sig_sem()
・set_flg()/wai_flg()
・snd_dtq()/rcv_dtq()
・snd_mbx()/rcv_mbx()
ITRONの拡張APIも含めると、
・loc_mtx()/unl_mtx()
・snd_mbf()/rcv_mbf()
・cal_por()/acp_por()

多数のAPIが用意されているため、ユーザーは用途に合ったAPIを選んで使う事になる。


一方、pthreadsでスレッド間の通信を行う場合、基本的には以下の4つのAPIを使う事になる。
・pthread_mutex_lock()/pthread_mutex_unlock()
・pthread_cond_signal()/pthread_cond_wait()
これらのAPIを使って、所望の通信機能を自分で作成する事になる。
例えばセマフォが欲しければ、これらの4つのAPIを使ってセマフォを実装する事になる。


■独自の通信APIを自分で実装できるかどうか

ITRONの場合は、自分で独自の通信APIを実装しようとした時に、かなり難しい事に気付く。
それは、
・ロックを解除する
・待ちに入る
を同時に(atomicに)実現する手段が、ITRONには用意されていないからだ。

ロックをしつつ、待ちに入る事ができないので、ITRONでは待ちに入る前には必ずロックを解除しなくてはならない。
wai_sem(lock_sem);
...
sig_sem(lock_sem);
/* ここで、他のスレッドにここで割り込まれるかも */
wai_sem(sleep_sem);

ロックの解除から待ちに入る間に他のスレッドにスイッチしてしまう可能性があるため、正しく動作するコードが書くのが非常に難しい。

逆に言うと、ITRONでは独自の通信APIを実装するのが難しいからこそ、多数の通信APIが最初から用意されているという見方もできる。


一方、pthradsのpthread_cond_wait()では、mutexのアンロックと待ちに入る事を同時に実現できる。
これにより、pthreadsでは独自の通信APIを作るのが非常に簡単である。

■結論

ITRONの通信APIは、多数の通信APIが最初から用意されているので、用途に合ったAPIが既にある場合には非常に楽。
一方、用途に合うAPIが無い場合は、非常に苦労する。

pthreadsの通信APIは、APIが少ないため、セマフォのような簡単に物でも自分で作らなくてはならない。
しかし、どんな通信APIでも実装が可能であるため、上級者にはこちらの方が使いやすい。

2008-10-21

NetBSD4/currentのgdbで、info threadsが動作しない

NetBSD4とcurrentの、gdbでのpthreadサポートが動作しないようだ。

以下のプログラムをコンパイルする。
#include <stdio.h>
#include <pthread.h>

void *func(void *arg)
{
printf("hello\n");

sleep(10);
return 0;
}

int main(void)
{
pthread_t th;

pthread_create(&th, 0, func, 0);

pthread_join(th, 0);

return 0;
}
gdbでinfo threadsとしても、何も出力されない。
(gdb) run
Starting program: /home/sakurai/tmp/pth/a.out
hello
^Z
Program received signal SIGTSTP, Stopped (user).
0xbbb17667 in sa_yield () from /usr/lib/libc.so.12
(gdb) info threads
(gdb)

いくつかPRが出ているが、まだ修正されていない様子。
PR34194
PR35540
PR35657(これはclosed)