WasmLinux: futex(2)の引数個数問題
futex(2)のsyscallは6引数だけど、Muslの用法は4引数や5引数が混ざっている。
うーん。。ゼロを補完するように呼出す方が良いのか。。?
とりあえず libc のレベルで吸収
libcのsyscall関数内で補完するようにしたら正常に呼出されるようになった。これ最適化で消えるからどうでも良いとは言え全パターン網羅しないといけないのは地味にキツいな。。
nanosleep(3)で逆の問題が起こる
カーネルは4引数、
一方Muslは キャンセルポイントでは全てのsyscallを6引数で呼ぶ 。
... これはMusl側をヘビーにパッチするしか無いやもしれんな。。
引数カウントマップを作る
一旦ランタイム側で置き換える方針にする。
Linuxソースのtopで:
$ git grep ^__SYSCALL > maptbl.txt
$ git grep ^SYSCALL_DEFINE > mapargs.txt
これで SYSCALL_DEFINE0
〜 SYSCALL_DEFINE6
と __SYSCALL
マクロが集まり、 適当に処理すれば
-
sys_*
関数とsyscall番号の対応 - 個々の
sys_*
関数の引数カウント
の対応表ができる。あとはランタイム側で表を引いて引数カウントを置き換えれば、一応 O(1) でsyscallを行える。はず。将来的にはもうちょっと真面目にやりたいところ。。
定義重複の処理
とりあえず syscall番号 → カーネル内のシンボルのマッピングを作る。
-- Already defined clone kernel/fork.c vs kernel/fork.c
-- Already defined clone kernel/fork.c vs kernel/fork.c
-- Already defined clone kernel/fork.c vs kernel/fork.c
-- Already defined sigsuspend kernel/signal.c vs kernel/signal.c
-- Already defined clock_settime kernel/time/posix-stubs.c vs kernel/time/posix-timers.c
-- Already defined clock_gettime kernel/time/posix-stubs.c vs kernel/time/posix-timers.c
-- Already defined clock_getres kernel/time/posix-stubs.c vs kernel/time/posix-timers.c
-- Already defined clock_settime32 kernel/time/posix-stubs.c vs kernel/time/posix-timers.c
-- Already defined clock_gettime32 kernel/time/posix-stubs.c vs kernel/time/posix-timers.c
-- Already defined clock_getres_time32 kernel/time/posix-stubs.c vs kernel/time/posix-timers.c
-- Already defined clock_nanosleep kernel/time/posix-stubs.c vs kernel/time/posix-timers.c
-- Already defined clock_nanosleep_time32 kernel/time/posix-stubs.c vs kernel/time/posix-timers.c
-- Already defined brk mm/mmap.c vs mm/nommu.c
-- Already defined mmap_pgoff mm/mmap.c vs mm/nommu.c
-- Already defined old_mmap mm/mmap.c vs mm/nommu.c
-- Already defined munmap mm/mmap.c vs mm/nommu.c
-- Already defined mremap mm/mremap.c vs mm/nommu.c
clone
は要らないので消すで良いな。 sigsuspend
はそもそもLinux側の定義がバグってると思う。まぁ CONFIG_OLD_SIGSUSPEND
なんて誰も使わないんでは。。
kernel/time/posix-stubs.c
の方は消してしまって良い。 mm/mmap.c
と mm/mremap.c
の方も、LKLはnommuなので不要だな。
手動導出が必要なもの
-- Unknown nr: __NR_io_getevents
-- Unknown nr: __NR3264_lseek
-- Unknown nr: __NR3264_fstatat
-- Unknown nr: __NR3264_fstat
-- Unknown nr: __NR_nanosleep
-- Unknown nr: __NR_timer_gettime
-- Unknown nr: __NR_timer_settime
-- Unknown nr: __NR_adjtimex
-- Unknown nr: __NR3264_mmap
-- Unknown nr: __NR_arch_specific_syscall
... 結構多いな。。引数カウントが64bits/32bits共通なので、特に考えずにハードコードしてしまう。
-
__NR_io_getevents
=> 5 -
__NR3264_lseek
=> 3 -
__NR3264_fstatat
=> 4 -
__NR3264_fstat
=> 2 -
__NR_nanosleep
=> 2 -
__NR_timer_gettime
=> 2 -
__NR_timer_settime
=> 4 -
__NR_adjtimex
=> 1 -
__NR3264_mmap
=> 1
__NR_arch_specific_syscall
は多分存在しないから無視で良いんじゃないかな。。
まだあった
一旦ここまででだいぶ良い感じに埋まったけど、まだ有った。
SYSCALL_ARGC(__NR_lookup_dcookie, )
SYSCALL_ARGC(__NR_nfsservctl, )
SYSCALL_ARGC(__NR_vhangup, )
SYSCALL_ARGC(__NR_sync, )
SYSCALL_ARGC(__NR_sched_yield, )
SYSCALL_ARGC(__NR_restart_syscall, )
SYSCALL_ARGC(__NR_setsid, )
SYSCALL_ARGC(__NR_getpid, )
SYSCALL_ARGC(__NR_getppid, )
SYSCALL_ARGC(__NR_getuid, )
SYSCALL_ARGC(__NR_geteuid, )
SYSCALL_ARGC(__NR_getgid, )
SYSCALL_ARGC(__NR_getegid, )
SYSCALL_ARGC(__NR_gettid, )
SYSCALL_ARGC(__NR_clone, )
SYSCALL_ARGC(__NR_munlockall, )
SYSCALL_ARGC(__NR_remap_file_pages, )
とりあえず分類しておく。
たぶんスクリプトの不具合で正常に取れてないもの:
SYSCALL_ARGC(__NR_lookup_dcookie, 3)
SYSCALL_ARGC(__NR_vhangup, 0)
SYSCALL_ARGC(__NR_sync, 0)
SYSCALL_ARGC(__NR_sched_yield, 0)
SYSCALL_ARGC(__NR_restart_syscall, 0)
SYSCALL_ARGC(__NR_setsid, 0)
SYSCALL_ARGC(__NR_getpid, 0)
SYSCALL_ARGC(__NR_getppid, 0)
SYSCALL_ARGC(__NR_getuid, 0)
SYSCALL_ARGC(__NR_geteuid, 0)
SYSCALL_ARGC(__NR_getgid, 0)
SYSCALL_ARGC(__NR_getegid, 0)
SYSCALL_ARGC(__NR_gettid, 0)
たぶん要らないsyscall:
SYSCALL_ARGC(__NR_nfsservctl, -1)
SYSCALL_ARGC(__NR_clone, -1)
SYSCALL_ARGC(__NR_munlockall, -1)
SYSCALL_ARGC(__NR_remap_file_pages, -1)
うまく行った
とりあえず sleep(1)
が正常に実行できるようになった。