реклама на сайте
подробности

 
 
> Хитровывернутый вопрос про RTOS, с интервью..
InsolentS
сообщение Jul 31 2014, 01:00
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 414
Регистрация: 8-06-06
Пользователь №: 17 897



Всем привет!
Недавно был на интервью в одной компании и "застрял" на вопросе про RTOS. После недели поисков ответ так и не был найден..
Условие задачи такое: есть 5 потоков, каждый из них увеличивает в цикле общую переменную count на 1. После завершения работы этих потоков, значение count выводится на экран.
Код
unsigned int count = 0;
void thread(void)
{
  unsigned int i;
  for(i = 0; i < 5; i++)
  {
    count++;
  }
}

void main(void)
{
  thread_create(thread, 5); // Создаём 5 экземпляров потока thread и запускаем их
  thread_join(); // Ждём пока все 5 потоков завершатся
  printf("%u", count); // Выводим значение count на экран
}

Внимание вопрос: почему программа печатает 2??
Договорились с интервьювером, что операция count++ состоит из 3х ассемблерных команд:
Код
  LDR reg, count
  ADD reg, #1
  STR reg, count

Т.к. переменная count не защищена ни мьютексом, ни критической секцией, самый пессимистичный вариант, который я "раскрутил" выглядит так:
Код
// начало работы thread1
  LDR reg, count // count = 0, thread1.reg = 0
  ADD reg, #1 // thread1.reg = 1
// thread1 вытеснен планировщиком, начало работы thread2
  LDR reg, count // count = 0, thread2.reg = 0
  ADD reg, #1 // thread2.reg = 1
  STR reg, count // count = 1
// thread2 завершил работу, управление возвращается к thread1
  STR reg, count // count = 1

т.е. в результате один поток делает override результата второго потока и count = 1 после выполнения всех потоков (а не 5, как было бы с мьютексом).
Но: хоть один из потоков все равно увеличит count на 1 в этой схеме, т.е. в результате работы программы count будет не меньше, чем 5.
Как же получается 2? (со слов интервьювера, он наблюдал такой эффект в реальном железе). Подсказка от интервьювера: результат не зависит ни от количества потоков, ни от количества итераций в цикле for


--------------------
Курильщик даташитов со стажем
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
psL
сообщение Aug 3 2014, 18:18
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 5-08-05
Пользователь №: 7 390



Типа ОСь очень реального времениsm.gif Видимо 2, потому что первый поток из пула успевает инкрементировать счетчик, поскольку пока еще нет потоков, способных ему помешать, последний поток из пула инкрементирует счетчик, поскольку потоки, способные ему помешать уже завершились.
Go to the top of the page
 
+Quote Post
Lagman
сообщение Aug 3 2014, 20:04
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Цитата(psL @ Aug 3 2014, 22:18) *
Типа ОСь очень реального времениsm.gif Видимо 2, потому что первый поток из пула успевает инкрементировать счетчик, поскольку пока еще нет потоков, способных ему помешать, последний поток из пула инкрементирует счетчик, поскольку потоки, способные ему помешать уже завершились.

Планировщик переключает задачи после каждой инструкции!?
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Aug 4 2014, 21:06
Сообщение #4


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(Lagman @ Aug 4 2014, 00:04) *
Планировщик переключает задачи после каждой инструкции!?


вести речь о переключении задач бесмысленно. т.к. фаза старта ниток не синхронизируется. в некоторых осях это вообще может не застартовать
секундами-минутами-часами-сутками... код в этом плане левый. нет синхронной фазы готовности всех ниток. типичная ошибка начинающих
программеров. Начинает сыпаться или странно себя вести, при ударных нагрузках на серваках. Особенно когда на время жизни ниток
начинает навешиваться некая логика. Например общая готовность, или там обслуживание клиентов и т.п. вещи...

теоретически-гепотетический код. хорошая тема для начала задушевной беседы, и больше ни для чего. результат не определён вообще...
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Aug 5 2014, 07:43
Сообщение #5


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(kolobok0 @ Aug 5 2014, 00:06) *
вести речь о переключении задач бесмысленно. т.к. фаза старта ниток не синхронизируется. в некоторых осях это вообще может не застартовать
секундами-минутами-часами-сутками... код в этом плане левый. нет синхронной фазы готовности всех ниток. типичная ошибка начинающих
программеров. Начинает сыпаться или странно себя вести, при ударных нагрузках на серваках. Особенно когда на время жизни ниток
начинает навешиваться некая логика. Например общая готовность, или там обслуживание клиентов и т.п. вещи...

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


Что это за загадочная "синхронная фаза"?

Если код основан на POSIX, то можно кое что восстановить.

pthread_create создает и устанавливает готовность задач.
Поскольку приоритет не указывается, то логично предположить, что он будет равен приоритету задачи main.

Рассматриваем что могло быть на реальном железе:

До вытеснения тут явно не дойдет. Тик осей редко бывает короче 10 мс.
Значит вся работа задач начнется после вызова thread_join
Без аргументов thread_join не бывает, возможно это переопределение оригинальной функции и в этой реализации ожидание всех задач производится по очереди с помощью семафоров.
Но возможно реализован механизм ожидания маски флагов от всех задач сразу.
В любом случае задачи выполнятся последовательно не вытесняя друг друга, поскольку имеют одинаковый приоритет.
Случится прерыванию во время выполнения тех задач крайне мала, поскольку все задачи выполнятся менее чем за микросекунду.

Но как в thread_join будет идентифицироваться каждая задача? Передачи дополнительных аргументов с уникальными значениями задачам не видно.
В процедуре thread_join наверняка произойдет ошибка после того как там попытаются ожидать окончания нескольких неразличимых задач.

И тогда произойдет неожиданный выход из thread_join.
Далее заход в функцию printf и там возможно где-то ось не на долго переключится на одну из оставшихся активных задач во время ожидания прерывания по готовности чего-то периферийного.
Вот тут и успеет какая-то из задач инкрементировать count до прерывания и переключения контекста на драйвер printf.

Во всяком случае у меня аналогичный код под MQX работает идеально при любом уровне оптимизации и всегда выдает 25
Код
const TASK_TEMPLATE_STRUCT  MQX_template_list[] =
{
  /* Task Index,    Function,                 Stack,  Priority,          Name,         Attributes,                                                         Param, Time Slice */
  { MAIN_IDX,        Main_task,                1500,   MAIN_ID_PRIO,      "Main",      MQX_FLOATING_POINT_TASK + MQX_AUTO_START_TASK,                       0,     0 },
  { TST_TSK_IDX,     Test_Task,                1500,   MAIN_ID_PRIO,      "TestTask",  MQX_FLOATING_POINT_TASK,                                             0,     0 },
  { 0 }
};

unsigned int count = 0;

LWEVENT_STRUCT lwevg;

/*-------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------*/
void Test_Task(unsigned int initial_data)
{
  unsigned int i;
  for(i = 0; i < 5; i++)
  {
    count++;
  }
  _lwevent_set(&lwevg, initial_data);
}
/*-------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------*/
void Main_task(unsigned int initial_data)
{
  _lwevent_create(&lwevg, LWEVENT_AUTO_CLEAR);

  _task_create(0, TST_TSK_IDX, 1);
  _task_create(0, TST_TSK_IDX, 2);
  _task_create(0, TST_TSK_IDX, 4);
  _task_create(0, TST_TSK_IDX, 8);
  _task_create(0, TST_TSK_IDX, 16);

  _lwevent_wait_for(&lwevg, 1+2+4+8+16,TRUE,NULL);
  printf("Count =%u  \r\n", count);
}




Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- InsolentS   Хитровывернутый вопрос про RTOS   Jul 31 2014, 01:00
- - RobFPGA   Приветствую! Скорее всего он "разводил...   Jul 31 2014, 09:54
- - Fat Robot   Переменная count не является volatile, поэтому пре...   Jul 31 2014, 10:35
- - wangan   Может у него был 8 битный микроконтроллер, а у нег...   Jul 31 2014, 12:08
- - gerber   Неправильно реализована функция printf на железке,...   Jul 31 2014, 13:42
|- - Mahagam   QUOTE (gerber @ Jul 31 2014, 16:42) Непра...   Jul 31 2014, 15:03
- - Lagman   25. Почему? Патамушта! (кооперативная, вытесн...   Jul 31 2014, 15:55
- - InsolentS   Прошу прощения, по условиям задачи RTOS вытесняюща...   Jul 31 2014, 18:09
- - ViKo   Для начала неплохо бы понять, в какой ОС есть функ...   Jul 31 2014, 18:17
|- - InsolentS   Цитата(ViKo @ Jul 31 2014, 23:17) Для нач...   Jul 31 2014, 18:27
- - Fedor   Нагло врет ваш интервьюер, если поток будет 1 все ...   Jul 31 2014, 19:15
- - DASM   99.9 % дело не вытеснении, на 32 разрядном проце к...   Jul 31 2014, 19:57
- - ViKo   Условная ОС не может быть проверена в железе, как ...   Jul 31 2014, 20:00
- - InsolentS   Тут дело не в особенностях какого-то конкретного ж...   Aug 1 2014, 05:39
|- - ViKo   Цитата(InsolentS @ Aug 1 2014, 08:39) Тут...   Aug 1 2014, 05:54
|- - andrew_b   Цитата(ViKo @ Aug 1 2014, 09:54) А разве ...   Aug 4 2014, 06:17
- - adnega   ЦитатаПодсказка от интервьювера: результат не зави...   Aug 1 2014, 05:59
- - ZASADA   что возвращает вызываемая функция void thread(void...   Aug 1 2014, 06:28
|- - ViKo   Цитата(ZASADA @ Aug 1 2014, 09:28) что во...   Aug 1 2014, 06:31
- - DASM   А какой это язык программирования ?   Aug 1 2014, 08:25
- - ZASADA   типа с   Aug 1 2014, 08:39
- - InsolentS   На работу всё-таки взяли, попробую найти там этого...   Aug 2 2014, 04:19
- - x893   Всё гораздо проще - просто посмотрите дебаггером -...   Aug 3 2014, 13:29
|- - InsolentS   Цитата(x893 @ Aug 3 2014, 18:29) Всё гора...   Aug 3 2014, 18:13
|- - AlexandrY   Цитата(InsolentS @ Aug 3 2014, 21:13) Спа...   Aug 4 2014, 06:48
|- - psL   Цитата(Lagman @ Aug 4 2014, 00:04) Планир...   Aug 3 2014, 21:53
||- - AndrewN   QUOTE (psL @ Aug 4 2014, 00:53) В реально...   Aug 5 2014, 10:04
||- - Mahagam   QUOTE (AndrewN @ Aug 5 2014, 13:04) Ключе...   Aug 5 2014, 10:09
- - AndrewN   QUOTE (InsolentS @ Jul 31 2014, 04:00) Не...   Aug 5 2014, 09:57
|- - AlexandrY   Цитата(AndrewN @ Aug 5 2014, 12:31) P.S. ...   Aug 5 2014, 10:01
||- - AndrewN   QUOTE (AlexandrY @ Aug 5 2014, 13:01) Да,...   Aug 5 2014, 10:07
|||- - AlexandrY   Цитата(AndrewN @ Aug 5 2014, 13:07) Да бр...   Aug 5 2014, 10:14
|||- - AndrewN   QUOTE (AlexandrY @ Aug 5 2014, 13:14) Есл...   Aug 5 2014, 10:21
||- - AndrewN   QUOTE (AlexandrY @ Aug 5 2014, 13:01) Да ...   Aug 5 2014, 10:09
||- - AlexandrY   Цитата(AndrewN @ Aug 5 2014, 13:09) Вы ме...   Aug 5 2014, 10:19
||- - AndrewN   QUOTE (AlexandrY @ Aug 5 2014, 13:19) Мне...   Aug 5 2014, 10:27
||- - AlexandrY   Цитата(AndrewN @ Aug 5 2014, 13:24) Совер...   Aug 5 2014, 10:31
||- - AndrewN   QUOTE (AlexandrY @ Aug 5 2014, 13:31) гов...   Aug 5 2014, 10:55
|- - Mahagam   QUOTE (AndrewN @ Aug 5 2014, 12:31) Хорош...   Aug 5 2014, 10:04
|- - AndrewN   QUOTE (Mahagam @ Aug 5 2014, 13:04) решен...   Aug 5 2014, 10:15
|- - AlexandrY   Цитата(AndrewN @ Aug 5 2014, 13:15) Мы же...   Aug 5 2014, 10:24
||- - den_po   Цитата(AlexandrY @ Aug 5 2014, 14:24) Тик...   Aug 5 2014, 12:29
|- - Mahagam   QUOTE (AndrewN @ Aug 5 2014, 13:15) Это п...   Aug 5 2014, 10:55
|- - AlexandrY   Цитата(Mahagam @ Aug 5 2014, 13:55) какое...   Aug 5 2014, 11:02
|- - AndrewN   QUOTE (Mahagam @ Aug 5 2014, 13:55) Ни од...   Aug 5 2014, 11:27
|- - Mahagam   QUOTE (AndrewN @ Aug 5 2014, 14:27) Увы, ...   Aug 5 2014, 11:37
||- - AndrewN   QUOTE (Mahagam @ Aug 5 2014, 14:37) вы то...   Aug 5 2014, 12:39
||- - AlexandrY   Цитата(AndrewN @ Aug 5 2014, 15:30) Я поп...   Aug 5 2014, 12:42
|||- - AndrewN   QUOTE (AlexandrY @ Aug 5 2014, 16:42) Ну ...   Aug 5 2014, 12:50
|||- - AlexandrY   Цитата(AndrewN @ Aug 5 2014, 15:50) P.S. ...   Aug 6 2014, 10:48
||- - AlexandrY   Цитата(AndrewN @ Aug 5 2014, 15:39) Ребят...   Aug 5 2014, 12:54
||- - Mahagam   QUOTE (AndrewN @ Aug 5 2014, 15:39) Неизв...   Aug 5 2014, 15:09
||- - AndrewN   QUOTE (Mahagam @ Aug 5 2014, 19:09) отсле...   Aug 5 2014, 16:06
|- - AlexandrY   Цитата(AndrewN @ Aug 5 2014, 14:27) Алгор...   Aug 5 2014, 12:26
- - ViKo   Ну, теоретически (практически тоже) можно допустит...   Aug 5 2014, 10:28
- - adnega   CODE задача А задача В задача Х ...   Aug 5 2014, 12:55
- - juvf   аш 4 страници настучали.... 1) а кто пробовал это...   Aug 5 2014, 18:05
- - AndrewN   Жаль, что не удалось узнать, что думает экзаминато...   Aug 7 2014, 12:35
- - InsolentS   Цитата(AndrewN @ Aug 7 2014, 18:35) Жаль,...   Jan 24 2015, 02:52


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 19:36
Рейтинг@Mail.ru


Страница сгенерированна за 0.01491 секунд с 7
ELECTRONIX ©2004-2016