Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: TEventFlag
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > scmRTOS
gladov
Объясните плз, почему TEventFlag.Wait() работает по-разному (очищает флаг или нет) в зависимости от того взведен флаг на момент запроса или нет? Я для себя никаких плюсов этого не вижу, а сумятицу в голову (в мою конкретно) вносит. Насколько понял, это сделано для множественной побудки, т.е. если в ожидании уснули вдвоем, то оба и проснутся. Но кто же должен тогда очистить флаг? Оба сразу? А если один из проснувшихся (первый) хочет инициировать новую операцию с новым ожиданием флага, а второй потом проснется и без разбора очистит флаг?

Вообще идея понятна но смущает то, что выйдя из wait() я не знаю, очищен ли уже флаг или нет. А проверять последующим вызовом IsSignaled() уже нельзя, т.к. ее результат может оказаться невалидным, т.к. между wait() и IsSignaled() может что-то произойти, а в критическую секцию их заключить нельзя т.к. возможно ожидание флага от прерывания. Вот и не срастается у меня в голове идеология - как же правильно по задумке автора(ов) работать с флагами?
Сергей Борщ
Цитата(gladov @ Nov 11 2010, 11:03) *
Объясните плз, почему TEventFlag.Wait() работает по-разному (очищает флаг или нет) в зависимости от того взведен флаг на момент запроса или нет? Я для себя никаких плюсов этого не вижу, а сумятицу в голову (в мою конкретно) вносит.
Нет, флаг чистится всегда если есть хоть один ждущий процесс. Будятся все ждущие процессы и чистится флаг.
Цитата(gladov @ Nov 11 2010, 11:03) *
Вообще идея понятна но смущает то, что выйдя из wait() я не знаю, очищен ли уже флаг или нет.
Должен быть очищен. В момент выхода из wait() он может быть уже снова взведен, но в момент пробуждения ждущего процесса он очищается.
dxp
Идея простая: когда флаг сигналится, это означает, что произошло событие (которое ожидает один [или несколько] процесс[ов]). При этом все ожидающие (процессы) будут переведены из спячки в активное состояние, а управление получат в соответствии со своими приоритетами. Флаг сбрасывает первый из ожидающих (самый приоритетный), но это не отменяет того, что остальные процессы, которые успели встать на ожидание флага до возникновения события, тоже станут активными - т.е. дождавшимися события, которое они хотели.
gladov
Цитата(Сергей Борщ @ Nov 11 2010, 14:07) *
Нет, флаг чистится всегда если есть хоть один ждущий процесс. Будятся все ждущие процессы и чистится флаг.
Должен быть очищен. В момент выхода из wait() он может быть уже снова взведен, но в момент пробуждения ждущего процесса он очищается.


Что-то я не пойму. smile3046.gif

Вот код из ветки https://scmrtos.svn.sourceforge.net/svnroot...os/trunk/Common, 268 revision:
Код
bool OS::TEventFlag::Wait(TTimeout timeout)
{
    TCritSect cs;

    if(Value)                                           // if flag already signaled
    {
        Value = efOff;                                  // clear flag
        return true;
    }
    else
    {
        TBaseProcess* p = Kernel.ProcessTable[Kernel.CurProcPriority];
        p->Timeout = timeout;
        TProcessMap PrioTag = GetPrioTag(Kernel.CurProcPriority);

        SetPrioTag(ProcessMap, PrioTag);                // put current process to the wait map
        ClrPrioTag(Kernel.ReadyProcessMap, PrioTag);    // remove current process from the ready map

        Kernel.Scheduler();

        p->Timeout = 0;

        if( !(ProcessMap & PrioTag) )                   // if waked up by signal() or signal_ISR()
            return true;

        ClrPrioTag(ProcessMap, PrioTag);                // otherwise waked up by timeout or by
        return false;                                   // OS::ForceWakeUpProcess(), remove process from the wait map
    }
}


В ветке else я не вижу очистки флага. Да и вопрос возник-то из практики: думал, что флаг сбрасывается всегда, написал некий код, запускаю - то работает, то нет. Оказалось, что флаг иногда остается взведенным.

Цитата
Идея простая: когда флаг сигналится, это означает, что произошло событие (которое ожидает один [или несколько] процесс[ов]). При этом все ожидающие (процессы) будут переведены из спячки в активное состояние, а управление получат в соответствии со своими приоритетами. Флаг сбрасывает первый из ожидающих (самый приоритетный), но это не отменяет того, что остальные процессы, которые успели встать на ожидание флага до возникновения события, тоже станут активными - т.е. дождавшимися события, которое они хотели.


Да в общем и целом, конечно понятно. А как разбуженные узнают, кто из них сейчас самый приоритетный ИЗ ОЖИДАЮЩИХ? Ведь самый-самый мог сейчас события и не ждать. Но мой вопрос даже не в том "почему сделано так, а не эдак", а как имея данный механизм корректно вручную из процесса флаг сбрасывать? И почему не сделали сброс внутри wait()? Ведь сам факт побудки процесса с результатом true уже говорит о том, что событие произошло! Зачем мне после выхода еще анализировать что-то и сбрасывать флаг?
Конечно, в самом простом случае, когда один сигналит, а другой ждет, можно тупо всегда после wait() делать сброс, но тогда небольшой оверхед получим.

Посмотрел внимательнее и понял, что флаг не взводится если его уже ждут процессы. А у меня он видимо все-же не "оставался взведенным", а уже сигналил повторно. Думаю, вопрос закрыт...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.