Аналог EnterCriticalSection/LeaveCriticalSection в юзермоде

Тема в разделе "WASM.WIN32", создана пользователем Rustem, 13 дек 2008.

  1. Rustem

    Rustem New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2004
    Сообщения:
    429
    Адрес:
    Russia
    Приветствую.
    В общем сабж.
    Нужно реализовать синхронизацию потоков без этих функций
     
  2. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    Rustem
    А мьютексы заюзать? Религия не позволяет?
    Можно семафоры заюзать.
    А еще почитайте Рихтера. Там целая глава про синхронизацию.
     
  3. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Тоесть kernel32 не юзоется, тогда заюзай ntdll, RtlEnterCriticalSection() и etc.
     
  4. Rustem

    Rustem New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2004
    Сообщения:
    429
    Адрес:
    Russia
    Я не точно сформулировал вопрос,
    необходимо минимальное использование АПИ, в идеале вообще без них
    Т.е. без RtlCriticalSection и без мутексов
     
  5. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Rustem
    Необходим обьект, на котором поток будет ждать первый поток, вошедший в критическую секцию. Эвент, мьютекс и др. должно создать ядро, без этих обьектов никак нельзя реализовать подобный механизм, если использовать подобие спин-блокировок то это сильно будет грузить систему. Да и зачем так извращатьсо, по любому процесс использовать будет критические секции.
     
  6. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Ну тогда остается только юзать собственный флаг занятости и накручивать циклы до посинения процессора, т.к. sleep и т.п. видимо тоже ни-изя ;)
     
  7. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    leo
    Все верно вы говорите
    Rustem
    В этом случае уже используют собственные реализации критических секций. Собственное планирование, а так же вы сами должны будете создать способы разрешения тупиков, алгоритм банкира и тп.
    Вот вам ссылка
    http://www.citforum.ru/operating_systems/sos/glava_6.shtml

    А вообще это все проходят в университетском курсе "Операционные системы"
     
  8. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    Вот в чём я не согласен с Рихтером так это в том что это наихудший вариант из возможных ;) Конечно если потоку обратившемуся к общим данным больше нечего делать как тупо ждать их готовности, то конечно же лучше поручить системе усыпить\разбудить его. Но так бывает не всегда - например есть поток с пользовательский интерфейсом, и поток - рабочая лошадка, который делает тяжёлый расчёт или работает с периодически тормозящей сетью и т.п. - здесь уже совсем неуместно усыплять интерфейсный поток поскольку тогда исчезает сам смысл разделения программы на потоки и лучше проверив свой флаг (или группу флагов) продолжить отображать на экране то что можно и строить комады рабочему потоку в очередь, которую он увидит когда освободится.
    Например в StrongDC очень раздражает что при подвисаниях сети пользовательский интерфейс тоже глухо зависает.
     
  9. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    Y_Mur
    Но на самом то деле есть разные алгосы планирования. Хотя я с вами согласен, рихтер смухлевал. В реальной жизни (при проектировании систем жизнеобеспечения и тп) лучше так не делать.
     
  10. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Y_Mur
    Не очень подходящий пример, т.к интерфейсный поток может и вздремнуть без ущерба интерфейсу, если поставит себе будильник MsgWaitForMultipleObjects :)
    А ожидание в цикле проверки флага действительно может быть и не таким уж страшным при условии, что конфликт за ресурсы возникает не часто и длится недолго. А если два потока одновременно работают на разных ядрах\процессорах, то покрутить цикл с несколько сотен тактов даже выгоднее, чем заставлять систему переключать потоки, тем самым еще более напрягая процессор ;)
     
  11. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    PS: Кстати сам вход\выход в\из крит.секции занимает немало времени. Например, у "классического" брмановского менеджера памяти (не FastMM) на выделение+освобождение памяти без юзанья крит.секции уходит ~пара сотен тактов, а с крит.секцией до тысячи и более. Поэтому вполне возможно, что ожидание на флаге, а не крит.секции, здесь было бы вполне целесообразным с учетом того, что сама вероятность наложения сотни критических тактов в двух потоках сама по себе мала (ну или комбинированный вариант - ждем пару сотен тактов в цикле, затем уходим в монастыР - крит.секцию :)
     
  12. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    leo
    Ну интерфейс и на GetMessage неплохо поспать может ;) отобразив при при этом на экране значки занятости где надо если это типа StrongDC. Или я делал прогу которая отображала физический объект, который можно было масштабировать и менять схему воздействия на него незовисимо от того уже рассчиталось его новое состояние или пока отображается старое с красным кружочком (сигнализирующем что расчёт не закончен) в уголке.

    ЗЫ: ещё статейка в тему :)
     
  13. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    локер из инферно
    Код (Text):
    1. ulong _tas(ulong *la){
    2.     ulong v;
    3.     _asm {
    4.         mov eax, la
    5.         mov ebx, 1
    6.         xchg    ebx, [eax]
    7.         mov v, ebx
    8.     }
    9.     return v;
    10. }
    11.  
    12. int
    13. canlock(rLock *l)
    14. {
    15.     return _tas(&l->val) == 0;
    16. }
    17.  
    18. void
    19. lock(rLock *l)
    20. {
    21.     int i;
    22.  
    23.     if(_tas(&l->val) == 0)
    24.         return;
    25.     for(i=0; i<100; i++){
    26.         if(_tas(&l->val) == 0)
    27.             return;
    28.         osyield();
    29.     }
    30.     for(i=1;; i++){
    31.         if(_tas(&l->val) == 0)
    32.             return;
    33.         osmillisleep(i*10);
    34.         if(i > 100){
    35.             osyield();
    36.             i = 1;
    37.         }
    38.     }
    39. }
    40.  
    41. void
    42. unlock(rLock *l)
    43. {
    44.     l->val = 0;
    45. }
    вообще-то это кусок алефовского рантайма (на алефе, но вроде все понятно). там вообще практически вся многопоточность и канальность не через ось зарелизена.
     
  14. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    _basmp_
    xchg - аппаратная привязка) Желательно ее не юзать :derisive:

    add: если кроссплатформенность важна
     
  15. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    TermoSINteZ
    Какбы.. А проц юзать можно? Шутка.

    Инферно/план9 имеют порты минимум на 5 платформ (больше. просто написалось 5). И кругом есть варианты реализации локеров/рфоркеров/канализаторов/болтунов/вытесняющей и кооперативной. Можно посмотреть если кросс нужен. Или вообще ядро потырить. Оно там маленькое. Инферновское хостовое, например. На выни и линях (кноппикс, убунту и асп) полет нормальный и крыльями машет одинаково.
     
  16. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    _basmp_
    Согласен. Я просто к тому, что проблема таких секций\локеров, как раз в том чтоб получить атомарный доступ к некоторой области памяти (так изначально было, а уже потом пошли области кода выполняемые непрерываемо и еще всякое..). И такой доступ, да вы правы, реализуется либо аппаратно, либо используя хитрые алгоритмы (эх, не помню названий - как вспомню, скажу, можно будет даже пообсуждать их, ибо тема очень тонкая, много нюансов), либо комбинируя и то и то.
     
  17. CrystalIC

    CrystalIC New Member

    Публикаций:
    0
    Регистрация:
    26 июл 2008
    Сообщения:
    500
    Можно без обьектов сделоть. Смысл в том, что в сервисах ожидания можно разрешить обработку апк. Тоесть остальные потоки входят в сервис ожидания, можно в NtDelayExecution. После того, как первый вошедший в критическую секцию поток из неё выйдет, он поставит в очередь остальным потокам событие. Они выйдут из ожидания. Это в общем, нужно продумоть.
     
  18. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    TermoSINteZ
    что нить в духе
    LOCK CMPXCHG DWORD PTR DS:[EDX+4],ECX
     
  19. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.552
    Адрес:
    Russia
    _basmp_
    Да.

    Вот кстати вспомнил алгоритм один, Алгоритм Деккера.
    Есть процесс А и процес B. Оба они одинаковые по части реализации алгоритма банкира, разница только в работе с переменными (вместо f2, будет f1, ну и сравниваться будет по другому . Но думаю вы поймете. Приведу примерный код первого процесса:
    Код (Text):
    1. int f = 1; int f1 = 0, f2 = 0;
    2. void A()
    3. {
    4. b: f1 = 1;
    5.     if (f2 != 0)
    6.         if (f == 2)
    7.         {
    8.             f1 = 0;
    9.             while (f2 != 0)
    10.                 ;
    11.             goto b;
    12.         }else
    13.         {
    14.             while (f2 != 0)
    15.                 ;
    16.         }
    17.     // здесь будет критическая секция
    18.     f1 = 0;
    19.     f = 2;
    20. }
    21.  
    22. void B()
    23. {
    24. b: f2 = 1;
    25.     if (f1 != 0)
    26.         if (f == 1)
    27.         {
    28.             f2 = 0;
    29.             while (f1 != 0)
    30.                 ;
    31.             goto b;
    32.         }else
    33.         {
    34.             while (f1 != 0)
    35.                 ;
    36.         }
    37.         // здесь будет критическая секция
    38.         f2 = 0;
    39.         f = 1;
    40. }
    Вроде бы правильно.
    f - указывает на то какой процесс будет исполнятся. Она исключает возможность бесконечного откладывания.
    f1, f2 - некие управляющие переменные.
     
  20. CrystalIC

    CrystalIC New Member

    Публикаций:
    0
    Регистрация:
    26 июл 2008
    Сообщения:
    500
    All
    В юзермоде спин-блокировки не катят)