2

スレッドを使用およびスケジュールするための独自のライブラリを構築しようとしています。

システムは可能な方法で機能してmake maximum 100 threadsおり、「準備完了」になっています。そして、一定期間ごとにアクティブなスレッドを取得し、それを準備完了リストに入れ、準備完了リストで最初に待機しているスレッドを取得するスケジューラーがあります。

私のテスターは500000スレッドを作成しています。各スレッドは新しいスレッドを作成し、それ自体を終了しようとします。2 番目のスレッド (最初のスレッドが作成する) も同じことを行います。3 つ目は、自分自身を終了させるだけです。

これはテスターです:

void f3()
{
    printf("f3 before terminate\n");
    uthread_terminate(uthread_get_tid());
    printf("f3 after terminate\n");
}

void f2()
{
    printf("f2 before spawn\n");
    uthread_spawn(f3);
    printf("f2 after spawn\n");
    uthread_terminate(uthread_get_tid());
    printf("f2 after termination\n");
}

void f1()
{
    printf("f1 before spawn\n");
    uthread_spawn(f2);
    printf("f1 after spawn\n");
    uthread_terminate(uthread_get_tid());
    printf("f1 after termination\n");
}



int main(int argc, char **argv)
{
   printf("test8:\n--------------\n");
   cout << "* Output should be:\n";    
   cout << "--------------\n";
   cout << "***1***\n";
   cout << "***2***\n";
   cout << "Output is:\n";
   uthread_init(100);
   printf("***1***\n");
   for (volatile int i=0; i< 50000;++i){
        uthread_spawn(f1);
   }
   printf("***2***\n");

   uthread_terminate(0);
   return 0;
}

プログラムがスケジューラに入ると「セグメンテーション違反」が発生しますが、次のようになります。

static void scheduler(){
DBG(("Schedular "))
nQuantum++;
if (ready.size()!=0){
    if (active != NULL){
        if (active->getState() == Thread::RUNNING){
            active->setState(Thread::READY);
            ready.push_back(active);
        }

        int val = sigsetjmp(*active->getEnv(),1);
        if (val !=0){
            blockTimerSignal(UNBLOCK);
            return;
        }
    }

    // Set new Active
    active = ready.front();
    DBG(("Active thread Id: %d",active->getTid()))
    ready.pop_front();
    DBG(("Doing pop front on ready list"))
    DBG(("Number of threads in ready list is  - %d",(ready.size())))
    active->setQuantums(active->getQuantums()+1);
    active->setState(Thread::RUNNING);
    setTimer();
    blockTimerSignal(UNBLOCK);
    DBG(("UNBLOCKED"))
    siglongjmp(*active->getEnv(),1);
    DBG(("After siglong jmp"))
}else{
    active->setQuantums(active->getQuantums()+1);
}
DBG(("Number of threads in ready list is  - %d",(ready.size())))

blockTimerSignal(UNBLOCK);
 }

するときsiglongjmp(*active->getEnv(),1);

これは、メイン スレッド (ID 0 のプログラムの最初のスレッド) でのみ発生します。プログラムがしばらく実行された後も発生します。つまり、プログラムの途中で、アクティブなスレッドに対して siglongjmp を実行できますが、しばらくしてから再試行すると、エラーが発生します。

役立つ場合は、終了機能を追加します。

int uthread_terminate(int tid) {
    DBG(("Terminate - %d", tid))

    if (tid == 0){
        // delete all (threads) - don't think it's needed because using stl!
        // TODO : check if needed - and then delete all lists !
        //Added by Roni - Deleting all lists!
        while(!sleeping.empty()){
            delete (sleeping.front());
            sleeping.pop_front();
        }

        while(!suspended.empty()){
            delete (suspended.front());
            suspended.pop_front();
        }

        while(!ready.empty()){
            delete (ready.front());
            ready.pop_front();
        }


        exit(0);
    }

    pThread t = getThread(tid);
    if (t == NULL){
        errmsgLibrary(THREAD_NOT_FOUND);
        return FAIL;
    }
    Thread::threadState state = t->getState();
    DBG(("Terminate - %d in State %d", tid, state))
    DBG(("Number of threads in ready list is  - %d",(ready.size())))
    blockTimerSignal(BLOCK);
    switch (state){
    case (Thread::RUNNING):
        //DBG(("Running Case"))
        //DBG(("Active thread id is: %d ",active->getTid()))
            delete active;
            active = NULL;
    //DBG(("Finsihed running Case"))
            scheduler();

            break;
    case (Thread::READY):
        //DBG(("ready Case"))
            ready.remove(t);
            delete t;
            //DBG(("Finsihed ready Case"))
        break;
    case (Thread::SLEEP):
            sleeping.remove(t);
            delete t;
        break;
    case (Thread::SUSPENDED):
            suspended.remove(t);
            delete t;
            break;
    default:
        break;
    }
    //DBG(("Number of threads in ready list is  - %d",(ready.size())))
    blockTimerSignal(UNBLOCK);
    return SUCCESS;
}
4

1 に答える 1

0

推測では、siglongjmpここで使用しており、呼び出し間でスタックを変更していない可能性があります。

代わりにgetcontext()swapcontext()およびを使用することを検討してください。makecontext()

于 2013-04-11T10:00:05.193 に答える