これをちょっと試してみた。
http://www.saturn.dti.ne.jp/~hsakai/kozos/kozos01.html
オリジナルは FreeBSD 用なので etch 用の glibc-2.3.6 のソースを見て thread.c を Linux 用に変更した。
ここを見ると glibc-2.4 だとポインタがエンコードされているようでうまくいかなそう。
http://d.hatena.ne.jp/higepon/20070131/1170257744
#patch は下に移した。
setjmp() 後に書き換えたコンテキストで longjmp() すると死んでしまう。呼び出し規約の問題かも。同じ gcc でも FreeBSD だと違うのかな。
その後も調査したら longjmp() は良いけど書き換えたコンテキストを元にスレッドの関数を起動すると失敗するみたい。スタックの配列の添え字が違うような気がするので直したらそれっぽく動くようになったがスレッドを終了すると死んでしまう。
osanai@debian:~/src/kozos$ diff thread.c thread.c.org
75c75
< ((int *)sp)[0] = (int)thread_end;
> ((int *)sp)[1] = (int)thread_end;
78,80c78,80
< ((int *)sp)[1] = (int)thp;
< ((int *)sp)[2] = argc;
< ((int *)sp)[3] = (int)argv;
> ((int *)sp)[2] = (int)thp;
> ((int *)sp)[3] = argc;
> ((int *)sp)[4] = (int)argv;
87,92c87,92
< thp->context.env[0].__jmpbuf[JB_PC] = (int)thread_init; /* EIP */
< thp->context.env[0].__jmpbuf[JB_BX] = intr_env[0].__jmpbuf[JB_BX]; /* EBX */
< thp->context.env[0].__jmpbuf[JB_SP] = (int)sp; /* ESP */
< thp->context.env[0].__jmpbuf[JB_BP] = intr_env[0].__jmpbuf[JB_BP]; /*
EBP */
< thp->context.env[0].__jmpbuf[JB_SI] = intr_env[0].__jmpbuf[JB_SI]; /* ESI */
< thp->context.env[0].__jmpbuf[JB_DI] = intr_env[0].__jmpbuf[JB_DI]; /* EDI */
> thp->context.env[0]._jb[0] = (int)thread_init; /* EIP */
> thp->context.env[0]._jb[1] = intr_env[0]._jb[1]; /* EBX */
> thp->context.env[0]._jb[2] = (int)sp; /* ESP */
> thp->context.env[0]._jb[3] = intr_env[0]._jb[3]; /*
EBP */
> thp->context.env[0]._jb[4] = intr_env[0]._jb[4]; /* ESI */
> thp->context.env[0]._jb[5] = intr_env[0]._jb[5]; /* EDI */
96,97c96,97
< thp->context.env[0].__jmpbuf[JB_PC] = (int)thread_init; /* EIP */
< thp->context.env[0].__jmpbuf[JB_SP] = (int)sp; /* ESP */
> thp->context.env[0]._jb[0] = (int)thread_init; /* EIP */
> thp->context.env[0]._jb[2] = (int)sp; /* ESP */