@date Tue,05 Dec,2006 - Sun,10 Dec,2006 @date Sat,30 Dec,2006 - Tue,09 Jan,2007 @author Copyright(C)2006-2007 G-HAL. All rights reserved. FreeBSD 5 までは HZ=100 (kern.clockrate hz = 100)。 FreeBSD 6 からは HZ=1000 (kern.clockrate hz = 1000)。 OpenBSD は HZ=100 (kern.clockrate hz = 100)。 BSD系で HZ がいくつになっているかは、 sysctl -a | grep kern.clockrate で判る。 Linux 2.6.0 より前は HZ=100。 Linux 2.6.0 から 2.6.12 は HZ=1000。 Linux 2.6.13 からは HZ=250。 Vine 4.0 は Linux 2.6.16 だが、独自パッチで HZ=100 らしい。 Linux系は .config の CONFIG_HZ で設定するらしい。 Linux系の HZ がいくつになっているかは、 /usr/include/asm/param.h を見ないと判らないらしい。 sched_setscheduler() と sched_rr_get_interval() は、 root 権限でしか実行できない。 FreeBSD 4系列の sched_getparam() は、 ソフトリアルタイムスケジューリングポリシー時以外は、 返値が不定になっていて、 getpriority() を使わないと現レベルを取得できない。 FreeBSD4系や OpenBSD40R では、sigprocmask() で SIG_BLOCK しても、 sigwait() 外では普通にシグナルが配信されてしまった(泣。 SIG_IGN すればブロックできる、が、sigwait() が無視される。 SIG_DFL すればアンブロックできる。 でも、 signal(,SIG_DFL) sigwait() signal(,SIG_IGN) とかすると、そのすきまでシグナルが来た時に、やっぱり落ちる。 SIG_UNBLOCK でダミーのハンドラを登録したまま sigwait() してやると、 sigwait() 外ではダミーハンドラへ飛び、 sigwait() 内では sigwait() 処理した。 POSIX の規格では、sigaction() と sigwait() の同時使用は未定義。 SunOS 5.8 Solaris8 では、 そもそも SIGALRM の sigwait() すると必ず Alarm clock だして落ちた(泣。 他のシグナルなら平気。 sigaction() しても、sigwait() 中では SIGALRM 以外の全シグナルをブロックした。 POSIX の規格では、sigaction() と sigwait() の同時使用は未定義。 sched_rr_get_interval() は FreeBSD 4 では 0.100[sec] だった。 FreeBSD 4系や、通常の GNU/Linux系の一般のスケジューリングポリシーで、 sleep系を実行すると、シグナルが無い限り、 最短でも HZ*2 は眠ったままだった。 FreeBSD 4系では SCHED_FIFO でも HZ*2 眠ったままだった。 GNU/Linux系でソフトリアルタイムポリシーにした時や、 一般のスケジューリングポリシーでも adeos nano kernel なら、 HZ 1回で起床した。 GNU/Linux adeos nano kernel では、 itimer の値と、実際の周期がずれる。 指定値 周期 9.997[ms] 9.889[ms]〜10.074[ms] 9.999[ms] 10.929[ms]〜11.076[ms] 19.996[ms] 19.935[ms]〜20.056[ms] 19.998[ms] 20.948[ms]〜21.034[ms] 199.969[ms] 199.97[ms]〜199.98[ms] 199.971[ms] 200.97[ms]〜200.98[ms] 1999.695[ms] 1999.5[ms]〜1999.8[ms] 1999.696[ms] 2000.5[ms]〜2000.8[ms] プライオリティパラメータの値域が、OS毎にばらばらで、 値域を取得する方法さえないのは、なんとかしてくれ。 POSIX 定義では、シグナルは、 プロセス内のどれか1つ適切なスレッドに配信される。 sigsuspend(), sigwait() していないシグナルの場合は、 マスクしていないスレッドのどれに配信されるかは未定義。 SIGINT(2) を奪うと ^C が効かなくなる。 BSD系の場合、SIGTSTP(18) の処理を奪うと ^Z が効かなくなる。 GNU/Linux系の場合、SIGCHLD(20) をマスクすると ^Z が効かなくなる。 Solarisの場合、SIGTSTP(24) をマスクすると ^Z が効かなくなる。 FreeBSD4 シグナルのマスクは、殆ど無視される。 sigaction() と sigsuspend() を同時使用した場合、 シグナルハンドラへ飛んでから sigsuspend() が返る。 sigaction() と sigwait() を同時使用した場合、 シグナルハンドラへ飛ばずに sigwait() が返る。 pthread_cancel() はシグナルマスクではマスクしない。 シグナルをマスクしていないスレッドが複数有った場合、 適当に選んで1つのスレッドに配信される。 sigaction(), setitimer(), sigsuspend() を使用した場合、 sigaction() や setitimer() したスレッドに関わりなく、 sigsuspend() したスレッドがシグナルハンドラ処理を行うらしい。 sigsuspend(), sigwait() の待ちに一致するシグナルなら、 待ちスレッド以外にシグナルをマスクしていないスレッドが有っても、 待ちスレッドにしか配信されない。 複数 sigsuspend(), sigwait() し、 且つ受信対象シグナルが重複している場合、 先に待ちに入った方が取る(取得するスレッドが順繰りに回る)。 OpenBSD シグナルのマスクは、殆ど無視される。 sigaction() と sigsuspend() を同時使用した場合、 シグナルハンドラへ飛んでから sigsuspend() が返る。 sigaction() と sigwait() を同時使用した場合、 シグナルハンドラへ飛ばずに sigwait() が返る。 pthread_cancel() はシグナルマスクではマスクしない。 シグナルをマスクしていないスレッドが複数有った場合、 マスクしていない全てのスレッドに配信される。 sigaction(), setitimer(), sigsuspend() を使用した場合、 sigaction() や setitimer() したスレッドに関わりなく、 最後に sigsuspend() したスレッドがシグナルハンドラ処理を行うらしい。 sigsuspend(), sigwait() の待ちに一致するシグナルでも、 待ちスレッド以外にシグナルをマスクしていないスレッドが有った場合、 マスクしていない全てのスレッドに配信される。 複数 sigsuspend(), sigwait() し、 且つ受信対象シグナルが重複している場合、 全てのスレッドに配信される。 GNU/Linux libc6 シグナルのマスクは、強力に効く。 sigaction() と sigsuspend() を同時使用した場合、 シグナルハンドラへ飛んでから sigsuspend() が返る。 sigaction() と sigwait() を同時使用した場合、 シグナルハンドラへ飛ばずに sigwait() が返る。 sigsuspend() の場合、SIGRTMIN+1 をマスクすると、 pthread_cancel() もマスクしてしまう。 シェル(キーボード)から送られたシグナルは、 親スレッドに送られ、親でマスクしていれば、そこで消える。 親でマスクしていなければ、 マスクしていない全子スレッドに配信される。 kill/killall から送られたシグナルは、 送られたスレッド≒プロセスだけに送られる、 マスクには関係なく、子スレッドには配信されない。 SIGALRM は setitimer() したスレッド≒プロセスにしか配信されない、 他スレッドのマスクは一切関係しない、 POSIX定義で「同一プロセス内」であっても、 GNU/Linux定義で「別スレッド」であれば、配信されない。 でも、親スレッドだろうが他スレッドだろうが、 sigaction() は全スレッドに引き継がれるらしい。 SunOS5.8 Solaris8 シグナルのマスクは、強力に効く。 sigaction() と sigsuspend() を同時使用した場合、 シグナルハンドラへ飛んでから sigsuspend() が返る。 sigaction() と sigwait() を同時使用した場合、 シグナルが無視され何も起きない。 sigsuspend() の場合、SIGCANCEL をマスクすると、 pthread_cancel() もマスクしてしまう。 シグナルをマスクしていないスレッドが複数有った場合、 適当に選んで1つのスレッドに配信される?。 SIGALRM は setitimer() したスレッドが シグナルハンドラ処理を行っている様に見える……、 sigsuspend(), sigwait() しているスレッドが有っても、 setitimer() したスレッドにしか配信されていない……、 setitimer() したスレッドが消えると、適当に選ぶらしい。 それ以外は、受信対象シグナルが一致する sigsuspend(), sigwait() の中で、 先に sigsuspend(), sigwait() した方が シグナルハンドラ処理を行っている様に見える。 複数 sigsuspend(), sigwait() し、 且つ受信対象シグナルが重複している場合、 なんでか知らんが、同じスレッドしか受信していない。 SIGALRM の sigwait() すると必ず Alarm clock だして落ちた(泣。 他のシグナルなら平気。