MyThreadYield(void)中的getcontext()获取空上下文

时间:2013-09-10 17:17:54

标签: c process operating-system pthreads

我有一个不寻常的问题,无法找到导致它的原因。

我正在开发用户级非preemtive线程库。

void MyThreadYield(void) {
    if(myThreadLib.readyQ->size > 0) {
        ucontext_t currentContext;
        getcontext(&currentContext);
        myThreadLib.runningMyThread->ctx = currentContext;
        queueEnqueue(myThreadLib.readyQ, myThreadLib.runningMyThread);
        myThreadLib.runningMyThread = queueDequeue(myThreadLib.readyQ);
        setcontext(&(myThreadLib.runningMyThread->ctx));
    }
}

执行getcontext(&currentContext)后,currentContext中的ss_stack为NULL。以下是currentContext的快照

enter image description here 执行myThreadLib.runningMyThread->ctx = currentContext;后,它会修改readyQ,不知道为什么。

但是,setcontext(&(myThreadLib.runningMyThread->ctx));执行正常并且上下文已成功更改,但在MyThreadYield()再次调用时会给出Segfault。

你可以帮我解决这个问题吗?

感谢。

1 个答案:

答案 0 :(得分:0)

在glib-2.17中,我得到了getcontext()汇编代码:

0x0000000000401b50 <+0>:     mov    %rbx,0x80(%rdi)
0x0000000000401b57 <+7>:     mov    %rbp,0x78(%rdi)
0x0000000000401b5b <+11>:    mov    %r12,0x48(%rdi)
0x0000000000401b5f <+15>:    mov    %r13,0x50(%rdi)
0x0000000000401b63 <+19>:    mov    %r14,0x58(%rdi)
0x0000000000401b67 <+23>:    mov    %r15,0x60(%rdi)
0x0000000000401b6b <+27>:    mov    %rdi,0x68(%rdi)
0x0000000000401b6f <+31>:    mov    %rsi,0x70(%rdi)
0x0000000000401b73 <+35>:    mov    %rdx,0x88(%rdi)
0x0000000000401b7a <+42>:    mov    %rcx,0x98(%rdi)
0x0000000000401b81 <+49>:    mov    %r8,0x28(%rdi)
0x0000000000401b85 <+53>:    mov    %r9,0x30(%rdi)
0x0000000000401b89 <+57>:    mov    (%rsp),%rcx
0x0000000000401b8d <+61>:    mov    %rcx,0xa8(%rdi)
0x0000000000401b94 <+68>:    lea    0x8(%rsp),%rcx
0x0000000000401b99 <+73>:    mov    %rcx,0xa0(%rdi)
0x0000000000401ba0 <+80>:    lea    0x1a8(%rdi),%rcx
0x0000000000401ba7 <+87>:    mov    %rcx,0xe0(%rdi)
0x0000000000401bae <+94>:    fnstenv (%rcx)
0x0000000000401bb0 <+96>:    fldenv (%rcx)
0x0000000000401bb2 <+98>:    stmxcsr 0x1c0(%rdi)
0x0000000000401bb9 <+105>:   lea    0x128(%rdi),%rdx
0x0000000000401bc0 <+112>:   xor    %esi,%esi
0x0000000000401bc2 <+114>:   xor    %edi,%edi
0x0000000000401bc4 <+116>:   mov    $0x8,%r10d
0x0000000000401bca <+122>:   mov    $0xe,%eax
0x0000000000401bcf <+127>:   syscall
0x0000000000401bd1 <+129>:   cmp    $0xfffffffffffff001,%rax
0x0000000000401bd7 <+135>:   jae    0x410f70 <__syscall_error>
0x0000000000401bdd <+141>:   xor    %eax,%eax
0x0000000000401bdf <+143>:   retq

似乎只在getcontext()调用中修改了uc_mcontext。 uc_stack没有受到影响。

通过阅读getcontext信息,获取以下字词:

Unix标准提供了另外一组函数来控制 执行路径和这些功能比那些更强大 到目前为止在本章中讨论过。这些功能的一部分 最初的System V API和这条路由被添加到Unix API中。 除了品牌的Unix实现,这些接口并不广泛 可用。并非GNU C Library的所有平台和/或体系结构都是如此 可用于提供此界面。使用`configure'来检测 可用性。

男人的getcontext有以下几个字:

遵守        SUSv2,POSIX.1-2001。 POSIX.1-2008删除了getcontext()的规范,        引用可移植性问题,并建议重写应用程序        改为使用POSIX线程。

所以我认为getcontext / setcontext / swapcontext / makecontext都是obselete,应该避免使用。