LINUX.ORG.RU

SCHED_FIFO и pthread_cond_wait vs. sched_yield

 , ,


0

1

очередной вопрос из серии «не распарсил man», но все-таки :)

Хочу назначить одному небольшому потоку scheduling policy SCHED_FIFO. В мане написано, что поток станет в конец очереди исполнения после sched_yield, но в потоке крутится цикл, который ждет события (pthread_cond_wait). И по-идее, мы все-равно уйдем спать...
Вот я и думаю, насколько корректно забить на sched_yield в таком случае, утитывая, что таких тредов может быть несколько?

p.s. поток мониторит события на железяке

p.p.s. сенкс ин эдвэнс, там, и все такое :)

★★★★★

Последнее исправление: metawishmaster (всего исправлений: 1)

Ответ на: комментарий от tailgunner

про cond_vars придумали FTDI-ные чуваки... но они только сигналят, не устанавливая «вспомогательную» переменную в состояние, отличное от нуля, потому и тред такой

// конечно, можно было бы сделать и pthread_cond_timedwait, но ждать мы можем долго...

metawishmaster ★★★★★
() автор топика
Последнее исправление: metawishmaster (всего исправлений: 2)
Ответ на: комментарий от metawishmaster

Когда в одном посте упомянуты SCHED_FIFO, sched_yield и цикл ожидания, это само по себе странно, так что нужны детали. Я вот не понимаю, откуда вообще взялась мысль использовать sched_yield, если ожидание реализовано разумно - т.е. _ожиданием_ на condvar, а не ее опросом (хотя как можно ждать события от железки на condvar, я тоже не понимаю).

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

sched_yield всплыл, когда я перечитывал ман про шедулинг, там написано только «When a running thread issues the sched_yield() function, the thread becomes the tail of the thread list for its priority». Написали бы что-нить типа «When a running process going to sleep state...» было бы определенней %)

а непоссредственно _событие_ от железяки ждет FTDI. а чтоб о нем узнало приложение, нужно «заказать» оповещение с помощью FT_SetEventNotification
и у них же определена структура, что-то вроде (стандартный паттерн использования condvars)

struct event_t {
    pthread_cond_t condition;
    pthread_mutex_t mutex;
    int state;
};

но беда в том, что state они не трогают вообще, и об их событии можно узнать только если заранее ждать

metawishmaster ★★★★★
() автор топика

Хочу назначить одному небольшому потоку scheduling policy SCHED_FIFO

Зачем?

В мане написано, что поток станет в конец очереди исполнения после sched_yield

Зачем???

но в потоке крутится цикл, который ждет события (pthread_cond_wait)

Тогда зачем тебе SCHED_FIFO? Все равно тред будет большую часть времени ждать cond_broadcast...

Вот я и думаю, насколько корректно забить на sched_yield в таком случае, утитывая, что таких тредов может быть несколько?

С вероятностью в 95% sched_yield не нужен, ибо только затормозит все остальнные потоки, которые сделали mutex_lock...

shkolnick-kun ★★★★★
()
Ответ на: комментарий от metawishmaster

но беда в том, что state они не трогают вообще, и об их событии можно узнать только если заранее ждать

state нужен для того, чтобы можно было с одной условной переменной броадкастить и сигналить несколько видов событий, то есть записали в state «вид события» - сделали broadcast/signal...

Если state не используется, значит там только один вид событий.

shkolnick-kun ★★★★★
()
Ответ на: комментарий от metawishmaster

Я так и не понял, какую задачу планировалось решить sched_yield, но при разумно сделанном ожидании на condvar (т.е. именно ожидании, а не опросе) sched_yield не нужен.

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

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 2)
Ответ на: комментарий от shkolnick-kun

из-за того, что они не используют этот state, http://www.ftdichip.com/Support/Knowledgebase/index.html?ft_seteventnotification.htm работать не будет - там будет логическая ошибка, когда ждать начинаешь уже после того, как просигналил.

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от shkolnick-kun

ответ на первое «Зачем?» будет ниже, в ответе tailgunner
на второе - так решили при разработке libpthread :)
на третье... да тоже, ниже будет подробнее

да, про sched_yield я только хотел узнать, «насколько корректно забить на sched_yield», учитывая, что все-равно спим на cond_wait'e

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

ну sched_yield только из-за упоминания в том мане, если б я его не прочитал (с дуру), то и вопроса бы не было.

там идейка такая: раз FTDI не устанавливает state (у них переменная называется iVar), то о событии мы можем узнать только если _уже_ будем ждать. В ряде случаев, такое проходит, но не во всех и не всегда. Потому я вводу еще один поток:

void* event_helper(void *arg)
{
    int devNo = *(int *)arg;
    msp_BOOL *shutdown = &bus.devices[devNo].threads.shutdown;
    ThreadEvent *event = bus.devices[devNo].locks.recv_event;
    ThreadEvent *coevent = bus.devices[devNo].locks.recv_coevent;

    while (!*shutdown) {
        FT_SetEventNotification(bus.devices[devNo].ftHandle, FT_EVENT_RXCHAR, event)

        threadEventWait(event, NULL);
        threadEventSet(coevent);
        threadEventReset(event);
    }    
}

чтобы как можно быстрее встать на ожидание события от либы и не пропустить ничего. Когда событие получи, тут де кидаю свое событие, вот только threadEventSet устанавливает coevent->state = 1, чтобы поток, который делает основную работу ничего не пропустил.

вот как-то так...

а, и да, сейчас все работает как часики :)

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от metawishmaster

Попробуй вот так:

FT_HANDLE ftHandle; 
FT_STATUS ftStatus;
EVENT_HANDLE eh;
DWORD EventMask;

ftStatus = FT_Open(0, &ftHandle);
if(ftStatus != FT_OK) {
   // FT_Open failed
   return;
}

pthread_mutex_init(&eh.eMutex, NULL);
pthread_cond_init(&eh.eCondVar, NULL);

EventMask = FT_EVENT_RXCHAR | FT_EVENT_MODEM_STATUS;
//We don't want event to leak, so...
pthread_mutex_lock(&eh.eMutex);
//Now may setup event...
ftStatus = FT_SetEventNotification(ftHandle, EventMask, (PVOID)&eh);

while(NEED_TO_DO_WORK())
{
  DWORD EventDWord;
  DWORD RxBytes;
  DWORD TxBytes;
  DWORD Status;

  pthread_cond_wait(&eh.eCondVar, &eh.eMutex);

  FT_GetStatus(ftHandle,&RxBytes,&TxBytes,&EventDWord);
  if (EventDWord & FT_EVENT_MODEM_STATUS) {
    // modem status event detected, so get current modem status
    FT_GetModemStatus(ftHandle,&Status);
    if (Status & 0x00000010) {
          // CTS is high
    }
    else {
          // CTS is low
    }
    if (Status & 0x00000020) {
          // DSR is high
    }
    else {
          // DSR is low
    }
  }
  if (RxBytes > 0) {
    // call FT_Read() to get received data from device
  }
}
pthread_mutex_unlock(&eh.eMutex);

FT_Close(ftHandle); 

shkolnick-kun ★★★★★
()
Ответ на: комментарий от shkolnick-kun

а зачем? мютексы сами по себе тормозные товарищи... а если залочить тот мютекс, что мы передает во FT_SetEventNotification, то все зависнет, потому что там внутри тоже будут пробовать его залочить. ну, конечно, если они придерживаются «политики партии» (man pthread_cond_signal) :)

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от metawishmaster

мютексы сами по себе тормозные товарищи...

Они у тебя уже используются, так что придется пользоваться.

(man pthread_cond_signal) :)

Мьютекс освобождается автоматически, и все, что надо, отвисает обратно.

man pthread_cond_wait.

shkolnick-kun ★★★★★
()
Ответ на: комментарий от metawishmaster

Чтобы все было совсем правильно надо захватывать мьютекс до вызова FT_Open

shkolnick-kun ★★★★★
()
Ответ на: комментарий от shkolnick-kun

ну то, что pthread_cond_wait временно освобождает мютекс я знаю :)

сейчас попробубую по-раньше его блокировать...

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от metawishmaster

Ты уверен, что делал именно так? У меня зават и освобождение мьютекса за пределами цикла...

while (!*shutdown) {
        FT_SetEventNotification(bus.devices[devNo].ftHandle, FT_EVENT_RXCHAR, event)
/*...*/
}

Ты уверен, что это надо делать больше одного раза?

shkolnick-kun ★★★★★
()
Ответ на: комментарий от shkolnick-kun

вот я сейчас поставил тест на 10*10^6 итераций, когда захват/освобождение мютнкса за пределами цикла

а если FT_SetEventNotification вынести из чикла, то она сбивается :-\
не знаю чей это косяк, но valgrind отказывается принимать любую прогу, слинкованную c libftd2xx :-\

metawishmaster ★★★★★
() автор топика
Ответ на: комментарий от metawishmaster

Это косяк libftd2xx судя по всему...

Суть в том, что должно быть 2 условных переменных/семафоров, чтобы можно было используя документированные API сделать как в твоем примере кода....

shkolnick-kun ★★★★★
()
Ответ на: комментарий от shkolnick-kun

ну да, так и есть - event и coevent...

но начальству не нравится мой маааленький поток %) поэтому, сейчас проверю еще раз беспоточную реализацию, но уже с Вашими поправками :)

metawishmaster ★★★★★
() автор топика
Последнее исправление: metawishmaster (всего исправлений: 2)
Ответ на: комментарий от shkolnick-kun

и, кстати, я думаю, что и свою iVar они тоже должны были выставлять в что-то отличное от нуля...

metawishmaster ★★★★★
() автор топика
Последнее исправление: metawishmaster (всего исправлений: 1)
Ответ на: комментарий от metawishmaster

ну да, так и есть - event и coevent...

А это стандартный интерфейс, или что-то для внутреннего использования?

Если стандартный, то лучше использовать его, если нет...даже не знаю, что тут посоветовать...

shkolnick-kun ★★★★★
()
Ответ на: комментарий от shkolnick-kun

не, там event - событие от FTDI и coevent - мое событие, которое можно поймать и после того, как оно просигналится

metawishmaster ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.