我有一个不寻常的问题,无法找到导致它的原因。
我正在开发用户级非preemtive线程库。
void MyThreadYield(void) {
if(myThreadLib.readyQ->size > 0) {
ucontext_t currentContext;
getcontext(¤tContext);
myThreadLib.runningMyThread->ctx = currentContext;
queueEnqueue(myThreadLib.readyQ, myThreadLib.runningMyThread);
myThreadLib.runningMyThread = queueDequeue(myThreadLib.readyQ);
setcontext(&(myThreadLib.runningMyThread->ctx));
}
}
执行getcontext(¤tContext)
后,currentContext中的ss_stack为NULL。以下是currentContext的快照
执行myThreadLib.runningMyThread->ctx = currentContext;
后,它会修改readyQ,不知道为什么。
但是,setcontext(&(myThreadLib.runningMyThread->ctx));
执行正常并且上下文已成功更改,但在MyThreadYield()再次调用时会给出Segfault。
你可以帮我解决这个问题吗?
感谢。
答案 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,应该避免使用。