ErlangにはHiPE(High Performance Erlang)というしかけがあって、 beam(erlangのためのvm)からネイティブコードを呼びだすよう変換することができる(hipeに関するスライド)。
FreeBSDでもx86だとhipeを有効にしてビルドする(FreeBSD-cvs:ports/lang/erlang/)ので、 OpenBSDでも動かないとおかしいわな、というわけで、otp-R11B-1をいじってみた。
まあ結果としては動いたのだが、別の問題が発覚したのでメモ。
さて、Erlangでhipeを有効にするには./configureに--enable-hipeを追加するだけでよろしい。OpenBSD-cvs:ports/lang/erlang/Makefileを見て、
./configure --disable-jinterface --disable-odbc --enable-threads --enable-kernel-poll --enable-hipe
このような感じか。
で、そのままだと、erts/emulator/hipe/hipe_x86_signal.cでこける。 ざっとコードを見たところ、OpenBSD-man:sigaltstackをdlsymして自前のsigaltstackでラップしているらしいことがわかる。
以前のエントリ(OpenBSD/2006/07/27/dlopen)を踏まえて、 このようなパッチを書いてみた: files:openbsd/otp_src_R11B-1-patch-erts_emulator_hipe_hipe_x86_signal.c
で、上のパッチを書いているときに気が付いたのだが、hipe_x86_signal.cから切り出した部分からのテストコード、
$ cat sigstack.c #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <pthread.h> /* * Set alternate signal stack for the invoking thread. */ static void set_sigaltstack(void *ss_sp) { struct sigaltstack ss; ss.ss_sp = ss_sp; ss.ss_flags = SS_ONSTACK; ss.ss_size = SIGSTKSZ; if (sigaltstack(&ss, NULL) < 0) { /* might be a broken pre-2.4 Linux kernel, try harder */ ss.ss_flags = 0; if (sigaltstack(&ss, NULL) < 0) { perror("sigaltstack"); abort(); } } } main() { static unsigned long my_sigstack[SIGSTKSZ/sizeof(long)]; set_sigaltstack(my_sigstack); }
が、-pthread付きでビルドしたときと、無しのときとで挙動が異なる。
$ cc sigstack.c $ ./a.out $
$ cc sigstack.c -pthread $ ./a.out sigaltstack: Invalid argument $
結局のところ、 OpenBSD-cvs:src/lib/libpthread/uthread/uthread_sigaltstack.c 33行目はどうみても、
if (ss == NULL) {
の間違いです。本当にありがとうございました。 本当にコードレビューしているのか怪しいものである。
ということでlibpthreadを再構築して、Erlangをビルド。
$ erl Erlang (BEAM) emulator version 5.5.1 [source] [async-threads:0] [hipe] [kernel-poll:false] Eshell V5.5.1 (abort with ^G) 1>
hipeが有効になった。 ちなみにhipe付きのbeamコードは、
$ erlc +native file
とするか、erl上で、
> c(module, [native, {hipe, ['O3']}]).
とすればよい。めでたしめでたし。
blog comments powered by Disqus