На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! user posted image
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.

Соблюдайте общие правила форума

Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как запустить программу/файл? (и дождаться ее завершения)
5. Как перехватить API-функции, поставить hook? (перехват сообщений от мыши, клавиатуры - внедрение в удаленное адресное прстранство)
... (продолжение следует) ...

Внимание:
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки - бан.
Мат в разделе - бан на три месяца...

Полезные ссылки:
user posted image MSDN Library user posted image FAQ раздела user posted image Поиск по разделу user posted image Как правильно задавать вопросы


Выразить свое отношение к модераторам раздела можно здесь: user posted image Rouse_, user posted image Krid

Модераторы: Rouse_, Krid
Страницы: (3) 1 [2] 3  все  ( Перейти к последнему сообщению )  
> Sleep - что внутри?
    Synchronization Functions

    Critical section
    Slim Reader/Writer (SRW)

    и возможно
    One-time initialization
    Synchronization barrier
      Цитата Jin X @
      Сдаётся мне, что установка/ожидание event'а процесс тяжёлый... Хотя, могу ошибаться.
      Цитата shm @
      Во всяком случае что это процесс не тяжелее, чем sleep.
      Реально...
      Замерил скорость выполнения разного кода (в тактах), получилось вот что:
      ExpandedWrap disabled
        Холостой ход - 30-60
        cmpxchg (10 раз) - 60-120
        lock cmpxchg (10 раз) - 400-550
        SpinLoop 1024 циклов (cmp) - 26000-36000
        SpinLoop 1024 циклов (locked cmpxchg) - 50000-70000
         
        CreateEvent - 30000-50000
        Set/ResetEvent - 2000-4000
        CloseHandle - 4000-7000
        SwitchToThread - 2500-4000
        Sleep(0) - 3000-5000
        Sleep(1) - 160 тыс-3 млн
        WaitForSingleObject (signaled) - 2000-5000
        InitializeCriticalSectionAndSpinCount - 1800-2800
        InitializeCriticalSection - 1400-2400
        EnterCriticalSection (свободная) - 80-150
        EnterCriticalSection (рекурсивно) - 100-300
        DeleteCriticalSection - 500-1500
      CreateEvent хоть и долгая тема, но CreateEvent+Set/ResetEvent+WaitForSingleObject по любому шустрее...

      Добавлено
      Shaggy, гляну, thanx!
        Вопрос: есть ли гарантия, что WaitForSingleObject успеет сработать, если другой поток сделает SetEvent и CloseHandle подряд?
          Цитата Jin X @
          CreateEvent хоть и долгая тема

          Его нужно дернуть 1 раз при запуске и все.
          Цитата Jin X @
          есть ли гарантия, что WaitForSingleObject успеет сработать, если другой поток сделает SetEvent и CloseHandle подряд?

          А зачем так делать? Нет, нету гарантий. Если уж так надо, то после WaitForSingleObject и закрывай.
            Цитата shm @
            Его нужно дернуть 1 раз при запуске и все.
            Если сделать инициализацию 1 раз, значит нужно делать и удаление (типа DeleteCriticalSection), а я хочу сделать только Lock (Enter) и Unlock (Leave). Есть прикольные функции: WaitOnAddress и WakeByAddressSingle/WakeByAddressAll, жаль только, что существуют они в Windows 8+ (посему придётся комбинировать их и Event'ы для поддержки работы в Windows 7/XP).
              Jin X
              А свою написать?

              Мне не понравилось то что для критической секции нужна глобальная переменная. И я сделал вой вариант.

              ExpandedWrap disabled
                procedure TaskSwitch;
                var
                  Cis:PCriticalSection;
                  Status:Boolean;
                begin
                  Status:=GetIntStatus;
                  DisableInt;
                  CisBegin(Cis);
                    if TaskSetModeCmd.Lock=MUnLocked then
                       ExecuteCMD;
                    AlgTaskSwitch;
                  CisEnd(Cis);  
                  if Status=False then
                     EnableInt;
                end;

              Прикреплённый файлПрикреплённый файлUSynchronization.pas (9,15 Кбайт, скачиваний: 316)

              Добавлено
              PS. Код сырой и не тестированный. Просто как пример.
              Сообщение отредактировано: Pavia -
                Цитата Jin X @
                Если сделать инициализацию 1 раз, значит нужно делать и удаление (типа DeleteCriticalSection), а я хочу сделать только Lock (Enter) и Unlock (Leave)

                Это неэффективно. Неужели так лень пару лишних функций вызвать?
                Pavia, :wacko:
                Я не претендую на правильность, но все же.
                ExpandedWrap disabled
                  class CriticalSection: private Event
                  {
                      static void EnterSingle(CriticalSection *cs)
                      {
                          //std::cout << "EnterSingle" << std::endl;
                      }
                      static void LeaveSingle(CriticalSection *cs)
                      {
                          //std::cout << "LeaveSingle" << std::endl;
                      }
                      static void EnterMultitasking(CriticalSection *cs);
                      static void LeaveMultitasking(CriticalSection *cs);
                      static void EnterSmp(CriticalSection *cs);
                      static void LeaveSmp(CriticalSection *cs);
                      static void (*EnterProc)(CriticalSection *cs);
                      static void (*LeaveProc)(CriticalSection *cs);
                      volatile atom State;
                  //  atom LockCounter;
                      //locked
                      bool OnWaitBegin();
                      //bool OnSetStateSingle(Thread *);
                  public:
                      class Lock
                      {
                          CriticalSection *section;
                      public:
                          Lock(CriticalSection &cs)
                          {
                              section = &cs;
                              cs.enter();
                          }
                          ~Lock()
                          {
                              section->leave();
                          }
                      };
                      CriticalSection();
                      CriticalSection(bool Busy);
                      static void SetMutlitaskingMode()
                      {
                          EnterProc = &EnterMultitasking;
                          LeaveProc = &LeaveMultitasking;
                      }
                      static void SetSmpMode()
                      {
                          EnterProc = &EnterSmp;
                          LeaveProc = &LeaveSmp;
                      }
                      void enter()
                      {
                          EnterProc(this);
                      }
                      void leave()
                      {
                          LeaveProc(this);
                      }
                      bool IsLock() const
                      {
                          return (State != 0);
                      }
                      bool enter(DWORD Timeout);
                  };
                  //...
                  void CriticalSection::EnterSmp(CriticalSection *cs)
                  {
                      static const int max_spin_it = 1024;
                      unsigned int cpu_id, result;
                      int i;
                      cpu_id = GetCurrentCpuId() + 1;
                      result = CpuCompareAndSwapLock<volatile atom>(&cs->State, 0, cpu_id);
                      if(result == 0)
                          return;
                      else if(result != cpu_id)
                      {
                          for(i = 0; i < max_spin_it; i++)
                          {
                              if(cs->State == 0)
                              {
                                  cpu_id = GetCurrentCpuId() + 1;
                                  result = CpuCompareAndSwapLock<volatile atom>(&cs->State, 0, cpu_id);
                                  if(result == 0)
                                      return;
                              }
                              CpuPause();
                          }
                      }
                      cs->Wait();
                      cs->State = GetCurrentCpuId() + 1;
                  }
                   
                  void CriticalSection::LeaveSmp(CriticalSection *cs)
                  {
                      if(cs->HaveWaitingThreads())
                          cs->SetState();
                      else
                          cs->State = 0;
                  }
                  Pavia, what's that?
                  ExpandedWrap disabled
                    uses SysSupport, UMemoryManager, UMemoryMap;
                  :)
                  Добавлено
                  Цитата Pavia @
                  А свою написать?
                  Что именно написать своё?



                  shm, то ли неполный код, то ли... х/з.
                  GetCurrentCpuId - ?
                  CpuCompareAndSwapLock - ?
                  Wait - ?
                  SetState - ?
                  HaveWaitingThreads - ?
                  ...
                    shm
                    Цитата shm @
                    Pavia, :wacko:

                    Я хотел показать метод с патчингом.
                    В стеке страниц выделяем страницы. Страницы связаны в цепочку двойным списком.
                    В этих страницах хранятся адреса критических секций и её данные как то мьютекс.
                    При 1 заходе в критическую секцию адрес патчится на спинлок.

                    Для задачи Jin X:
                    Цитата Jin X @
                    Если сделать инициализацию 1 раз, значит нужно делать и удаление (типа DeleteCriticalSection), а я хочу сделать только Lock (Enter) и Unlock (Leave).

                    Можно сделать по аналогии патч который накладывает 5-байтовый NOP.
                    Сообщение отредактировано: Pavia -
                      Цитата Jin X @
                      shm, то ли неполный код, то ли... х/з.

                      Это для Pavia. Код не имеет никакого отношения к Win, как и код Pavia. Да простят нас админы за оффтоп.

                      Добавлено
                      Pavia, я у тебя не вижу усыпления потока. Без этого твои мьютексы это скорее спинлок, что крайне неэффективно в силу очевидных причин. Связанный список я у себя храню прямо в структуре потока, которую очень легко достать средствами TLS.
                      Сообщение отредактировано: shm -
                        Цитата Jin X @
                        Замерил скорость выполнения разного кода (в тактах), получилось вот что:
                        lock cmpxchg (10 раз) - 400-550
                        pinLoop 1024 циклов (locked cmpxchg) - 50000-70000

                        Это для случая, когда только один поток крутит спин-луп. Если же его будут крутить два и более потока одновременно, то эти цифирьки могут увеличиться в несколько раз (где-то от 3 до 5). Дело в том, что lock cmpxchg в любом случае производит запись в переменную (записывается либо новое, либо старое значение), поэтому соответствующая линейка кэша оказывается модифицированной, со всеми вытекающими последствиями синхронизации кэшей 1-2 уровня при многопоточном доступе. В случае одного потока модифицированная линейка остается в кэше L1 того ядра, на котором работает поток. А в случае двух и более потоков, она постоянно перебрасывается из L1 одного ядра в L1 другого через общий L3. Поэтому, чтобы избежать этих перебросов, в приведенных тобой примерах от Intel перед lock-обменом используется простое сравнение переменной "только на чтение". В этом случае, при наличии нескольких ожидающих потоков, они до снятия лока только читают линейку, не изменяя ее, и соотв-но она находится в неизменном shared состоянии в L1 этих потоков\ядер
                          Цитата leo @
                          Дело в том, что lock cmpxchg в любом случае производит запись в переменную (записывается либо новое, либо старое значение)
                          Я даже скажу, что lock вообще сильно тормозит процесс. Особенно если это будут делать одновременно несколько потоков...

                          Из Intel Instruction Set Reference (cmpxchg):
                          ExpandedWrap disabled
                            TEMP ← DEST
                            IF accumulator = TEMP
                              THEN
                                ZF ← 1;
                                DEST ← SRC;
                              ELSE
                                ZF ← 0;
                                accumulator ← TEMP;
                                DEST ← TEMP;
                            FI;
                          А вообще, непонятно, зачем cmpxchg делает запись во втором случае. Можно было бы обойтись и без неё.
                            Цитата Jin X @
                            Можно было бы обойтись и без неё.

                            Как?
                              Цитата shm @
                              Как?
                              А в чём её суть?

                              Temp := Dest
                              Dest := Temp
                                Быть может там прописана технология реализации. Т.е. TEMP - a'la кэш, а в конце команды обязательно надо что-то послать в память, ну а потому как совпадёт кэш с DEST, то не страшно его и послать обратно!?? :unsure:
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) 1 [2] 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0648 ]   [ 18 queries used ]   [ Generated: 29.03.24, 11:14 GMT ]