Написание планировщика для библиотеки потоков Userspace - PullRequest
0 голосов
/ 06 ноября 2011

Я занимаюсь разработкой библиотеки преимущественных потоков в пользовательском пространстве (fiber), в которой базовый подход использует переключение контекста.Для этого я написал планировщик.Тем не менее, это не работает, как ожидалось.Могу ли я иметь какие-либо предложения для этого.Структура используемого thread_t:

typedef struct thread_t {
    int thr_id;
    int thr_usrpri;
    int thr_cpupri;
    int thr_totalcpu;
    ucontext_t thr_context;
    void * thr_stack;
    int thr_stacksize;
    struct thread_t *thr_next;
    struct thread_t *thr_prev;
} thread_t;

Функция планирования следующая:

void schedule(void)
{
        thread_t *t1, *t2;
    thread_t * newthr = NULL;
    int newpri = 127;
    struct itimerval tm;
    ucontext_t dummy;
    sigset_t sigt;


    t1 = ready_q;

    // Select the thread with higest priority
    while (t1 != NULL)
    {
        if (newpri > t1->thr_usrpri + t1->thr_cpupri)
        {
            newpri = t1->thr_usrpri + t1->thr_cpupri;
            newthr = t1;
        }

        t1 = t1->thr_next;
    }

    if (newthr == NULL)
    {
        if (current_thread == NULL)
        {
            // No more threads? (stop itimer)
            tm.it_interval.tv_usec = 0;
            tm.it_interval.tv_sec = 0;
            tm.it_value.tv_usec = 0; // ZERO Disable
            tm.it_value.tv_sec = 0;
            setitimer(ITIMER_PROF, &tm, NULL);
        }
        return;
    }
    else
    {
        // TO DO :: Reenabling of signals must be done.
        // Switch to new thread
        if (current_thread != NULL)
        {
            t2 = current_thread;
            current_thread = newthr;
            timeq = 0;
            sigemptyset(&sigt);
            sigaddset(&sigt, SIGPROF);
            sigprocmask(SIG_UNBLOCK, &sigt, NULL);
            swapcontext(&(t2->thr_context), &(current_thread->thr_context));
        }
        else 
        {
            // No current thread? might be terminated
            current_thread = newthr;
            timeq = 0;
            sigemptyset(&sigt);
            sigaddset(&sigt, SIGPROF);
            sigprocmask(SIG_UNBLOCK, &sigt, NULL);
            swapcontext(&(dummy), &(current_thread->thr_context));
        }
    }
}

1 Ответ

1 голос
/ 06 ноября 2011

Кажется, что "ready_q" (заголовок списка готовых потоков?) Никогда не меняется, поэтому поиск потока с наивысшим приоритетом всегда находит первый подходящий элемент.Если два потока имеют одинаковый приоритет, только первый имеет шанс получить процессор.Есть много алгоритмов, которые вы можете использовать, некоторые основаны на динамическом изменении приоритета, другие используют своего рода вращение в очереди готовности.В вашем примере вы могли бы удалить выбранный поток с его места в очереди готовности и поместить на последнее место (это двойной связанный список, поэтому операция тривиальна и довольно недорога).Кроме того, я бы посоветовал вам рассмотреть проблемы производительности из-за линейного поиска в ready_q, поскольку это может быть проблемой, когда число потоков велико.В этом случае может быть полезна более сложная структура с разными списками потоков для разных уровней приоритета.Bye!

...