【问题标题】:getcontext() in MyThreadYield(void) fetches null contextMyThreadYield(void) 中的 getcontext() 获取空上下文
【发布时间】:2013-09-14 12:45:54
【问题描述】:

我遇到了一个不寻常的问题,但找不到导致它的原因。

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

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 的快照

而且myThreadLib.runningMyThread->ctx = currentContext;执行后修改了readyQ,不知道为什么。

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

你能帮我解决这个问题吗?

谢谢。

【问题讨论】:

  • 嗨,查理,但是在这里,在执行 getcontext(&currentContext) 之后,currentContext 的 uc_stack 为 NULL。这是我还在 MyThreadYield() 函数中的时候。此外,我将 currentContext 分配给动态分配的 MyThread 结构。

标签: c process operating-system pthreads


【解决方案1】:

在 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 info,得到以下单词:

Unix 标准提供了一组函数来控制 执行路径,这些功能比那些功能更强大 本章讨论到此为止。这些功能的一部分 原始的 System V API 并通过此路线被添加到 Unix API。 除了品牌的 Unix 实现之外,这些接口并不广泛 可用的。并非所有平台和/或体系结构 GNU C 库都是 可在提供此接口时使用。使用“配置”来检测 可用性。

而man getcontext有以下几个字:

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

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

【讨论】:

    猜你喜欢
    • 2020-01-20
    • 2011-09-07
    • 2023-04-01
    • 2015-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-08
    • 1970-01-01
    相关资源
    最近更新 更多