Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Свой микропланировщик


Автор: IGanja 28.3.2012, 09:50
Пишу планировщик, который должен с заданной частотой запускать потоки. Потока два, основной поток процесса и бэкграунд поток. 
Задача раз в такт планировщика запускать одну итерацию основного поток, по завершению итерации оставшееся время такта отдавать бэкграунду. В следующий такт работа бэкграунда приостанавливается и запускается следующая итерация основного потока и так далее.

Принудительно устанавливаю выполнение процесса на конкретное ядро, чтобы потоки не выполнялись на разных ядрах, далее основному потоку ставлю приоритет Highest, бэкграунд потоку Idle. Устанавливаю ожидаемый таймер с автосбросом и запускаю.

Получаю совсем не то что хочу, в лучшем случае бэкграунд всегда успевает выполнится до конца, в худшем оба потока почему то начинают работать вместе. 

Почему бэкграунд не вытесняется более приоритетным потоком?

Ниже приведен код программы.
Код

#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <iostream>
using namespace std;

int FREQUENCY = 100; //Гц

void func(void)
{
        cout<<"main 1"<<endl;
        cout<<"main 2"<<endl;
        cout<<"main 3"<<endl;
        cout<<"main 4"<<endl;
        cout<<"main 5"<<endl;
        cout<<"main 6"<<endl;
        cout<<"main 7"<<endl;
        cout<<"main 8"<<endl;
        cout<<"main 9"<<endl;
        cout<<"main 10"<<endl;
}

DWORD WINAPI background_thread(PVOID pvParam)
{
    while(true)
    {
        Sleep(10);
        cout<<"bckgrnd 1"<<endl;
        cout<<"bckgrnd 2"<<endl;
        cout<<"bckgrnd 3"<<endl;
        cout<<"bckgrnd 4"<<endl;
        cout<<"bckgrnd 5"<<endl;
        cout<<"bckgrnd 6"<<endl;
        cout<<"bckgrnd 7"<<endl;
        cout<<"bckgrnd 8"<<endl;
        cout<<"bckgrnd 9"<<endl;
        cout<<"bckgrnd 10"<<endl;
    }
    return 0;
}

void main(void)
{
    int iter = 0;
    LARGE_INTEGER firstStart;
    const int unitPerSecond = 10000000;
    int freq_ms = 1000/FREQUENCY; //msec
    DWORD dwThreadId;

    HANDLE hBackgrnd = CreateThread(NULL, 0, background_thread, NULL, 0, &dwThreadId);// создание потока backgrnd

    SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS); // установка приоритета процесса
    SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST); // установка приоритета главного потока
    SetThreadPriority(hBackgrnd,THREAD_PRIORITY_IDLE); // установка приоритета background потока
    SetProcessAffinityMask(GetCurrentProcess(),1); // установка TASKa на конкретное ядро процессора

    // создание и настройка таймера
    firstStart.QuadPart = -(1*unitPerSecond);
    HANDLE hTimer = CreateWaitableTimer(NULL, FALSE, NULL); // таймер с автосбросом
    SetWaitableTimer(hTimer, &firstStart, freq_ms, NULL, NULL, FALSE); // настройка

    while(iter<2)
    {
        func();
        iter++;
        WaitForSingleObject(hTimer, INFINITE); // жду следующего кванта
    }
}


Автор: Dem_max 28.3.2012, 11:41
Цитата

Получаю совсем не то что хочу, в лучшем случае бэкграунд всегда успевает выполнится до конца,

Ты первым делом поток запустил и он тут же выполнился, потом только выполнилась func(). Все правильно.

Автор: GremlinProg 28.3.2012, 11:42
Цитата(IGanja @  28.3.2012,  11:50 Найти цитируемый пост)
Получаю совсем не то что хочу, в лучшем случае бэкграунд всегда успевает выполнится до конца, в худшем оба потока почему то начинают работать вместе. Почему бэкграунд не вытесняется более приоритетным потоком?

windows-многозадачная система, установка приоритетов не означает, что менее приоритетные потоки будут ожидать более приоритетных,

не надо понимать документацию так буквально

просто на менее приоритетные будет отдаваться меньше времени,
грубо говоря, т.с. "внутренняя частота" таких задач будет снижена в пользу более приоритетных

Автор: IGanja 29.3.2012, 18:41
Спасибо за помощь, решение нашел с помощью функций
SuspendThread(hBackgrnd);
ResumeThread(hBackgrnd);
обрамив ими задачу основного потока
Код

while(iter<2)
{
   SuspendThread(hBackgrnd);
   func();
   iter++;
   ResumeThread(hBackgrnd);
   WaitForSingleObject(hTimer, INFINITE); // жду следующего кванта
}


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)