linux 下 tango.core.sync.Condition 和 gc 的相关问题, 源码检查
redsea
2007-09-10
今天用到 condition, 查看 Condition.d 源代码的时候, 想到一个问题:
如果线程安装了某个信号处理器, 这个信号处理器没有设置 SA_RESTART, 那么信号发生的时候, pthread_cond_wait 会被打断, 同时返回0 (当作正常返回). 因此, 不能认为 condition 返回的话, 要等的条件是一定发生了. 想到 gc 也是通过 signal 暂停其他线程的, 进行了一些检查, 检查结果发现tango 设计是正确的, gc 不会打断 pthread_cond_wait. 检查的过程中大致了解了 gc 的启动情况. gcx.d 中, 当进行内存分配, 而目前可用的 page 不足的时候, 会fullcollectshell, 然后调用到 fullcollect, fullcollect 调用 thread_suspendAll 暂停所有线程, 然后进行垃圾收集, 完事之后再 thread_resumeAll 让其他线程恢复执行. thread_suspendAll, thread_resumeAll 都在 thread.d 中. thread_suspendAll 通过发送 SIGUSR1 让线程进入 signal handler 等待 gc 完毕. gc 处理完毕发送 SIGUSR2 通知其他线程, 可以从 signal handler 中返回. 整个逻辑还是比较简单的, 但是用到一些汇编代码都是 x86 的, 不可以移植. 我本来以为会有一个单独运行的 gc 线程 ---- 以前看 java 文章老是提到这个东西, 结果并没有这个线程. 相关的 signal handler 代码如下: extern (C) void thread_suspendHandler( int sig ) in { assert( sig == SIGUSR1 ); } body { version( D_InlineAsm_X86 ) { asm { pushad; } } else version( GNU ) { __builtin_unwind_init(); } else { static assert( false, "Architecture not supported." ); } // NOTE: Since registers are being pushed and popped from the stack, // any other stack data used by this function should be gone // before the stack cleanup code is called below. { Thread obj = Thread.getThis(); // NOTE: The thread reference returned by getThis is set within // the thread startup code, so it is possible that this // handler may be called before the reference is set. In // this case it is safe to simply suspend and not worry // about the stack pointers as the thread will not have // any references to GC-managed data. if( obj && !obj.m_lock ) { obj.m_curr.tstack = getStackTop(); } sigset_t sigres = void; int status; status = sigfillset( &sigres ); assert( status == 0 ); status = sigdelset( &sigres, SIGUSR2 ); assert( status == 0 ); status = sem_post( &suspendCount ); assert( status == 0 ); sigsuspend( &sigres ); if( obj && !obj.m_lock ) { obj.m_curr.tstack = obj.m_curr.bstack; } } version( D_InlineAsm_X86 ) { asm { popad; } } else version( GNU ) { // registers will be popped automatically } else { static assert( false, "Architecture not supported." ); } } extern (C) void thread_resumeHandler( int sig ) in { assert( sig == SIGUSR2 ); } body { } |
|
oldrev
2007-09-10
看来是跟 phobos 一样的策略,不知道什么时候能把runtime的这些接口规范一下,把基本的runtime代码统一起来
|
|
redsea
2007-09-10
oldrev 写道 看来是跟 phobos 一样的策略,不知道什么时候能把runtime的这些接口规范一下,把基本的runtime代码统一起来
我相信这些和操作系统底层密切相关的地方, 最优的方案应该都很接近. 稍高级别些, 例如 gc 的垃圾收集方法, 不同的应用程序可能不同的做法会更好, 这里可能会出现更多的设计选择, 如果有多种 gc, 编译时刻可选, 就更好了. |