カテゴリ: プログラミング

完全に自分用メモ


robocopy src dst /MIR /R:0 /W:0 /LOG:logfile.txt /NDL /TEE /XJD /XJF /DCOPY:T

/MIR
バックアップ元とバックアップ先をミラーリングします。
/R:0
ファイルコピーに失敗した場合に再度コピーを試す回数です。
/W:0
再試行する時の待ち時間(秒)です。
/LOG:
ログファイル名
/NP
バックアップ中の進行状況を表示しません。
/NDL
バックアップ結果として、ログファイルにファイルのみが出力されるようになります。
/TEE
バックアップの結果をコマンドプロンプトとログファイルの両方に出力します。
/XJD
フォルダのジャンクション・ポイントを除外する
/XJF
ファイルのジャンクション・ポイントを除外する

/DCOPY:T
日付を保存

このエントリーをはてなブックマークに追加

Rubyの開発するときに、いつもビルドディレクトリを分けているので flymake効かなかったんだけど、
どうせ、build/Makefile決め打ちでいいんだから、出来るはずだよなーと思ってやってみたら出来た。

だいたい http://www.emacswiki.org/emacs/FlyMake に載ってるサンプル通りなんだけど、あれは変に柔軟にしようとして、プロジェクト毎に場所を別途教えてあげないといけないので、余計めんどくささ感が上がっていた気がして敬遠していたの。



emacs lisp分かんないので、きっと改善の余地があると思うので晒します。叩いてください。
このエントリーをはてなブックマークに追加

http://gnu.wildebeest.org/blog/mjw/2012/03/16/automagically-merging-changelog-files-with-mercurial-or-git/

GIT

For git add the following lines to your ~/.gitconfig

[merge "merge-changelog"]
name = GNU-style ChangeLog merge driver
driver = /usr/local/bin/git-merge-changelog %O %A %B

[core]
attributesfile = ~/.gitattributes
And add the following line to ~/.gitattributes

ChangeLog merge=merge-changelog



うーむ、いまどきは project/.git/info/attributes をいじるのは古いのだな。git 1.7.4以降だからCentOS6だと使えないのが玉に瑕だけど。
このエントリーをはてなブックマークに追加

glibcでrealloc(ptr, 0)とわたしたときに、mtraceのログがおかしいというバグがあってその議論が面白かったのでご紹介。
http://sourceware.org/bugzilla/show_bug.cgi?id=14981

reallocという関数がある。まあ、みなさんよくご存知のように realloc(ptr, size)とわたしたときにptrをsizeの大きさに拡張(縮小)してくれる関数である。

malloc(0)がNULLを返しても非NULLを返してもいいように、realloc(ptr, 0)も挙動に実装の自由度がある

1.realloc(ptr, 1) と同等(mallocが非NULLを返すケースではこれが普通)
2.ptrは解放され、NULLが返る(mallocがNULLを返すケースでは常識的な挙動)
3.ptrは解放されず、NULLが返る(mallocがNULLを返すケースでは同じくらい常識的な挙動、malloc(0)をエラーとみなす哲学だと関数の最初に引数チェックをするのは理解できる)

The Austin Group Defect Report #400
http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_400.htm

によると、AIXとglibcが2、BSD系が3のようである。ところでPOSIXはテキストの書き方がわるくて3しか認めないような文章になってるから規格を直さないといけないんじゃないかな。という議論をしている

で、glibcに戻るとglibc 2.17までの挙動は

・malloc(0)は非NULLを返す(環境によるけど malloc(16)と同じになると思う)
・しかしなぜか realloc(ptr, 0) は free(ptr) と同じ挙動をし、NULLを返す(0サイズのメモリをアロケートしてはくれない)
・そしてmtraceのrealloc hookではrealloc(ptr, 0) で 非NULL が返ってくることを期待していてNULLは全部エラーとして扱っている

という不整合があり、正しくログがとれていなかった。

で、いつものようにみんなで規格書パース合戦を繰り広げた後、Roland McGrath が仲裁にはいって、ログと実際の挙動が違っているのは明らかにバグだから2.18ではmtraceを変える。realloc(ptr, 0)の挙動を変えるかどうかは規格解釈をglibc MLで議論するのがそもそも間違っていて、Austinで議論してから、必要なら変える。このコーナーケース
について変えてはいけないとは思わないが、規格に対する推測をもとに変更はしない。という結論になった。

まあ、順当なところかな。malloc(0)とrealloc(ptr, 0)の挙動が一貫してないのは気持ち悪いけど。
このエントリーをはてなブックマークに追加

なんかでてきた。またなくすと思うのでメモっとこう

http://togetter.com/li/22380?f

nalsh NetBSDのsetenv(3)ってnameに=を含む引数を許すのか


tnozaki @nalsh setenv("FOO=bar", "buzz") の場合、environは FOO=buzz になったはず、つまり '=' 以降は無視されるちう感じだったかと


このエントリーをはてなブックマークに追加

11:00 (peterz) # cat ~/.gitconfig
11:00 (peterz) [diff "default"]
11:00 (peterz) xfuncname = "^[[:alpha:]$_].*[^:]$"

以下の設定でいけるらしい。ふーん
このエントリーをはてなブックマークに追加

> According to specification
> mkdir d; ln -s d a; open("a/", O_NOFOLLOW | O_RDONLY)
> should return success but currently it did return ELOOP. Fix the code to ignore
> O_NOFOLLOW in case the provided path has trailing slashes. This is a regression
> caused by path lookup cleanup patch series.
>
> CC: stable@kernel.org

Hmm? Is this correct? Isn't the bug introduced in this merge window, and
thus not relevant for stable?



Jan KaraがAl ViroのせいでVFSがこわれたぞって修正パッチをポストしたところ、
Linusから、なんで今回のマージウィンドウでマージされたパッチに対する修正が -stableへの
バックポートが必要なのか。というツッコミが。


On Thu, 13 May 2010, Andrew Morton wrote:
>
> > Ah, you're right! I've seen dates in the patches around December so I
> > automatically thought the series went to 2.6.33 but checking git logs and
> > the actual source code of 2.6.33 it went in later. I'm sorry for the
> > confusion.
>
> Yes, it's a bit tricky (for me, at least) to work out "which kernel version did
> that patch go into" via git.
>
> I just keep lots of kernel trees around and poke about with `patch
> --dry-run'. PITA.



まず、Andrew Mortonがバージョン毎のツリーを抱えて、いちいち patch --dry-run で
当ててみるという自身の力業テクを披露

それをみたLinus大先生による、どうやってバージョン特定を簡単にやるかという
git講座が開始される


What I did to double-check was:

git log fs/namei.c

to find the commit series by Al (obviously, you can do it other ways too,
but that was the easy way). Then, when you find the commit just do

git name-rev 1f36f774b22a0ceb7dd33eca626746c81a97b6a5

which gives us

1f36f774b22a0ceb7dd33eca626746c81a97b6a5 tags/v2.6.34-rc1~195^2

ie that commit is reachable from v2.6.34-rc1, not from any stable kernel.

(Or alternatively, use "git describe", and get "v2.6.33-5088-g1f36f77",
which means that it is v2.6.33 plus 5088 commits).

And as usual, there are other ways. One particularly obscure one is to say

git log --tags --source --author=viro fs/namei.c

which basically says "show only commits by viro in fs/namei.c, start from
all tags, and for each commit, show _which_ tag the commit was reached
from". It's not perfect, but it does it in one go. With "--oneline", you'd
have gotten a listing like

3e297b6 v2.6.34-rc3 Restore LOOKUP_DIRECTORY hint handling in final lookup on open()
781b167 v2.6.34-rc2 Fix a dumb typo - use of & instead of &&
1f36f77 v2.6.34-rc2 Switch !O_CREAT case to use of do_last()
def4af3 v2.6.34-rc2 Get rid of symlink body copying
3866248 v2.6.34-rc2 Finish pulling of -ESTALE handling to upper level in do_filp_open()
806b681 v2.6.34-rc2 Turn do_link spaghetty into a normal loop
10fa8e6 v2.6.34-rc2 Unify exits in O_CREAT handling
9e67f36 v2.6.34-rc2 Kill is_link argument of do_last()
...

so you see into which -rc the different patches from Al went.

Linus
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html



超訳

git name-rev 1f36f774b22a0ceb7dd33eca626746c81a97b6a5

みたいに、git name-rev [commit-id] ってやれば

1f36f774b22a0ceb7dd33eca626746c81a97b6a5 tags/v2.6.34-rc1~195^2

こんな感じで、v2.6.34-rc1 で入ったって分かる。
もっと簡単にやるには

git log --tags --source --author=viro --oneline fs/namei.c

とかすると、fs/namei.c ファイルに入ったAl Viroの修正一覧がバージョンと共にずらっとでるよ。

3e297b6 v2.6.34-rc3 Restore LOOKUP_DIRECTORY hint handling in final lookup on open()
781b167 v2.6.34-rc2 Fix a dumb typo - use of & instead of &&
1f36f77 v2.6.34-rc2 Switch !O_CREAT case to use of do_last()
def4af3 v2.6.34-rc2 Get rid of symlink body copying
3866248 v2.6.34-rc2 Finish pulling of -ESTALE handling to upper level in do_filp_open()
806b681 v2.6.34-rc2 Turn do_link spaghetty into a normal loop
10fa8e6 v2.6.34-rc2 Unify exits in O_CREAT handling
9e67f36 v2.6.34-rc2 Kill is_link argument of do_last()
...
このエントリーをはてなブックマークに追加

http://d.hatena.ne.jp/issei_y/comment?date=20100501§ion=1272668964#c

によると、なんか最近のチェスソフトは手動プリフェッチで高速化とかしてるらしい。へー

面白いのはprefetch乱用ソフトの最右翼だったLinuxはprefetchを削除する方向に話を進めていることである。
最近はIntelがプリフェッチを推奨してないのよ。CPU内蔵の自動プリフェッチのほうが石の内部事情に
詳しいので。
なのでインテルコンパイラがプリフェッチ命令を削除してしまうケースがあるというのはおそらく意図的な
ものじゃないかな。

昔のCPUは自動プリフェッチとか弱かったから意味あったんだろうけど・・・
このエントリーをはてなブックマークに追加

http://news.slashdot.org/story/10/03/29/1952215/OpenSSL-100-Released?art_pos=5

リリースされちゃったみたい。0.9系と色々と非互換があるので中の人にはもうちょっと頑張って欲しかったのだが。
このエントリーをはてなブックマークに追加

ひさしぶりにプログラミングの話題でも。
現在のRubyのtrunkをx86_64上のFedora12でmake test-allすると8個ぐらいテストが失敗するのだが、その中の1つにこういうエラーがある

  1) Failure:
test_sin(DL::TestDL) [/home/kosaki/linux/ruby/test/dl/test_dl2.rb:95]:
<1.0> expected but was
<1.38523885234213e-309>.


test/dl/test_dl2.rbというのが、なにをしているテストかというと、ようするに以下のようにdlモジュールを使ってlibmのsin関数を呼んでいるわけだ

module DL
class TestDL < TestBase
# TODO: refactor test repetition
def test_sin()
pi_2 = Math::PI/2
cfunc = CFunc.new(@libm['sin'], TYPE_DOUBLE, 'sin')
x = cfunc.call([pi_2].pack("d").unpack("l!*"))
assert_equal(Math.sin(pi_2), x)
end
end
end # module DL


dlモジュールというのは(僕は知らなかったのだが)RubyからCのコードを直接呼ぶためのしくみで、引数をpackとunpackを使ってlongの配列にしておくと、なぜか関数の型に関わらず正しい結果がかえって来るという魔法のライブラリである。

まあ sin(π/2)が1.0にならなかったら、バグだよね。


では、その実装をみていこう


static VALUE
rb_dlcfunc_call(VALUE self, VALUE ary)
{
struct cfunc_data *cfunc;
int i;
DLSTACK_TYPE stack[DLSTACK_SIZE];
VALUE result = Qnil;

rb_secure_update(self);

memset(stack, 0, sizeof(DLSTACK_TYPE) * DLSTACK_SIZE);
Check_Type(ary, T_ARRAY);

TypedData_Get_Struct(self, struct cfunc_data, &dlcfunc_data_type, cfunc);

if( cfunc->ptr == 0 ){
rb_raise(rb_eDLError, "can't call null-function");
return Qnil;
}

for( i = 0; i < RARRAY_LEN(ary); i++ ){
if( i >= DLSTACK_SIZE ){
rb_raise(rb_eDLError, "too many arguments (stack overflow)");
}
rb_check_safe_obj(RARRAY_PTR(ary)[i]);
stack[i] = NUM2LONG(RARRAY_PTR(ary)[i]);
}


まず、RubyのArray(ary)をCのArray(stack[])に変換する。


switch( cfunc->type ){
case DLTYPE_VOID:
#define CASE(n) case n: { \
DECL_FUNC_CDECL(f,void,DLSTACK_PROTO##n) = cfunc->ptr; \
f(DLSTACK_ARGS##n(stack)); \
result = Qnil; \
}
CALL_CASE;
#undef CASE
break;
・・・

case DLTYPE_DOUBLE:
#define CASE(n) case n: { \
DECL_FUNC_CDECL(f,double,DLSTACK_PROTO##n) = cfunc->ptr; \
double ret; \
ret = f(DLSTACK_ARGS##n(stack)); \
result = rb_float_new(ret); \
}
CALL_CASE;
#undef CASE


んで、CFunc.newで渡したtypeに応じてクソ長い switch caseが始まる。ここでさらに引数の数に応じて場合分けしたいが最大引数数がrubyのdlモジュールの仕様上20個もあるため、いちいち書くのがめんどくさいのでCASE, CALLCASEマクロで量産している。CALL_CASEマクロの定義は以下


#define CALL_CASE switch( RARRAY_LEN(ary) ){ \
CASE(0); break; \
CASE(1); break; CASE(2); break; CASE(3); break; CASE(4); break; CASE(5); break; \
CASE(6); break; CASE(7); break; CASE(8); break; CASE(9); break; CASE(10);break; \
CASE(11);break; CASE(12);break; CASE(13);break; CASE(14);break; CASE(15);break; \
CASE(16);break; CASE(17);break; CASE(18);break; CASE(19);break; CASE(20);break; \
default: rb_raise(rb_eArgError, "too many arguments"); \
}


というわけで、cfunc.call()すると


DECL_FUNC_CDECL(f,double,DLSTACK_PROTO##n) = cfunc->ptr; \


はCFunc.newでlookupした関数ポインタcfunc->ptr(この場合はsin())をfに代入して、


double ret; \
ret = f(DLSTACK_ARGS##n(stack)); \


fをcallして


result = rb_float_new(ret); \


それをrubyのfloatオブジェクトに変換して返す。ということをしているのだと分かる。実装の詳細を見るために
DLSTACK_PROTO1
DECL_FUNC_CDECL
DLSTACK_ARGS1
のマクロ定義も見ていこう。(あ、今回は引数1つなので##nは1になる。CALL_CASEマクロをもう一度みると納得できると思います。)

まず、DLSTACK_PROTO1とDECL_FUNC_CDECLから見る

#define DLSTACK_TYPE long
#define DLSTACK_PROTO1_ DLSTACK_TYPE
#define DLSTACK_PROTO1 DLSTACK_PROTO1_, ...

#if !defined(FUNC_CDECL)
# define FUNC_CDECL(x) x
#endif
# define DECL_FUNC_CDECL(f,ret,args) ret (FUNC_CDECL(*f))(args)


ようするに DLSTACK_PROTO1 → "long, ..." で結果として

DECL_FUNC_CDECL(f,double,DLSTACK_PROTO##n) = cfunc->ptr; \

という行は

double (*f)(long, ...) = cfunc->ptr;

となる。

わざわざ可変長引数にしている理由は、すぐそばに以下のコメントががが

/*
* Add ",..." as the last argument.
* This is required for variable argument functions such
* as fprintf() on x86_64-linux.
*
* http://refspecs.linuxfoundation.org/elf/x86_64-abi-0.95.pdf
* page 19:
*
* For calls that may call functions that use varargs or stdargs
* (prototype-less calls or calls to functions containing ellipsis
* (...) in the declaration) %al is used as hidden argument to
* specify the number of SSE registers used.
*/


つまり、x86_64では...を特別扱いするから、これでうまくいくんだよ。と言いたいようだ。

でもって、DLSTACK_ARGS1は


#define DLSTACK_ARGS1(stack) stack[0]


なので、

f(DLSTACK_ARGS##n(stack)); \



f(stack[0]);

という普通の関数呼び出しになる。

あれ?なんかx86_64対策も入ってるのになんでうまくいかんのだ?という話になるので、参照されているx86_64 ABI
の原典を読む



3.2.3 Parameter Passing

After the argument values have been computed, they are placed in registers, or
pushed on the stack. The way how values are passed is described in the following
sections.

Definitions We first define a number of classes to classify arguments. The
classes are corresponding to AMD64 register classes and defined as:

INTEGER This class consists of integral types that fit into one of the general
purpose registers.
SSE The class consists of types that fits into a SSE register.
SSEUP The class consists of types that fit into a SSE register and can be passed
and returned in the most significant half of it.
X87, X87UP These classes consists of types that will be returned via the x87 FPU.
COMPLEX_X87 This class consists of types that will be returned via the x87 FPU.
NO_CLASS This class is used as initializer in the algorithms. It will be used for
padding and empty structures and unions.
MEMORY This class consists of types that will be passed and returned in memory
via the stack.


超訳。ABI的にはINTEGER, SSE, SSEUP, X87, X87UP, COMPLEX_X87, NO_CLASSという
引数のタイプがあるよ。



Classification The size of each argument gets rounded up to eightbytes.
The basic types are assigned their natural classes:

• Arguments of types (signed and unsigned) _Bool, char, short, int,
long, long long, and pointers are in the INTEGER class.
• Arguments of types float, double and __m64 are in class SSE.
(しばらく略)


超訳
(signed and unsigned) _Bool, char, short, int, long, long long, およびポインタは INTEGERだよ
float, double and __m64 はSSEだよ

(この後、__float128とか構造体とかの説明がつづくが割愛)



Passing Once arguments are classified, the registers get assigned (in left-to-right
order) for passing as follows:

1. If the class is MEMORY, pass the argument on the stack.
2. If the class is INTEGER, the next available register of the sequence %rdi,
%rsi, %rdx, %rcx, %r8 and %r9 is used.
3. If the class is SSE, the next available SSE register is used, the registers are
taken in the order from %xmm0 to %xmm7.
4. (略)
5. (略)


超訳。
MEMORYならスタック渡し確定
INTEGERならrdi, rsi, rdx, rcx, r8, r9の順に使うよ
SSEならSSEレジスタをxmm0からxmm7の順につかうよ


If there is no register available anymore for any eightbyte of an argument, the
whole argument is passed on the stack. If registers have already been assigned for
some eightbytes of this argument, those assignments get reverted.

Once registers are assigned, the arguments passed in memory are pushed on
the stack in reversed (right-to-left) order.


超訳
レジスタが足りなくなったらスタックを使って引数を渡すよ。
スタックには逆順(右から左)でpushするよ


で、ここで問題のセンテンスが現れる

For calls that may call functions that use varargs or stdargs (prototype-less
calls or calls to functions containing ellipsis (. . . ) in the declaration) %al is used
as hidden argument to specify the number of SSE registers used. The contents of
%al do not need to match exactly the number of registers, but must be an upper


超訳
varargsまたはstdargsな関数(プロトタイプがなかったり、宣言で...を使っていたり)を呼ぶときは
%al に何個SSEレジスタを使ったか隠し引数で入れるよ。


つまり、ここではprintf()的なまっとうな可変長引数の事を語っているだけであって、呼び出し元と呼び出し先で
関数の型が適合しない場合については何も語っていない。

今回の場合で言うとsin関数はlibmの中では
double sin(double)
という型でコンパイルされていて、呼び出し側では
double f(long, ...)
という型だと思ってcallしている。

じゃあ、実際に何が起こるかを示すためにテストプログラムを書いてみた。

main.c

#define _GNU_SOURCE
#include
#include

void f1(void) {
double (*func)(long, ...);
double d = 57.0;
long l = *(long*)&d;
double ret;

func = dlsym(RTLD_DEFAULT, "func");
ret = func(l);
printf("%f\n",ret);
}

int main(void)
{
f1();
return 0;
}


f.c

double func(double d)
{
return d*2;
}


実行結果

% gcc *.c -ldl -Wall -g -rdynamic; ./a.out
0.000000


はい、57*2で114 が返ってくるはずが0が返ってきてしまいました。

んではdisassemble,


0000000000400834 :
400834: 55 push %rbp
400835: 48 89 e5 mov %rsp,%rbp
400838: f2 0f 11 45 f8 movsd %xmm0,-0x8(%rbp)
40083d: f2 0f 10 45 f8 movsd -0x8(%rbp),%xmm0
400842: f2 0f 58 c0 addsd %xmm0,%xmm0
400846: c9 leaveq
400847: c3 retq


funcでは素直にxmm0を引数だと思って二倍しています。


00000000004008e0 :
4008e0: 55 push %rbp
4008e1: 48 89 e5 mov %rsp,%rbp
4008e4: 48 83 ec 20 sub $0x20,%rsp
4008e8: 48 b8 00 00 00 00 00 mov $0x404c800000000000,%rax
4008ef: 80 4c 40
4008f2: 48 89 45 e0 mov %rax,-0x20(%rbp)
4008f6: 48 8d 45 e0 lea -0x20(%rbp),%rax
4008fa: 48 8b 00 mov (%rax),%rax
4008fd: 48 89 45 f0 mov %rax,-0x10(%rbp)
400901: b8 48 0b 40 00 mov $0x400b48,%eax
400906: 48 89 c6 mov %rax,%rsi
400909: bf 00 00 00 00 mov $0x0,%edi
40090e: e8 2d fe ff ff callq 400740
400913: 48 89 45 e8 mov %rax,-0x18(%rbp)
400917: 48 8b 45 f0 mov -0x10(%rbp),%rax
40091b: 48 8b 55 e8 mov -0x18(%rbp),%rdx
40091f: 48 89 c7 mov %rax,%rdi
400922: b8 00 00 00 00 mov $0x0,%eax
400927: ff d2 callq *%rdx
400929: f2 0f 11 45 f8 movsd %xmm0,-0x8(%rbp)
40092e: b8 4d 0b 40 00 mov $0x400b4d,%eax
400933: f2 0f 10 45 f8 movsd -0x8(%rbp),%xmm0
400938: 48 89 c7 mov %rax,%rdi
40093b: b8 01 00 00 00 mov $0x1,%eax
400940: e8 db fd ff ff callq 400720
400945: c9 leaveq
400946: c3


でもf1ではrdi(INTEGERの第一引数)に l を、eaxに0を入れて関数コールしています。

つまり、これが起きていることのすべてです。
呼び出し側がrdiに引数を詰んでいるのに、呼び出され側はxmm0を呼んでいるのですから
正しい答えが返るはずがありません。

というわけで、これはdlモジュール制作者のABIの誤読ですね。
なお、Cの規格的には呼び出し元と呼び出し先で関数型が適合しない場合は未定義。たぶん、dlモジュール作者は規格を元に考えたのではなく

1)全CPUアーキテクチャでlongで無理矢理callしても安心と考えた。または
2)x86_32 だけで動けばいいや。と割り切った

のどちらかだと思いますが、イマドキx86_64は普通ですからねぇ。。。

現在のインターフェースだと直しようがないので、RubyのCFuncの仕様を大きく変えないと x86_64対応は出来ないでしょう。
というわけで、RubyユーザのみなさんはCFuncでfloat, doubleを使わないようにしておくと将来幸せになれるかもしれないというお話でした。

ではでは


追記: なぜこの問題がx86_64だけで発生するのかを、つらつらと考えてみたのだが、やはり歴史的な理由だろう。昔は関数宣言を忘れるとか当たり前だったので、昔からあるアーキだと、こういう関数型が不適合な呼び出しに対してABIを寛容に作ることが多かったのではないか?

追記2: 関数の型の適合性とか安易に書いた気がする。でもCの規格を読み直す気がおきない。めどい
簡単にいうと
1)呼び出し元と呼び出し先が両方とも関数宣言有り: 引数、戻り値の型が全部一致していた場合のみOK
2)どちらかが宣言なし: 戻り値の型は厳密一致が必要だけど、引数は型がshortとintみたいに十分近ければOK
みたいなノリだったと思う。今回はケース1だけど、2の基準で反転してもアウトという論外さ
このエントリーをはてなブックマークに追加

↑このページのトップヘ