【问题标题】:Switching from one thread to another giving segmentation fault从一个线程切换到另一个导致分段错误
【发布时间】:2016-07-13 05:57:48
【问题描述】:

我正在尝试在 x86_64 中用 C 语言开发一个用户级线程库。 我有一个名为machine_switch 的函数,它将新线程和当前线程的堆栈指针作为参数。该函数应该通过备份当前寄存器值并从新堆栈指针恢复新值来切换线程。这是我尝试过的。

.text
.global machine_switch

machine_switch:
    # address of the new sp is arg1
    # address of the current sp is arg2
    # need to store all required registered for old tcb
    # restore all required registred from the new tcb
    # then when you return, you should get to the new thread 

    pushq %rbx
    pushq %rbp
    pushq %r12
    pushq %r13
    pushq %r14
    pushq %r15

    movq %rdi, %rsp

    popq %r15
    popq %r14
    popq %r13
    popq %r12
    popq %rbp
    popq %rbx

    ret 

这是我用来存储线程的数据结构。

struct tcb { 
  void *sp;  /* Address of stack pointer. 
          * Keep this as first element would ease switch.S 
          * You can do something else as well. 
          */  
  int id;
  int state; /* 1 - ready state
          * 2 - running state
          * 3 - blocked state
          */
};

我有一个tcb 的列表。我在新旧tcb 中传递sp 作为machine_switch 函数的参数。

但是这个函数在改变堆栈指针时会出现分段错误。 (movq %rdi, %rsp)。我检查了函数的参数,它们是正确的。我错过了什么吗?

【问题讨论】:

  • 如何获得新的堆栈指​​针?也许你没有使用一个好的价值。
  • @FUZxxl 我想知道的是我在概念上错过了什么。从一个线程切换到另一个线程时是否还有更多工作要做。完整的代码大约有 600 行,这就是我没有发布它的原因。
  • 等一下,我想我发现了您的错误(不确定,因为我对您的代码不太了解):推送后,旧的堆栈指针已更改。您将最终的旧堆栈指针存储在哪里?您似乎为旧堆栈指针保存了错误的值。
  • 错误不太可能出在movq %rdi, %rsp,该指令只是一个寄存器副本。您错误地使用了调试器,或者误解了它的操作(人们经常将 gdb 错误误认为是程序错误)。

标签: c multithreading assembly x86-64


【解决方案1】:

您的问题是您可能会在调用machine_switch 之前保存旧的堆栈指针。但是,machine_switch 将值压入堆栈,导致保存的堆栈指针无效。要解决此问题,您可以将指针传递到要保存旧堆栈指针的位置并在推送寄存器后存储指针:

machine_switch:
    pushq %rbx
    pushq %rbp
    pushq %r12
    pushq %r13
    pushq %r14
    pushq %r15

    movq %rsp,(%rsi) # save old stack pointer
    movq %rdi, %rsp

    popq %r15
    popq %r14
    popq %r13
    popq %r12
    popq %rbp
    popq %rbx

    ret 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-06-28
    • 1970-01-01
    • 1970-01-01
    • 2020-10-25
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多