2016-07-13 4 views
0

私は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のリストを持っています。 machine_switchの引数として、を新しく入れて、spを渡しています。

しかし、この関数はスタックポインタを変更する際にセグメンテーションフォールトを与えます。 (movq %rdi, %rspに)。私は関数の引数をチェックしたが、正しい。何か不足していますか?

+1

新しいスタックポインタはどうやって取得できますか?多分あなたは良い価値を使っていないでしょう。 –

+0

[mcve]を作成してください。 – fuz

+0

@FUZxxl私が知りたいのは、私が概念的に見逃したことです。あるスレッドから別のスレッドに切り替えるときに、より多くのことがあるかどうか。完全なコードは約600行なので、私はそれを投稿しませんでした。 – pahan

答えて

2

あなたの問題は、おそらく古いスタックポインタを保存してから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 
関連する問題