2015-11-12 4 views
2

Рассмотрим следующие коды:мьютекса в RTOSes в этой конкретной ситуации

/*---------------------------------------------------------------------------- 
First Thread 
*---------------------------------------------------------------------------*/ 
void Thread1 (void const *argument) 
{ 
    for (;;) 
    { 
     osMutexWait(mutex, osWaitForever); 
       Thread1_Functions; 
     osMutexRelease(mutex); 
    } 
} 

/*---------------------------------------------------------------------------- 
    Second Thread 
*---------------------------------------------------------------------------*/ 
void Thread2 (void const *argument) 
{ 
    for(;;) 
    { 
     osMutexWait(mutex, osWaitForever); 
       Thread2_Functions; 
     osMutexRelease(mutex); 
    } 
} 

Насколько я заметил из RTOS's scheduling, RTOS назначить определенное время для каждой задачи и после того, как на этот раз закончится, он переключается на другая задача.
Затем в это конкретное время бесконечный цикл внутренней задачи, возможно, цикл повторяется несколько раз, пока не закончится конкретное время задачи.
Предположим, что задача завершена менее чем наполовину, тогда у нее есть время, чтобы выполнить эту задачу еще раз. в последней строке после освобождения мьютекса, тогда он достигнет мьютекса перед задачей2 во второй раз, правда ли?
Предположим, что таймер включен, когда MCU запускает Thread1_Functions во второй раз, затем task2 не работает, потому что mutex принадлежит задаче 1, RTOS запускает задачу 1 снова, и если таймер имеет место каждый раз в Thread1_Functions, тогда task2 не имеет шансов работать, Am I правда ?

ответ

2

Прежде всего, позвольте мне прояснить описанный вами способ планирования. Вы сказали: «RTOS назначает определенное время каждой задаче, и по прошествии этого времени она переключается на другую задачу». Этот метод планирования обычно называют «срезом времени». И все RTOS не всегда используют этот метод все время. Временной срез может использоваться для задач с одинаковым приоритетом (или если ОСРВ не поддерживает приоритеты задач). Но если задачи имеют разные приоритеты, тогда планировщик не будет использовать временную привязку и вместо этого будет планировать в соответствии с приоритетом задачи.

Но предположим, что две задачи в вашем примере имеют одинаковый приоритет, а планировщик - выбор времени.

  1. Thread1 проходит и получает мьютексы.
  2. Временной срез Thread1 истекает, и планировщик переключается на Thread2.
  3. Thread2 пытается получить мьютекс, но блокирует, так как Thread1 уже владеет мьютексом.
  4. Планировщик переключается обратно в Thread1, так как Thread2 заблокирован.
  5. Thread1 выпускает мьютексы.

Когда мьютекс освобожден, планировщик должен переключиться на любую задачу с более высоким приоритетом, ожидающую мьютекс. Но так как Thread2 является одним и тем же приоритетом, предположим, что планировщик не переключается, и Thread1 продолжает работать в пределах своего временного фрагмента.

  1. Thread1 пытается снова получить мьютекс.

В вашем сценарии Thread1 успешно получает мьютекс, и это может привести к тому, что Thread2 никогда не сможет работать. Чтобы это не происходило, служба мьютекса должна назначать приоритеты запросам мьютекса. Запросы Mutex из задач с более высоким приоритетом получают более высокий приоритет. И сначала нужно сначала запросить мьютексы с равных приоритетных задач. Другими словами, служба мьютекса должна помещать запросы с равными приоритетными задачами в очередь. Помните, что Thread2 уже имеет ожидающий запрос для мьютекса (шаг 3 выше). Поэтому, когда Thread1 пытается снова получить мьютекс (шаг 6), запрос Thread1 должен быть поставлен в очередь за предыдущим запросом Thread2. И когда второй запрос Thread1 для мьютекса попадает в очередь за запросом Thread2, планировщик должен блокировать Thread1 и переключиться на Thread2, предоставив мьютекс Thread2.

Обновление: Выше была только мысль о том, как неопределенная RTOS могла бы справиться с ситуацией, чтобы избежать голода Thread2. Вы не упомянули конкретную ОС реального времени, пока не найдете свой комментарий ниже. Я не знаю, работает ли Keil RTX, как описано выше. И теперь мне интересно, каков ваш вопрос на самом деле.

Вы спрашиваете, что сделает Keil RTX в этой ситуации? Я не уверен. Вам нужно будет посмотреть код для osMutexRelease(), чтобы узнать, переключается ли он на задачу с тем же приоритетом. Также посмотрите на osMutexWait(), чтобы узнать, как он приоритезирует задачи одного и того же приоритета.

Или вы заявляете, что Keil RTX позволяет Thread2 голодать в этой ситуации, и вы спрашиваете, как это исправить. Чтобы исправить эту ситуацию, вы можете вызвать osThreadYeild() после освобождения мьютекса. Как это:

void Thread1 (void const *argument) 
{ 
    for (;;) 
    { 
     osMutexWait(mutex, osWaitForever); 
       Thread1_Functions; 
     osMutexRelease(mutex); 
     osThreadYeild(); 
    } 
} 
+0

Пусть в 2th секции, квант времени истек на теле нити 2, что происходит знает, я использую Keil RTX, который используется упреждающей раунд время малиновки задачи schedling.Each выполняется только один!? или он работает всегда и раньше, пока не появится следующий таймер? –

+0

@MahmoudHD См. Обновление в моем ответе выше. – kkrambo

Смежные вопросы