Алгоритм Петерсона

Тема в разделе "LANGS.C", создана пользователем osox, 9 мар 2010.

  1. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    как думаете можно ли этим пользоватся в винде учитывая что винда сможет в любой момент изменить приоритет потока с
    приоритетом в динамическом диапазоне ?
    алгоритм содержится в книге Э. Таненбаума Операционные системы

    /* Алгоритм Петерсона */

    Код (Text):
    1. #include <stdio.h>
    2. #include <windows.h>
    3.  
    4. #define N 2
    5.  
    6. static int turn;
    7. static int interested[N];
    8.  
    9. void enter_region(int thread)
    10. {
    11.     int other;
    12.     other = 1 - thread;
    13.     interested[thread] = TRUE;
    14.     turn = thread;
    15.     while (turn == thread && interested[other] == TRUE);
    16. }
    17.  
    18. void leave_region(int thread)
    19. {
    20.     interested[thread] = FALSE;
    21. }
    22.  
    23. static volatile long test_var;
    24.  
    25. DWORD WINAPI Thread(PVOID pvContext)
    26. {
    27.     int i = 0;
    28.     while (i++ < 100000)
    29.     {
    30.         enter_region((int)pvContext);
    31.         test_var++;
    32.         leave_region((int)pvContext);
    33.     }
    34.     return 0;
    35. }
    36.  
    37. int main(void)
    38. {
    39.     HANDLE hArr[N];
    40.     HANDLE hCrProcess;
    41.     int i;
    42.     hCrProcess = GetCurrentProcess();
    43.     SetPriorityClass(hCrProcess, NORMAL_PRIORITY_CLASS);
    44.     SetProcessPriorityBoost(hCrProcess, TRUE);
    45.     for (i = 0; i < N; i++)
    46.         hArr[i] = CreateThread(NULL, 0, Thread, (PVOID)i, 0, NULL);
    47.     WaitForMultipleObjects(i, hArr, TRUE, INFINITE);
    48.     for (i = 0; i < N; i++)
    49.         CloseHandle(hArr[i]);
    50.     printf("%d\n", test_var);
    51.     return 0;
    52. }
     
  2. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    Врезка из книги

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

    собственно высказывайте свои мнения по поводу этого алгоритма можно ли им пользоватся при организации спинлоков например с последующим переходом в режим ядра примерно как InitializeCriticalSectionAndSpinCount
    ;)
     
  3. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    osox
    Какой-то отфанарный набор фактов сгреблён в кучу. В чём вопрос, не ясно.
    Алгоритм Петерсона никакого отношения не имеет ни к винде, ни к инверсии, ни к динамическим приоритетам, ни к планированию в принципе.
    Поэтому независимо от планирования и ОС алгоритм использовать можно, но смысла не имеет. Его недостаток в том, что он всегда рассчитан на заранее известное число потоков. Приведенные enter/leave несмотря на параметризацию N подходят исключительно для двух потоков. Изменение N на число неравное двум сделает алгоритм неработоспособным.

    Ввиду налагаемого ограничения на число потоков применять алгоритм имеет смысл только при отсутствии подходящих атомарных инструкций у процессора (xchg у x86, swp у ARM, tas у MC68000 и т.п.).
    Кроме того busy waiting вообще никогда не был желательным. Поэтому встроенные в Windows ф-ии синхронизации используют busy waiting в минимально возможных количествах.

    Вывод: применение бессмысленно.
     
  4. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    l_inc

    ну как же не имеет отношения к планированию черным по белому написано что если в системе не заложено выделение квантов голодающим потокам то поток с более высоким приритетом при выходе из операции ввода вывода с повышенным приоритетом войдет в ожидание и фактически второй поток не выйдет из критической секции так как первый с высоким приритетом будет постоянно время забирать или другой сценарий у потоков одинаковые приритеты тогда этой проблемы не возникнет отсюда я и упомянул про приоритеты и планировщик разве нет связи ?
     
  5. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    l_inc

    разные оси разные планировщики одни ориентированны на пакетную обработку другие системы реального времени третьи интерактивные во всех этих случаях планировщик затачивается под конкретные нужды связь очевидна вставка про планировщик винды была сделана из за этого странно что Вы связи не видите
    этот алгоритм поведет себя по разному на системах с разными планировщиками связь все таки прямая
     
  6. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    l_inc

    и кстати Вы очень сильно ошибаетесь по поводу заточености алгоритма под два потока алгоритм расширяется это адлгоритм
    Декера не расширяется он действительно под два процесса или потока заточен а этот расширяется
     
  7. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    osox
    Проблема инверсии (которая, кстати, тоже совсем по другому выглядит) имеет отношение к взаимоисключающему доступу в принципе, а не к алгоритму Петерсона. Критические секции, как метод реализации взаимоисключающего доступа, есть необходимое средство в наборе возможностей ОС. Каким именно образом оно реализовано — вопрос десятый.
    Поэтому ещё раз: алгоритм Петерсона здесь никаким боком.
    Что значит "по разному"? Если реализация соответствует условиям (например, алгоритм для 2-х потоков и не более 2-х потоков работают в системе), то никаких "по-разному" не будет. Будет, как и планировалось, взаимоисключающий доступ. А если есть голодание, то с тем же успехом оно было бы и у спинлока на атомарной инструкции.
    Начнём с того, что я не говорил, что алгоритм нельзя переделать под другое число потоков. Я сказал, что приведенные enter/leave будут работать только для двух потоков. А то, что Петерсон расширяется на любое заранее фиксированное число потоков, — это, разумеется, верно.
     
  8. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    l_inc

    еще вопрос есть я часто в исходных кодах вижу что тип указателя на *void часто приводится явно кастом (type*)(void*)
    к нужному типу например после malloc в то же время достаточно много литература по ansi c конверитруют из void*
    в нужный тип без явного каста ptr = malloc(); к примеру
    последняя книга которую я читаю там из void* кастится в другой
    тип без явного каста тоесть конвертируется из (void*)->(type*)
    и из (type*)->(void*) без явного каста книга по стандарту ansi c
    так как же все таки правильно поступать в языке С просветите )
     
  9. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    l_inc

    есть подозрение что авторы часто не удосуживаются указать язык
    того на чем они писали если для плюсов код то тогда там вроде void* и другие не совместимы при такой конвертации (void*)->(type*) а обратно (type*)->(void*) можно поэтому и встречаются разные коды на многих форумах например с пометкой C++ сливают как С так и С++ да много где наблюдается несоответствие
    можно в чистом С делать без явного каста как считаете ?
     
  10. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    osox
    В си можно, насколько мне известно. В плюсах компилятор должен выдать как минимум предупреждение. К указателю на void можно везде приводить неявно.
    Но вообще это уже не ко мне. Я некомпетентен по вопросам стандартов. Моё правило такое: если компилятор ругается, то надо трижды подумать, имел ли я в виду именно это, а потом откастить. :)
     
  11. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    l_inc

    ясно спасибо надоела эта путаница с кастом смотриш одни исходники кастится другие смортиш нет сейчас посмотрел K&R ANSI C там снова кастится в разделе структуры пример с деревом поиска функа из книги
    struct tnode *talloc(void)
    {
    return (struct tnode*)malloc(sizeof(struct tnode));
    }
    затем
    открыл книгу искуство программирования на си тоже автор всю дорогу рассказывает что надо придерживатся стандарта в тоже время по всей книге прмеры типа typedef int *T; T a = malloc(); или char *p; p = malloc(); автор с 20 стажем или около того
    пишет тоже про ANSI C почему код разный
    не пониманию
    вообщем вопрос до конца не ясен каждый раз когда приходится присваивать из void*->type* эта неопределенность определено начинает надоедать ;)
     
  12. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    l_inc

    вот что нашел в K&R ANSI C электронная версия

    вообщем как понимаю до ANSI C надо было явно приводить (void*)->(type*) в ANSI C как я понял это не обязательно и даже может скрыть случайную ошибку

    а вот K&R ANSI C бумажная у меня дома

    КТО ПИШЕТ ЭТИ КНИГИ ? КАЗНИТЬ !!!
     
  13. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    l_inc

    или вот еще пример из Си я часто использую каллбеки например
    удобно передавать функциям обработки связного списка например для
    ForEachList(ProxyList, Attack);

    у ForEachList такой прототип

    typedef VOID(*ForEach)(PVOID Item, DWORD Tag, SIZE_T Size);
    VOID ForEachList(DLLIST List, ForEach pfn);

    ForEach принимает PVOID так как в списке можно хранить объекты разной структуры различаю по tag

    теперь возмем частый случай у меня в списке объеты одного типа
    например строки адреса проксей и функцию свою я определяю так
    VOID Attack(CONST PCHAR Proxy, DWORD Tag, SIZE_T Size)
    {
    /* body */
    }

    и передаю ForEachList(ProxyList, Attack);

    можно ли вместо

    VOID Attack(PVOID Proxy, DWORD Tag, SIZE_T Size)
    {
    CONST PCHAR pszProxy = Proxy;
    /* body */
    }

    писать сразу
    VOID Attack(CONST PCHAR Proxy, DWORD Tag, SIZE_T Size)
    {
    /* body */
    }

    избавляемся от каста тем более что void* и anothertype*
    взаимозаменяемы какой смысл внутри делать указатель на другой
    тип если можно параметром записать так удобнее по крайней мере мне

    вот этот вопрос меня тоже интересует можно так делать или нет ?
     
  14. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    osox
    Я так понимаю, что при вызове ForEachList(ProxyList, Attack); мы кастим уже не PCHAR в PVOID, а всё таки VOID(*)(PVOID Item, DWORD Tag, SIZE_T Size); в VOID(*)(CONST PCHAR Item, DWORD Tag, SIZE_T Size);. Такой кастинг указателей уже не прокатит бесследно. Но, как я уже сказал, я — не спец. Так что зря Вы мой ник прям в каждый пост заголовком.
     
  15. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    l_inc

    сегодня случайно прочитал в одной книге
    Herbert Schildt - C: The Complete Reference, 4th Edition
    В языке С допускается присваивание указателя типа void * указателю любого другого типа (и наоборот) без явного преобразования типа указателя. Тип указателя void * используется, если тип объекта неизвестен. Например, использование типа void * в качестве параметра функции позволяет передавать в функцию указатель на объект любого типа, при этом сообщение об ошибке не генерируется.
    В языке C++ требуется явно указывать преобразование типа указателей, в том числе указателей типа void *. Поэтому многие программисты используют в языке С явное преобразование для совместимости с C++.
     
  16. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    а сейчас когда в с99 много разных новых свойств которые с++ никогда не скомпилит заведомо можно и не беспокоится о совместимости не писать же на Си старой редакции только для совместимости с Си++ ? :)
     
  17. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    и вот еще из той же книги

     
  18. osox

    osox New Member

    Публикаций:
    0
    Регистрация:
    13 ноя 2009
    Сообщения:
    280
    кстати а какой смысл в том что в C++ указателю void * можно присвоить любой тип указателя а обратно нельзя ?
    в С и туда и обратно можно